fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / svx / source / form / fmtextcontrolshell.cxx
blobc4d3f2b1047c1bf015cd8e365484903719b8d54a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include "fmprop.hrc"
22 #include "svx/fmresids.hrc"
23 #include "fmtextcontroldialogs.hxx"
24 #include "fmtextcontrolfeature.hxx"
25 #include "fmtextcontrolshell.hxx"
26 #include "editeng/crossedoutitem.hxx"
27 #include "svx/dialmgr.hxx"
28 #include "editeng/editeng.hxx"
29 #include "editeng/eeitem.hxx"
30 #include "svx/fmglob.hxx"
31 #include "editeng/scriptspaceitem.hxx"
32 #include "svx/svxids.hrc"
33 #include "editeng/udlnitem.hxx"
35 #include <com/sun/star/beans/XPropertySet.hpp>
36 #include <com/sun/star/awt/FontDescriptor.hpp>
37 #include <com/sun/star/frame/XDispatchProvider.hpp>
38 #include <com/sun/star/form/XForm.hpp>
39 #include <com/sun/star/container/XChild.hpp>
40 #include <com/sun/star/awt/XFocusListener.hpp>
41 #include <com/sun/star/awt/XMouseListener.hpp>
42 #include <com/sun/star/util/URLTransformer.hpp>
44 #include <comphelper/componentcontext.hxx>
45 #include <comphelper/processfactory.hxx>
46 #include <cppuhelper/implbase1.hxx>
47 #include <sfx2/app.hxx>
48 #include <sfx2/bindings.hxx>
49 #include <sfx2/dispatch.hxx>
50 #include <sfx2/msgpool.hxx>
51 #include <sfx2/objsh.hxx>
52 #include <sfx2/request.hxx>
53 #include <sfx2/sfxuno.hxx>
54 #include <sfx2/viewfrm.hxx>
55 #include <svl/eitem.hxx>
56 #include <svl/intitem.hxx>
57 #include <svl/itempool.hxx>
58 #include <svl/languageoptions.hxx>
59 #include <svtools/stringtransfer.hxx>
60 #include <svl/whiter.hxx>
61 #include <toolkit/helper/vclunohelper.hxx>
62 #include <tools/diagnose_ex.h>
63 #include <vcl/msgbox.hxx>
64 #include <vcl/outdev.hxx>
65 #include <osl/mutex.hxx>
67 #include <memory>
69 //........................................................................
70 namespace svx
72 //........................................................................
74 using namespace ::com::sun::star;
75 using namespace ::com::sun::star::uno;
76 using namespace ::com::sun::star::awt;
77 using namespace ::com::sun::star::form;
78 using namespace ::com::sun::star::form::runtime;
79 using namespace ::com::sun::star::lang;
80 using namespace ::com::sun::star::frame;
81 using namespace ::com::sun::star::util;
82 using namespace ::com::sun::star::beans;
83 using namespace ::com::sun::star::container;
85 //====================================================================
86 typedef sal_uInt16 WhichId;
88 //====================================================================
89 static SfxSlotId pTextControlSlots[] =
91 SID_CLIPBOARD_FORMAT_ITEMS,
92 SID_CUT,
93 SID_COPY,
94 SID_PASTE,
95 SID_SELECTALL,
96 // SID_ATTR_TABSTOP, /* 2 */
97 SID_ATTR_CHAR_FONT,
98 SID_ATTR_CHAR_POSTURE,
99 SID_ATTR_CHAR_WEIGHT,
100 SID_ATTR_CHAR_SHADOWED,
101 SID_ATTR_CHAR_WORDLINEMODE,
102 SID_ATTR_CHAR_CONTOUR,
103 SID_ATTR_CHAR_STRIKEOUT,
104 SID_ATTR_CHAR_UNDERLINE,
105 SID_ATTR_CHAR_FONTHEIGHT,
106 SID_ATTR_CHAR_COLOR,
107 SID_ATTR_CHAR_KERNING,
108 SID_ATTR_CHAR_LANGUAGE, /* 20 */
109 SID_ATTR_CHAR_ESCAPEMENT,
110 SID_ATTR_PARA_ADJUST, /* 28 */
111 SID_ATTR_PARA_ADJUST_LEFT,
112 SID_ATTR_PARA_ADJUST_RIGHT,
113 SID_ATTR_PARA_ADJUST_CENTER,
114 SID_ATTR_PARA_ADJUST_BLOCK,
115 SID_ATTR_PARA_LINESPACE, /* 33 */
116 SID_ATTR_PARA_LINESPACE_10,
117 SID_ATTR_PARA_LINESPACE_15,
118 SID_ATTR_PARA_LINESPACE_20,
119 SID_ATTR_LRSPACE, /* 48 */
120 SID_ATTR_ULSPACE, /* 49 */
121 SID_ATTR_CHAR_AUTOKERN,
122 SID_SET_SUPER_SCRIPT,
123 SID_SET_SUB_SCRIPT,
124 SID_CHAR_DLG,
125 SID_PARA_DLG,
126 // SID_TEXTDIRECTION_LEFT_TO_RIGHT, /* 907 */
127 // SID_TEXTDIRECTION_TOP_TO_BOTTOM,
128 SID_ATTR_CHAR_SCALEWIDTH, /* 911 */
129 SID_ATTR_CHAR_RELIEF,
130 SID_ATTR_PARA_LEFT_TO_RIGHT, /* 950 */
131 SID_ATTR_PARA_RIGHT_TO_LEFT,
132 SID_ATTR_CHAR_OVERLINE,
136 // slots which we are not responsible for on the SfxShell level, but
137 // need to handle during the "paragraph attributes" and/or "character
138 // attributes" dialogs
139 static SfxSlotId pDialogSlots[] =
141 SID_ATTR_TABSTOP,
142 SID_ATTR_PARA_HANGPUNCTUATION,
143 SID_ATTR_PARA_FORBIDDEN_RULES,
144 SID_ATTR_PARA_SCRIPTSPACE,
145 SID_ATTR_CHAR_LATIN_LANGUAGE,
146 SID_ATTR_CHAR_CJK_LANGUAGE,
147 SID_ATTR_CHAR_CTL_LANGUAGE,
148 SID_ATTR_CHAR_LATIN_FONT,
149 SID_ATTR_CHAR_CJK_FONT,
150 SID_ATTR_CHAR_CTL_FONT,
151 SID_ATTR_CHAR_LATIN_FONTHEIGHT,
152 SID_ATTR_CHAR_CJK_FONTHEIGHT,
153 SID_ATTR_CHAR_CTL_FONTHEIGHT,
154 SID_ATTR_CHAR_LATIN_WEIGHT,
155 SID_ATTR_CHAR_CJK_WEIGHT,
156 SID_ATTR_CHAR_CTL_WEIGHT,
157 SID_ATTR_CHAR_LATIN_POSTURE,
158 SID_ATTR_CHAR_CJK_POSTURE,
159 SID_ATTR_CHAR_CTL_POSTURE,
160 SID_ATTR_CHAR_EMPHASISMARK,
164 //====================================================================
165 //= FmFocusListenerAdapter
166 //====================================================================
167 typedef ::cppu::WeakImplHelper1 < XFocusListener
168 > FmFocusListenerAdapter_Base;
169 class FmFocusListenerAdapter : public FmFocusListenerAdapter_Base
171 private:
172 IFocusObserver* m_pObserver;
173 Reference< XWindow > m_xWindow;
175 public:
176 FmFocusListenerAdapter( const Reference< XControl >& _rxControl, IFocusObserver* _pObserver );
178 // clean up the instance
179 void dispose();
181 protected:
182 ~FmFocusListenerAdapter();
184 protected:
185 virtual void SAL_CALL focusGained( const FocusEvent& e ) throw (RuntimeException);
186 virtual void SAL_CALL focusLost( const FocusEvent& e ) throw (RuntimeException);
187 virtual void SAL_CALL disposing( const EventObject& Source ) throw (RuntimeException);
190 //--------------------------------------------------------------------
191 DBG_NAME( FmFocusListenerAdapter )
192 //--------------------------------------------------------------------
193 FmFocusListenerAdapter::FmFocusListenerAdapter( const Reference< XControl >& _rxControl, IFocusObserver* _pObserver )
194 :m_pObserver( _pObserver )
195 ,m_xWindow( _rxControl, UNO_QUERY )
197 DBG_CTOR( FmFocusListenerAdapter, NULL );
199 DBG_ASSERT( m_xWindow.is(), "FmFocusListenerAdapter::FmFocusListenerAdapter: invalid control!" );
200 osl_atomic_increment( &m_refCount );
204 if ( m_xWindow.is() )
205 m_xWindow->addFocusListener( this );
207 catch( const Exception& )
209 DBG_UNHANDLED_EXCEPTION();
212 osl_atomic_decrement( &m_refCount );
215 //--------------------------------------------------------------------
216 FmFocusListenerAdapter::~FmFocusListenerAdapter()
218 acquire();
219 dispose();
221 DBG_DTOR( FmFocusListenerAdapter, NULL );
224 //--------------------------------------------------------------------
225 void FmFocusListenerAdapter::dispose()
227 if ( m_xWindow.is() )
229 m_xWindow->removeFocusListener( this );
230 m_xWindow.clear();
234 //--------------------------------------------------------------------
235 void SAL_CALL FmFocusListenerAdapter::focusGained( const FocusEvent& e ) throw (RuntimeException)
237 if ( m_pObserver )
238 m_pObserver->focusGained( e );
241 //--------------------------------------------------------------------
242 void SAL_CALL FmFocusListenerAdapter::focusLost( const FocusEvent& e ) throw (RuntimeException)
244 if ( m_pObserver )
245 m_pObserver->focusLost( e );
248 //--------------------------------------------------------------------
249 void SAL_CALL FmFocusListenerAdapter::disposing( const EventObject& Source ) throw (RuntimeException)
251 (void)Source;
252 DBG_ASSERT( Source.Source == m_xWindow, "FmFocusListenerAdapter::disposing: where did this come from?" );
253 m_xWindow.clear();
256 //====================================================================
257 //= FmMouseListenerAdapter
258 //====================================================================
259 typedef ::cppu::WeakImplHelper1 < XMouseListener
260 > FmMouseListenerAdapter_Base;
261 class FmMouseListenerAdapter : public FmMouseListenerAdapter_Base
263 private:
264 IContextRequestObserver* m_pObserver;
265 Reference< XWindow > m_xWindow;
267 public:
268 FmMouseListenerAdapter( const Reference< XControl >& _rxControl, IContextRequestObserver* _pObserver );
270 // clean up the instance
271 void dispose();
273 protected:
274 ~FmMouseListenerAdapter();
276 protected:
277 virtual void SAL_CALL mousePressed( const awt::MouseEvent& e ) throw (RuntimeException);
278 virtual void SAL_CALL mouseReleased( const awt::MouseEvent& e ) throw (RuntimeException);
279 virtual void SAL_CALL mouseEntered( const awt::MouseEvent& e ) throw (RuntimeException);
280 virtual void SAL_CALL mouseExited( const awt::MouseEvent& e ) throw (RuntimeException);
281 virtual void SAL_CALL disposing( const EventObject& Source ) throw (RuntimeException);
284 //====================================================================
285 //= FmMouseListenerAdapter
286 //====================================================================
287 //--------------------------------------------------------------------
288 DBG_NAME( FmMouseListenerAdapter )
289 //--------------------------------------------------------------------
290 FmMouseListenerAdapter::FmMouseListenerAdapter( const Reference< XControl >& _rxControl, IContextRequestObserver* _pObserver )
291 :m_pObserver( _pObserver )
292 ,m_xWindow( _rxControl, UNO_QUERY )
294 DBG_CTOR( FmMouseListenerAdapter, NULL );
296 DBG_ASSERT( m_xWindow.is(), "FmMouseListenerAdapter::FmMouseListenerAdapter: invalid control!" );
297 osl_atomic_increment( &m_refCount );
301 if ( m_xWindow.is() )
302 m_xWindow->addMouseListener( this );
304 catch( const Exception& )
306 DBG_UNHANDLED_EXCEPTION();
309 osl_atomic_decrement( &m_refCount );
312 //--------------------------------------------------------------------
313 FmMouseListenerAdapter::~FmMouseListenerAdapter()
315 acquire();
316 dispose();
318 DBG_DTOR( FmMouseListenerAdapter, NULL );
321 //--------------------------------------------------------------------
322 void FmMouseListenerAdapter::dispose()
324 if ( m_xWindow.is() )
326 m_xWindow->removeMouseListener( this );
327 m_xWindow.clear();
331 //--------------------------------------------------------------------
332 void SAL_CALL FmMouseListenerAdapter::mousePressed( const awt::MouseEvent& _rEvent ) throw (::com::sun::star::uno::RuntimeException)
334 SolarMutexGuard aGuard;
335 // is this a request for a context menu?
336 if ( _rEvent.PopupTrigger )
338 if ( m_pObserver )
339 m_pObserver->contextMenuRequested( _rEvent );
343 //--------------------------------------------------------------------
344 void SAL_CALL FmMouseListenerAdapter::mouseReleased( const awt::MouseEvent& /*e*/ ) throw (::com::sun::star::uno::RuntimeException)
346 // not interested in
349 //--------------------------------------------------------------------
350 void SAL_CALL FmMouseListenerAdapter::mouseEntered( const awt::MouseEvent& /*e*/ ) throw (::com::sun::star::uno::RuntimeException)
352 // not interested in
355 //--------------------------------------------------------------------
356 void SAL_CALL FmMouseListenerAdapter::mouseExited( const awt::MouseEvent& /*e*/ ) throw (::com::sun::star::uno::RuntimeException)
358 // not interested in
361 //--------------------------------------------------------------------
362 void SAL_CALL FmMouseListenerAdapter::disposing( const EventObject& Source ) throw (RuntimeException)
364 (void)Source;
365 DBG_ASSERT( Source.Source == m_xWindow, "FmMouseListenerAdapter::disposing: where did this come from?" );
366 m_xWindow.clear();
369 //====================================================================
370 //= FmTextControlShell
371 //====================================================================
372 //------------------------------------------------------------------------
373 namespace
375 //....................................................................
376 void lcl_translateUnoStateToItem( SfxSlotId _nSlot, const Any& _rUnoState, SfxItemSet& _rSet )
378 WhichId nWhich = _rSet.GetPool()->GetWhich( _nSlot );
379 if ( !_rUnoState.hasValue() )
381 if ( ( _nSlot != SID_CUT )
382 && ( _nSlot != SID_COPY )
383 && ( _nSlot != SID_PASTE )
386 _rSet.InvalidateItem( nWhich );
389 else
391 switch ( _rUnoState.getValueType().getTypeClass() )
393 case TypeClass_BOOLEAN:
395 sal_Bool bState = sal_False;
396 _rUnoState >>= bState;
397 if ( _nSlot == SID_ATTR_PARA_SCRIPTSPACE )
398 _rSet.Put( SvxScriptSpaceItem( bState, nWhich ) );
399 else
400 _rSet.Put( SfxBoolItem( nWhich, bState ) );
402 break;
404 default:
406 Sequence< PropertyValue > aComplexState;
407 if ( _rUnoState >>= aComplexState )
409 if ( !aComplexState.getLength() )
410 _rSet.InvalidateItem( nWhich );
411 else
413 SfxAllItemSet aAllItems( _rSet );
414 TransformParameters( _nSlot, aComplexState, aAllItems );
415 const SfxPoolItem* pTransformed = aAllItems.GetItem( nWhich );
416 OSL_ENSURE( pTransformed, "lcl_translateUnoStateToItem: non-empty parameter sequence leading to empty item?" );
417 if ( pTransformed )
418 _rSet.Put( *pTransformed );
419 else
420 _rSet.InvalidateItem( nWhich );
423 else
425 OSL_FAIL( "lcl_translateUnoStateToItem: invalid state!" );
432 //....................................................................
433 OUString lcl_getUnoSlotName( SfxApplication&, SfxSlotId _nSlotId )
435 OUString sSlotUnoName;
437 SfxSlotPool& rSlotPool = SfxSlotPool::GetSlotPool( NULL );
438 const SfxSlot* pSlot = rSlotPool.GetSlot( _nSlotId );
440 const sal_Char* pAsciiUnoName = NULL;
441 if ( pSlot )
443 pAsciiUnoName = pSlot->GetUnoName();
445 else
447 // some hard-coded slots, which do not have a UNO name at SFX level, but which
448 // we nevertheless need to transport via UNO mechanisms, so we need a name
449 switch ( _nSlotId )
451 case SID_ATTR_PARA_HANGPUNCTUATION: pAsciiUnoName = "AllowHangingPunctuation"; break;
452 case SID_ATTR_PARA_FORBIDDEN_RULES: pAsciiUnoName = "ApplyForbiddenCharacterRules"; break;
453 case SID_ATTR_PARA_SCRIPTSPACE: pAsciiUnoName = "UseScriptSpacing"; break;
457 if ( pAsciiUnoName )
459 sSlotUnoName = OUString( ".uno:" );
460 sSlotUnoName += OUString::createFromAscii( pAsciiUnoName );
462 #if OSL_DEBUG_LEVEL > 0
463 else
465 OString sMessage( "lcl_getUnoSlotName: invalid slot id, or invalid slot, or no UNO name!\n" );
466 sMessage += "(slot id: ";
467 sMessage += OString::valueOf( (sal_Int32)_nSlotId );
468 sMessage += ")";
469 OSL_FAIL( sMessage.getStr() );
471 #endif
472 return sSlotUnoName;
475 //....................................................................
476 bool lcl_determineReadOnly( const Reference< XControl >& _rxControl )
478 bool bIsReadOnlyModel = true;
481 Reference< XPropertySet > xModelProps;
482 if ( _rxControl.is() )
483 xModelProps = xModelProps.query( _rxControl->getModel() );
484 Reference< XPropertySetInfo > xModelPropInfo;
485 if ( xModelProps.is() )
486 xModelPropInfo = xModelProps->getPropertySetInfo();
488 if ( !xModelPropInfo.is() || !xModelPropInfo->hasPropertyByName( FM_PROP_READONLY ) )
489 bIsReadOnlyModel = true;
490 else
492 sal_Bool bReadOnly = sal_True;
493 xModelProps->getPropertyValue( FM_PROP_READONLY ) >>= bReadOnly;
494 bIsReadOnlyModel = bReadOnly;
497 catch( const Exception& )
499 DBG_UNHANDLED_EXCEPTION();
501 return bIsReadOnlyModel;
504 //....................................................................
505 static Window* lcl_getWindow( const Reference< XControl >& _rxControl )
507 Window* pWindow = NULL;
510 Reference< XWindowPeer > xControlPeer;
511 if ( _rxControl.is() )
512 xControlPeer = _rxControl->getPeer();
513 if ( xControlPeer.is() )
514 pWindow = VCLUnoHelper::GetWindow( xControlPeer );
516 catch( const Exception& )
518 DBG_UNHANDLED_EXCEPTION();
521 return pWindow;
524 //....................................................................
525 bool lcl_isRichText( const Reference< XControl >& _rxControl )
527 if ( !_rxControl.is() )
528 return false;
530 bool bIsRichText = false;
533 Reference< XPropertySet > xModelProps( _rxControl->getModel(), UNO_QUERY );
534 Reference< XPropertySetInfo > xPSI;
535 if ( xModelProps.is() )
536 xPSI = xModelProps->getPropertySetInfo();
537 OUString sRichTextPropertyName = OUString( "RichText" );
538 if ( xPSI.is() && xPSI->hasPropertyByName( sRichTextPropertyName ) )
540 OSL_VERIFY( xModelProps->getPropertyValue( sRichTextPropertyName ) >>= bIsRichText );
543 catch( const Exception& )
545 DBG_UNHANDLED_EXCEPTION();
547 return bIsRichText;
551 //------------------------------------------------------------------------
552 FmTextControlShell::FmTextControlShell( SfxViewFrame* _pFrame )
553 :m_bActiveControl( false )
554 ,m_bActiveControlIsReadOnly( true )
555 ,m_bActiveControlIsRichText( false )
556 ,m_pViewFrame( _pFrame )
557 ,m_rBindings( _pFrame->GetBindings() )
558 ,m_bNeedClipboardInvalidation( true )
560 m_aClipboardInvalidation.SetTimeoutHdl( LINK( this, FmTextControlShell, OnInvalidateClipboard ) );
561 m_aClipboardInvalidation.SetTimeout( 200 );
564 //------------------------------------------------------------------------
565 FmTextControlShell::~FmTextControlShell()
567 dispose();
570 //------------------------------------------------------------------------
571 IMPL_LINK( FmTextControlShell, OnInvalidateClipboard, void*, /*_pNotInterestedIn*/ )
573 if ( m_bNeedClipboardInvalidation )
575 OSL_TRACE( "FmTextControlShell::ClipBoard: invalidating clipboard slots" );
576 m_rBindings.Invalidate( SID_CUT );
577 m_rBindings.Invalidate( SID_COPY );
578 m_rBindings.Invalidate( SID_PASTE );
579 m_bNeedClipboardInvalidation = false;
581 return 0L;
584 //------------------------------------------------------------------------
585 void FmTextControlShell::transferFeatureStatesToItemSet( ControlFeatures& _rDispatchers, SfxAllItemSet& _rSet, bool _bTranslateLatin )
587 SfxItemPool& rPool = *_rSet.GetPool();
589 for ( ControlFeatures::const_iterator aFeature = _rDispatchers.begin();
590 aFeature != _rDispatchers.end();
591 ++aFeature
594 SfxSlotId nSlotId( aFeature->first );
595 #if OSL_DEBUG_LEVEL > 0
596 OUString sUnoSlotName;
597 if ( SFX_APP() )
598 sUnoSlotName = lcl_getUnoSlotName( *SFX_APP(), nSlotId );
599 else
600 sUnoSlotName = OUString( "<unknown>" );
601 OString sUnoSlotNameAscii( "\"" );
602 sUnoSlotNameAscii += OString( sUnoSlotName.getStr(), sUnoSlotName.getLength(), RTL_TEXTENCODING_ASCII_US );
603 sUnoSlotNameAscii += "\"";
604 #endif
606 if ( _bTranslateLatin )
608 // A rich text control offers a dispatcher for the "Font" slot/feature.
609 // Sadly, the semantics of the dispatches is that the feature "Font" depends
610 // on the current cursor position: If it's on latin text, it's the "latin font"
611 // which is set up at the control. If it's on CJK text, it's the "CJK font", and
612 // aequivalent for "CTL font".
613 // The same holds for some other font related features/slots.
614 // Thus, we have separate dispatches for "Latin Font", "Latin Font Size", etc,
615 // which are only "virtual", in a sense that there exist no item with this id.
616 // So when we encounter such a dispatcher for, say, "Latin Font", we need to
617 // put an item into the set which has the "Font" id.
619 switch ( nSlotId )
621 case SID_ATTR_CHAR_LATIN_FONT: nSlotId = SID_ATTR_CHAR_FONT; break;
622 case SID_ATTR_CHAR_LATIN_FONTHEIGHT:nSlotId = SID_ATTR_CHAR_FONTHEIGHT; break;
623 case SID_ATTR_CHAR_LATIN_LANGUAGE: nSlotId = SID_ATTR_CHAR_LANGUAGE; break;
624 case SID_ATTR_CHAR_LATIN_POSTURE: nSlotId = SID_ATTR_CHAR_POSTURE; break;
625 case SID_ATTR_CHAR_LATIN_WEIGHT: nSlotId = SID_ATTR_CHAR_WEIGHT; break;
629 WhichId nWhich = rPool.GetWhich( nSlotId );
630 bool bIsInPool = rPool.IsInRange( nWhich );
631 if ( bIsInPool )
633 #if OSL_DEBUG_LEVEL > 0
634 bool bFeatureIsEnabled = aFeature->second->isFeatureEnabled();
635 OString sMessage( "FmTextControlShell::transferFeatureStatesToItemSet: found a feature state for " );
636 sMessage += sUnoSlotNameAscii;
637 if ( !bFeatureIsEnabled )
638 sMessage += " (disabled)";
639 OSL_TRACE( "%s", sMessage.getStr() );
640 #endif
642 lcl_translateUnoStateToItem( nSlotId, aFeature->second->getFeatureState(), _rSet );
644 #if OSL_DEBUG_LEVEL > 0
645 else
647 OString sMessage( "FmTextControlShell::transferFeatureStatesToItemSet: found a feature state for " );
648 sMessage += sUnoSlotNameAscii;
649 sMessage += ", but could not translate it into an item!";
650 OSL_TRACE( "%s", sMessage.getStr() );
652 #endif
656 //------------------------------------------------------------------------
657 void FmTextControlShell::executeAttributeDialog( AttributeSet _eSet, SfxRequest& _rReq )
659 const SvxFontListItem* pFontList = PTR_CAST( SvxFontListItem, m_pViewFrame->GetObjectShell()->GetItem( SID_ATTR_CHAR_FONTLIST ) );
660 DBG_ASSERT( pFontList, "FmTextControlShell::executeAttributeDialog: no font list item!" );
661 if ( !pFontList )
662 return;
664 SfxItemPool* pPool = EditEngine::CreatePool();
665 pPool->FreezeIdRanges();
666 ::std::auto_ptr< SfxItemSet > pPureItems( new SfxItemSet( *pPool ) );
668 // put the current states of the items into the set
669 ::std::auto_ptr< SfxAllItemSet > pCurrentItems( new SfxAllItemSet( *pPureItems ) );
670 transferFeatureStatesToItemSet( m_aControlFeatures, *pCurrentItems );
672 // additional items, which we are not responsible for at the SfxShell level,
673 // but which need to be forwarded to the dialog, anyway
674 ControlFeatures aAdditionalFestures;
675 fillFeatureDispatchers( m_xActiveControl, pDialogSlots, aAdditionalFestures );
676 transferFeatureStatesToItemSet( aAdditionalFestures, *pCurrentItems, true );
678 ::std::auto_ptr< SfxTabDialog > pDialog ( _eSet == eCharAttribs
679 ? static_cast< SfxTabDialog* >( new TextControlCharAttribDialog( NULL, *pCurrentItems, *pFontList ) )
680 : static_cast< SfxTabDialog* >( new TextControlParaAttribDialog( NULL, *pCurrentItems ) ) );
681 if ( RET_OK == pDialog->Execute() )
683 const SfxItemSet& rModifiedItems = *pDialog->GetOutputItemSet();
684 for ( WhichId nWhich = pPool->GetFirstWhich(); nWhich <= pPool->GetLastWhich(); ++nWhich )
686 if ( rModifiedItems.GetItemState( nWhich ) == SFX_ITEM_SET )
688 SfxSlotId nSlotForItemSet = pPool->GetSlotId( nWhich );
689 const SfxPoolItem* pModifiedItem = rModifiedItems.GetItem( nWhich );
692 SfxSlotId nSlotForDispatcher = nSlotForItemSet;
693 switch ( nSlotForDispatcher )
695 case SID_ATTR_CHAR_FONT: nSlotForDispatcher = SID_ATTR_CHAR_LATIN_FONT; break;
696 case SID_ATTR_CHAR_FONTHEIGHT:nSlotForDispatcher = SID_ATTR_CHAR_LATIN_FONTHEIGHT; break;
697 case SID_ATTR_CHAR_LANGUAGE: nSlotForDispatcher = SID_ATTR_CHAR_LATIN_LANGUAGE; break;
698 case SID_ATTR_CHAR_POSTURE: nSlotForDispatcher = SID_ATTR_CHAR_LATIN_POSTURE; break;
699 case SID_ATTR_CHAR_WEIGHT: nSlotForDispatcher = SID_ATTR_CHAR_LATIN_WEIGHT; break;
702 // do we already have a dispatcher for this slot/feature?
703 ControlFeatures::const_iterator aFeaturePos = m_aControlFeatures.find( nSlotForDispatcher );
704 bool bFound = aFeaturePos != m_aControlFeatures.end( );
706 if ( !bFound )
708 aFeaturePos = aAdditionalFestures.find( nSlotForDispatcher );
709 bFound = aFeaturePos != aAdditionalFestures.end( );
712 if ( bFound )
714 Sequence< PropertyValue > aArgs;
715 // temporarily put the modified item into a "clean" set,
716 // and let TransformItems calc the respective UNO parameters
717 pPureItems->Put( *pModifiedItem );
718 TransformItems( nSlotForItemSet, *pPureItems, aArgs );
719 pPureItems->ClearItem( nWhich );
721 if ( ( nSlotForItemSet == SID_ATTR_PARA_HANGPUNCTUATION )
722 || ( nSlotForItemSet == SID_ATTR_PARA_FORBIDDEN_RULES )
723 || ( nSlotForItemSet == SID_ATTR_PARA_SCRIPTSPACE )
726 // these are no UNO slots, they need special handling since TransformItems cannot
727 // handle them
728 DBG_ASSERT( aArgs.getLength() == 0, "FmTextControlShell::executeAttributeDialog: these are no UNO slots - are they?" );
730 const SfxBoolItem* pBoolItem = PTR_CAST( SfxBoolItem, pModifiedItem );
731 DBG_ASSERT( pBoolItem, "FmTextControlShell::executeAttributeDialog: no bool item?!" );
732 if ( pBoolItem )
734 aArgs.realloc( 1 );
735 aArgs[ 0 ].Name = OUString( "Enable" );
736 aArgs[ 0 ].Value <<= (sal_Bool)pBoolItem->GetValue();
740 // dispatch this
741 aFeaturePos->second->dispatch( aArgs );
743 #if OSL_DEBUG_LEVEL > 0
744 else
746 OString sError( "FmTextControShell::executeAttributeDialog: Could not handle the following item:" );
747 sError += "\n SlotID: "; sError += OString::valueOf( (sal_Int32)nSlotForItemSet );
748 sError += "\n WhichID: "; sError += OString::valueOf( (sal_Int32)nWhich );
749 sError += "\n UNO name: ";
751 OUString sUnoSlotName = lcl_getUnoSlotName( *SFX_APP(), nSlotForItemSet );
752 if ( !sUnoSlotName.isEmpty() )
753 sError += OString( sUnoSlotName.getStr(), sUnoSlotName.getLength(), RTL_TEXTENCODING_ASCII_US );
754 else
755 sError += "unknown (no SfxSlot)";
756 OSL_FAIL( sError.getStr() );
758 #endif
761 _rReq.Done( rModifiedItems );
764 pDialog.reset();
765 pCurrentItems.reset();
766 pPureItems.reset();
767 SfxItemPool::Free(pPool);
770 //------------------------------------------------------------------------
771 bool FmTextControlShell::executeSelectAll( )
775 if ( m_xActiveTextComponent.is() )
777 sal_Int32 nTextLen = m_xActiveTextComponent->getText().getLength();
778 m_xActiveTextComponent->setSelection( awt::Selection( 0, nTextLen ) );
779 return true;
782 catch( const Exception& )
784 DBG_UNHANDLED_EXCEPTION();
786 return false; // not handled
789 //------------------------------------------------------------------------
790 bool FmTextControlShell::executeClipboardSlot( SfxSlotId _nSlot )
794 if ( m_xActiveTextComponent.is() )
796 switch ( _nSlot )
798 case SID_COPY:
799 case SID_CUT:
801 OUString sSelectedText( m_xActiveTextComponent->getSelectedText() );
802 ::svt::OStringTransfer::CopyString( sSelectedText, lcl_getWindow( m_xActiveControl ) );
803 if ( SID_CUT == _nSlot )
805 awt::Selection aSelection( m_xActiveTextComponent->getSelection() );
806 m_xActiveTextComponent->insertText( aSelection, OUString() );
809 break;
810 case SID_PASTE:
812 OUString sClipboardContent;
813 OSL_VERIFY( ::svt::OStringTransfer::PasteString( sClipboardContent, lcl_getWindow( m_xActiveControl ) ) );
814 awt::Selection aSelection( m_xActiveTextComponent->getSelection() );
815 m_xActiveTextComponent->insertText( aSelection, sClipboardContent );
817 break;
818 default:
819 OSL_FAIL( "FmTextControlShell::executeClipboardSlot: invalid slot!" );
821 return true;
824 catch( const Exception& )
826 DBG_UNHANDLED_EXCEPTION();
828 return false; // not handled
831 //------------------------------------------------------------------------
832 void FmTextControlShell::ExecuteTextAttribute( SfxRequest& _rReq )
834 SfxSlotId nSlot = _rReq.GetSlot();
836 ControlFeatures::const_iterator aFeaturePos = m_aControlFeatures.find( nSlot );
837 if ( aFeaturePos == m_aControlFeatures.end() )
839 // special slots
840 switch ( nSlot )
842 case SID_CHAR_DLG:
843 executeAttributeDialog( eCharAttribs, _rReq );
844 break;
846 case SID_PARA_DLG:
847 executeAttributeDialog( eParaAttribs, _rReq );
848 break;
850 case SID_SELECTALL:
851 executeSelectAll();
852 break;
854 case SID_CUT:
855 case SID_COPY:
856 case SID_PASTE:
857 executeClipboardSlot( nSlot );
858 break;
860 default:
861 DBG_ASSERT( aFeaturePos != m_aControlFeatures.end(), "FmTextControShell::ExecuteTextAttribute: I have no such dispatcher, and cannot handle it at all!" );
862 return;
865 else
867 // slots which are dispatched to the control
869 switch ( nSlot )
871 case SID_ATTR_CHAR_STRIKEOUT:
872 case SID_ATTR_CHAR_UNDERLINE:
873 case SID_ATTR_CHAR_OVERLINE:
875 SfxItemSet aToggled( *_rReq.GetArgs() );
877 lcl_translateUnoStateToItem( nSlot, aFeaturePos->second->getFeatureState(), aToggled );
878 WhichId nWhich = aToggled.GetPool()->GetWhich( nSlot );
879 const SfxPoolItem* pItem = aToggled.GetItem( nWhich );
880 if ( ( SID_ATTR_CHAR_UNDERLINE == nSlot ) || ( SID_ATTR_CHAR_OVERLINE == nSlot ) )
882 const SvxOverlineItem* pTextLine = PTR_CAST( SvxOverlineItem, pItem );
883 DBG_ASSERT( pTextLine, "FmTextControlShell::ExecuteTextAttribute: ooops - no underline/overline item!" );
884 if ( pTextLine )
886 FontUnderline eTL = pTextLine->GetLineStyle();
887 if ( SID_ATTR_CHAR_UNDERLINE == nSlot ) {
888 aToggled.Put( SvxUnderlineItem( eTL == UNDERLINE_SINGLE ? UNDERLINE_NONE : UNDERLINE_SINGLE, nWhich ) );
889 } else {
890 aToggled.Put( SvxOverlineItem( eTL == UNDERLINE_SINGLE ? UNDERLINE_NONE : UNDERLINE_SINGLE, nWhich ) );
894 else
896 const SvxCrossedOutItem* pCrossedOut = PTR_CAST( SvxCrossedOutItem, pItem );
897 DBG_ASSERT( pCrossedOut, "FmTextControlShell::ExecuteTextAttribute: ooops - no CrossedOut item!" );
898 if ( pCrossedOut )
900 FontStrikeout eFS = pCrossedOut->GetStrikeout();
901 aToggled.Put( SvxCrossedOutItem( eFS == STRIKEOUT_SINGLE ? STRIKEOUT_NONE : STRIKEOUT_SINGLE, nWhich ) );
905 Sequence< PropertyValue > aArguments;
906 TransformItems( nSlot, aToggled, aArguments );
907 aFeaturePos->second->dispatch( aArguments );
909 break;
911 case SID_ATTR_CHAR_FONTHEIGHT:
912 case SID_ATTR_CHAR_FONT:
913 case SID_ATTR_CHAR_POSTURE:
914 case SID_ATTR_CHAR_WEIGHT:
915 case SID_ATTR_CHAR_SHADOWED:
916 case SID_ATTR_CHAR_CONTOUR:
917 case SID_SET_SUPER_SCRIPT:
918 case SID_SET_SUB_SCRIPT:
920 const SfxItemSet* pArgs = _rReq.GetArgs();
921 Sequence< PropertyValue > aArgs;
922 if ( pArgs )
923 TransformItems( nSlot, *pArgs, aArgs );
924 aFeaturePos->second->dispatch( aArgs );
926 break;
928 default:
929 if ( aFeaturePos->second->isFeatureEnabled() )
930 aFeaturePos->second->dispatch();
931 break;
934 _rReq.Done();
937 //------------------------------------------------------------------------
938 void FmTextControlShell::GetTextAttributeState( SfxItemSet& _rSet )
940 SfxWhichIter aIter( _rSet );
941 sal_uInt16 nSlot = aIter.FirstWhich();
942 while ( nSlot )
944 if ( ( nSlot == SID_ATTR_PARA_LEFT_TO_RIGHT )
945 || ( nSlot == SID_ATTR_PARA_RIGHT_TO_LEFT )
948 if ( !SvtLanguageOptions().IsCTLFontEnabled() )
950 _rSet.DisableItem( nSlot );
951 nSlot = aIter.NextWhich();
952 continue;
956 ControlFeatures::const_iterator aFeaturePos = m_aControlFeatures.find( nSlot );
957 if ( aFeaturePos != m_aControlFeatures.end() )
959 if ( aFeaturePos->second->isFeatureEnabled() )
960 lcl_translateUnoStateToItem( nSlot, aFeaturePos->second->getFeatureState(), _rSet );
961 else
962 _rSet.DisableItem( nSlot );
964 else
966 bool bDisable = false;
968 bool bNeedWriteableControl = false;
969 bool bNeedTextComponent = false;
970 bool bNeedSelection = false;
972 switch ( nSlot )
974 case SID_CHAR_DLG:
975 case SID_PARA_DLG:
976 bDisable |= m_aControlFeatures.empty();
977 bNeedWriteableControl = true;
978 break;
980 case SID_CUT:
981 bNeedSelection = true;
982 bNeedTextComponent = true;
983 bNeedWriteableControl = true;
984 OSL_TRACE( "FmTextControlShell::ClipBoard: need to invalidate again" );
985 m_bNeedClipboardInvalidation = true;
986 break;
988 case SID_PASTE:
990 Window* pActiveControlVCLWindow = lcl_getWindow( m_xActiveControl );
991 if ( pActiveControlVCLWindow )
993 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pActiveControlVCLWindow) );
994 bDisable |= !aDataHelper.HasFormat( SOT_FORMAT_STRING );
996 else
997 bDisable |= true;
999 bNeedTextComponent = true;
1000 bNeedWriteableControl = true;
1002 break;
1004 case SID_COPY:
1005 bNeedTextComponent = true;
1006 bNeedSelection = true;
1007 break;
1009 case SID_SELECTALL:
1010 bNeedTextComponent = true;
1011 break;
1013 default:
1014 // slot is unknown at all
1015 bDisable |= true;
1016 break;
1018 OSL_POSTCOND( !bNeedSelection || bNeedTextComponent, "FmTextControlShell::GetTextAttributeState: bNeedSelection should imply bNeedTextComponent!" );
1020 if ( !bDisable && bNeedWriteableControl )
1021 bDisable |= !IsActiveControl( ) || m_bActiveControlIsReadOnly;
1023 if ( !bDisable && bNeedTextComponent )
1024 bDisable |= !m_xActiveTextComponent.is();
1026 if ( !bDisable && bNeedSelection )
1028 awt::Selection aSelection = m_xActiveTextComponent->getSelection();
1029 bDisable |= aSelection.Min == aSelection.Max;
1032 if ( bDisable )
1033 _rSet.DisableItem( nSlot );
1036 nSlot = aIter.NextWhich();
1040 //------------------------------------------------------------------------
1041 bool FmTextControlShell::IsActiveControl( bool _bCountRichTextOnly ) const
1043 if ( _bCountRichTextOnly && !m_bActiveControlIsRichText )
1044 return false;
1046 return m_bActiveControl;
1049 //------------------------------------------------------------------------
1050 void FmTextControlShell::dispose()
1052 if ( IsActiveControl() )
1053 controlDeactivated();
1054 if ( isControllerListening() )
1055 stopControllerListening();
1058 //------------------------------------------------------------------------
1059 void FmTextControlShell::designModeChanged( bool /*_bNewDesignMode*/ )
1061 m_rBindings.Invalidate( pTextControlSlots );
1064 //------------------------------------------------------------------------
1065 void FmTextControlShell::formActivated( const Reference< XFormController >& _rxController )
1067 #if OSL_DEBUG_LEVEL > 0
1068 OString sTrace( "FmTextControlShell::formActivated: 0x" );
1069 sTrace += OString::valueOf( (sal_IntPtr)_rxController.get(), 16 );
1070 OSL_TRACE( "%s", sTrace.getStr() );
1071 #endif
1073 DBG_ASSERT( _rxController.is(), "FmTextControlShell::formActivated: invalid controller!" );
1074 if ( !_rxController.is() )
1075 return;
1077 // sometimes, a form controller notifies activations, even if it's already activated
1078 if ( m_xActiveController == _rxController )
1079 return;
1083 startControllerListening( _rxController );
1084 controlActivated( _rxController->getCurrentControl() );
1086 catch( const Exception& )
1088 DBG_UNHANDLED_EXCEPTION();
1092 //------------------------------------------------------------------------
1093 void FmTextControlShell::formDeactivated( const Reference< XFormController >& _rxController )
1095 #if OSL_DEBUG_LEVEL > 0
1096 OString sTrace( "FmTextControlShell::formDeactivated: 0x" );
1097 sTrace += OString::valueOf( (sal_IntPtr)_rxController.get(), 16 );
1098 OSL_TRACE( "%s", sTrace.getStr() );
1099 #endif
1100 (void)_rxController;
1102 if ( IsActiveControl() )
1103 controlDeactivated();
1104 if ( isControllerListening() )
1105 stopControllerListening();
1108 //------------------------------------------------------------------------
1109 void FmTextControlShell::startControllerListening( const Reference< XFormController >& _rxController )
1111 OSL_PRECOND( _rxController.is(), "FmTextControlShell::startControllerListening: invalid controller!" );
1112 if ( !_rxController.is() )
1113 return;
1115 OSL_PRECOND( !isControllerListening(), "FmTextControlShell::startControllerListening: already listening!" );
1116 if ( isControllerListening() )
1117 stopControllerListening( );
1118 DBG_ASSERT( !isControllerListening(), "FmTextControlShell::startControllerListening: inconsistence!" );
1122 Sequence< Reference< XControl > > aControls( _rxController->getControls() );
1123 m_aControlObservers.resize( 0 );
1124 m_aControlObservers.reserve( aControls.getLength() );
1126 const Reference< XControl >* pControls = aControls.getConstArray();
1127 const Reference< XControl >* pControlsEnd = pControls + aControls.getLength();
1128 for ( ; pControls != pControlsEnd; ++pControls )
1130 m_aControlObservers.push_back( FocusListenerAdapter( new FmFocusListenerAdapter( *pControls, this ) ) );
1133 catch( const Exception& )
1135 DBG_UNHANDLED_EXCEPTION();
1138 m_xActiveController = _rxController;
1141 //------------------------------------------------------------------------
1142 void FmTextControlShell::stopControllerListening( )
1144 OSL_PRECOND( isControllerListening(), "FmTextControlShell::stopControllerListening: inconsistence!" );
1146 // dispose all listeners associated with the controls of the active controller
1147 for ( FocusListenerAdapters::iterator aLoop = m_aControlObservers.begin();
1148 aLoop != m_aControlObservers.end();
1149 ++aLoop
1152 (*aLoop)->dispose();
1155 FocusListenerAdapters aEmpty;
1156 m_aControlObservers.swap( aEmpty );
1158 m_xActiveController.clear();
1161 //------------------------------------------------------------------------
1162 void FmTextControlShell::implClearActiveControlRef()
1164 // no more features for this control
1165 for ( ControlFeatures::iterator aLoop = m_aControlFeatures.begin();
1166 aLoop != m_aControlFeatures.end();
1167 ++aLoop
1170 aLoop->second->dispose();
1173 ControlFeatures aEmpty;
1174 m_aControlFeatures.swap( aEmpty );
1176 if ( m_aContextMenuObserver.get() )
1178 m_aContextMenuObserver->dispose();
1179 m_aContextMenuObserver = MouseListenerAdapter();
1182 if ( m_xActiveTextComponent.is() )
1184 OSL_TRACE( "FmTextControlShell::ClipBoard: stopping timer for clipboard invalidation" );
1185 m_aClipboardInvalidation.Stop();
1187 // no more active control
1188 m_xActiveControl.clear();
1189 m_xActiveTextComponent.clear();
1190 m_bActiveControlIsReadOnly = true;
1191 m_bActiveControlIsRichText = false;
1192 m_bActiveControl = false;
1195 //------------------------------------------------------------------------
1196 void FmTextControlShell::controlDeactivated( )
1198 DBG_ASSERT( IsActiveControl(), "FmTextControlShell::controlDeactivated: no active control!" );
1200 m_bActiveControl = false;
1202 m_rBindings.Invalidate( pTextControlSlots );
1205 //------------------------------------------------------------------------
1206 void FmTextControlShell::controlActivated( const Reference< XControl >& _rxControl )
1208 // ensure that all knittings with the previously active control are lost
1209 if ( m_xActiveControl.is() )
1210 implClearActiveControlRef();
1211 DBG_ASSERT( m_aControlFeatures.empty(), "FmTextControlShell::controlActivated: should have no dispatchers when I'm here!" );
1213 #if OSL_DEBUG_LEVEL > 0
1215 Sequence< Reference< XControl > > aActiveControls;
1216 if ( m_xActiveController.is() )
1217 aActiveControls = m_xActiveController->getControls();
1219 bool bFoundThisControl = false;
1221 const Reference< XControl >* pControls = aActiveControls.getConstArray();
1222 const Reference< XControl >* pControlsEnd = pControls + aActiveControls.getLength();
1223 for ( ; ( pControls != pControlsEnd ) && !bFoundThisControl; ++pControls )
1225 if ( *pControls == _rxControl )
1226 bFoundThisControl = true;
1228 DBG_ASSERT( bFoundThisControl, "FmTextControlShell::controlActivated: only controls which belong to the active controller can be activated!" );
1230 #endif
1231 // ask the control for dispatchers for our text-related slots
1232 fillFeatureDispatchers( _rxControl, pTextControlSlots, m_aControlFeatures );
1234 // remember this control
1235 m_xActiveControl = _rxControl;
1236 m_xActiveTextComponent = m_xActiveTextComponent.query( _rxControl );
1237 m_bActiveControlIsReadOnly = lcl_determineReadOnly( m_xActiveControl );
1238 m_bActiveControlIsRichText = lcl_isRichText( m_xActiveControl );
1240 // if we found a rich text control, we need context menu support
1241 if ( m_bActiveControlIsRichText )
1243 DBG_ASSERT( NULL == m_aContextMenuObserver.get(), "FmTextControlShell::controlActivated: already have an observer!" );
1244 m_aContextMenuObserver = MouseListenerAdapter( new FmMouseListenerAdapter( _rxControl, this ) );
1247 if ( m_xActiveTextComponent.is() )
1249 OSL_TRACE( "FmTextControlShell::ClipBoard: starting timer for clipboard invalidation" );
1250 m_aClipboardInvalidation.Start();
1253 m_bActiveControl = true;
1255 m_rBindings.Invalidate( pTextControlSlots );
1257 if ( m_pViewFrame )
1258 m_pViewFrame->UIFeatureChanged();
1260 // don't call the activation handler if we don't have any slots we can serve
1261 // The activation handler is used to put the shell on the top of the dispatcher stack,
1262 // so it's preferred when slots are distributed.
1263 // Note that this is a slight hack, to prevent that we grab slots from the SfxDispatcher
1264 // which should be served by other shells (e.g. Cut/Copy/Paste).
1265 // A real solution would be a forwarding-mechanism for slots: We should be on the top
1266 // if we're active, but if we cannot handle the slot, then we need to tell the dispatcher
1267 // to skip our shell, and pass the slot to the next one. However, this mechanism is not
1268 // not in place in SFX.
1269 // Another possibility would be to have dedicated shells for the slots which we might
1270 // or might not be able to serve. However, this could probably increase the number of
1271 // shells too much (In theory, nearly every slot could have an own shell then).
1273 // #i51621# / 2005-08-19 / frank.schoenheit@sun.com
1274 // bool bHaveAnyServeableSlots = m_xActiveTextComponent.is() || !m_aControlFeatures.empty();
1275 // LEM: not calling m_aControlActivatonHandler causes fdo#63695, so disable this hack for now.
1276 if ( m_aControlActivationHandler.IsSet() /* && bHaveAnyServeableSlots */ )
1277 m_aControlActivationHandler.Call( NULL );
1279 m_bNeedClipboardInvalidation = true;
1282 //------------------------------------------------------------------------
1283 void FmTextControlShell::fillFeatureDispatchers( const Reference< XControl > _rxControl, SfxSlotId* _pZeroTerminatedSlots,
1284 ControlFeatures& _rDispatchers )
1286 Reference< XDispatchProvider > xProvider( _rxControl, UNO_QUERY );
1287 SfxApplication* pApplication = SFX_APP();
1288 DBG_ASSERT( pApplication, "FmTextControlShell::fillFeatureDispatchers: no SfxApplication!" );
1289 if ( xProvider.is() && pApplication )
1291 SfxSlotId* pSlots = _pZeroTerminatedSlots;
1292 while ( *pSlots )
1294 FmTextControlFeature* pDispatcher = implGetFeatureDispatcher( xProvider, pApplication, *pSlots );
1295 if ( pDispatcher )
1296 _rDispatchers.insert( ControlFeatures::value_type( *pSlots, ControlFeature( pDispatcher ) ) );
1298 ++pSlots;
1303 //------------------------------------------------------------------------
1304 void FmTextControlShell::impl_parseURL_nothrow( URL& _rURL )
1308 if ( !m_xURLTransformer.is() )
1310 m_xURLTransformer = util::URLTransformer::create( ::comphelper::getProcessComponentContext() );
1312 if ( m_xURLTransformer.is() )
1313 m_xURLTransformer->parseStrict( _rURL );
1315 catch( const Exception& )
1317 DBG_UNHANDLED_EXCEPTION();
1321 //------------------------------------------------------------------------
1322 FmTextControlFeature* FmTextControlShell::implGetFeatureDispatcher( const Reference< XDispatchProvider >& _rxProvider, SfxApplication* _pApplication, SfxSlotId _nSlot )
1324 OSL_PRECOND( _rxProvider.is() && _pApplication, "FmTextControlShell::implGetFeatureDispatcher: invalid arg(s)!" );
1325 URL aFeatureURL;
1326 aFeatureURL.Complete = lcl_getUnoSlotName( *_pApplication, _nSlot );
1327 impl_parseURL_nothrow( aFeatureURL );
1328 Reference< XDispatch > xDispatcher = _rxProvider->queryDispatch( aFeatureURL, OUString(), 0xFF );
1329 if ( xDispatcher.is() )
1330 return new FmTextControlFeature( xDispatcher, aFeatureURL, _nSlot, this );
1331 return NULL;
1334 //------------------------------------------------------------------------
1335 void FmTextControlShell::Invalidate( SfxSlotId _nSlot )
1337 m_rBindings.Invalidate( _nSlot );
1338 // despite this method being called "Invalidate", we also update here - this gives more immediate
1339 // feedback in the UI
1340 m_rBindings.Update( _nSlot );
1343 //------------------------------------------------------------------------
1344 void FmTextControlShell::focusGained( const ::com::sun::star::awt::FocusEvent& _rEvent )
1346 Reference< XControl > xControl( _rEvent.Source, UNO_QUERY );
1348 #if OSL_DEBUG_LEVEL > 0
1349 OString sTrace( "FmTextControlShell::focusGained: 0x" );
1350 sTrace += OString::valueOf( (sal_IntPtr)xControl.get(), 16 );
1351 OSL_TRACE( "%s", sTrace.getStr() );
1352 #endif
1354 DBG_ASSERT( xControl.is(), "FmTextControlShell::focusGained: suspicious focus event!" );
1355 if ( xControl.is() )
1356 controlActivated( xControl );
1359 //------------------------------------------------------------------------
1360 void FmTextControlShell::focusLost( const ::com::sun::star::awt::FocusEvent& _rEvent )
1362 Reference< XControl > xControl( _rEvent.Source, UNO_QUERY );
1364 #if OSL_DEBUG_LEVEL > 0
1365 OString sTrace( "FmTextControlShell::focusLost: 0x" );
1366 sTrace += OString::valueOf( (sal_IntPtr)xControl.get(), 16 );
1367 OSL_TRACE( "%s", sTrace.getStr() );
1368 #endif
1370 m_bActiveControl = false;
1373 //------------------------------------------------------------------------
1374 void FmTextControlShell::ForgetActiveControl()
1376 implClearActiveControlRef();
1379 //------------------------------------------------------------------------
1380 void FmTextControlShell::contextMenuRequested( const awt::MouseEvent& /*_rEvent*/ )
1382 m_rBindings.GetDispatcher()->ExecutePopup( SVX_RES( RID_FM_TEXTATTRIBUTE_MENU ) );
1385 //........................................................................
1386 } // namespace svx
1387 //........................................................................
1389 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */