1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: fmtextcontrolshell.cxx,v $
10 * $Revision: 1.16.86.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
35 #include "fmresids.hrc"
36 #include "fmtextcontroldialogs.hxx"
37 #include "fmtextcontrolfeature.hxx"
38 #include "fmtextcontrolshell.hxx"
39 #include "svx/crsditem.hxx"
40 #include "svx/dialmgr.hxx"
41 #include "svx/editeng.hxx"
42 #include "svx/eeitem.hxx"
43 #include "svx/fmglob.hxx"
44 #include "svx/scriptspaceitem.hxx"
45 #include "svx/svxids.hrc"
46 #include "svx/udlnitem.hxx"
48 /** === begin UNO includes === **/
49 #include <com/sun/star/beans/XPropertySet.hpp>
50 #include <com/sun/star/awt/FontDescriptor.hpp>
51 #include <com/sun/star/frame/XDispatchProvider.hpp>
52 #include <com/sun/star/form/XForm.hpp>
53 #include <com/sun/star/container/XChild.hpp>
54 #include <com/sun/star/awt/XFocusListener.hpp>
55 #include <com/sun/star/awt/XMouseListener.hpp>
56 /** === end UNO includes === **/
58 #include <comphelper/componentcontext.hxx>
59 #include <comphelper/processfactory.hxx>
60 #include <cppuhelper/implbase1.hxx>
61 #include <sfx2/app.hxx>
62 #include <sfx2/bindings.hxx>
63 #include <sfx2/dispatch.hxx>
64 #include <sfx2/msgpool.hxx>
65 #include <sfx2/objsh.hxx>
66 #include <sfx2/request.hxx>
67 #include <sfx2/sfxuno.hxx>
68 #include <sfx2/viewfrm.hxx>
69 #include <svtools/eitem.hxx>
70 #include <svtools/intitem.hxx>
71 #include <svtools/itempool.hxx>
72 #include <svtools/languageoptions.hxx>
73 #include <svtools/stringtransfer.hxx>
74 #include <svtools/whiter.hxx>
75 #include <toolkit/helper/vclunohelper.hxx>
76 #include <tools/diagnose_ex.h>
77 #include <vcl/msgbox.hxx>
78 #include <vcl/outdev.hxx>
79 #include <vos/mutex.hxx>
83 //........................................................................
86 //........................................................................
88 using namespace ::com::sun::star
;
89 using namespace ::com::sun::star::uno
;
90 using namespace ::com::sun::star::awt
;
91 using namespace ::com::sun::star::form
;
92 using namespace ::com::sun::star::lang
;
93 using namespace ::com::sun::star::frame
;
94 using namespace ::com::sun::star::util
;
95 using namespace ::com::sun::star::beans
;
96 using namespace ::com::sun::star::container
;
98 //====================================================================
99 typedef USHORT WhichId
;
101 //====================================================================
102 static SfxSlotId pTextControlSlots
[] =
108 // SID_ATTR_TABSTOP, /* 2 */
110 SID_ATTR_CHAR_POSTURE
,
111 SID_ATTR_CHAR_WEIGHT
,
112 SID_ATTR_CHAR_SHADOWED
,
113 SID_ATTR_CHAR_WORDLINEMODE
,
114 SID_ATTR_CHAR_CONTOUR
,
115 SID_ATTR_CHAR_STRIKEOUT
,
116 SID_ATTR_CHAR_UNDERLINE
,
117 SID_ATTR_CHAR_FONTHEIGHT
,
119 SID_ATTR_CHAR_KERNING
,
120 SID_ATTR_CHAR_LANGUAGE
, /* 20 */
121 SID_ATTR_CHAR_ESCAPEMENT
,
122 SID_ATTR_PARA_ADJUST
, /* 28 */
123 SID_ATTR_PARA_ADJUST_LEFT
,
124 SID_ATTR_PARA_ADJUST_RIGHT
,
125 SID_ATTR_PARA_ADJUST_CENTER
,
126 SID_ATTR_PARA_ADJUST_BLOCK
,
127 SID_ATTR_PARA_LINESPACE
, /* 33 */
128 SID_ATTR_PARA_LINESPACE_10
,
129 SID_ATTR_PARA_LINESPACE_15
,
130 SID_ATTR_PARA_LINESPACE_20
,
131 SID_ATTR_LRSPACE
, /* 48 */
132 SID_ATTR_ULSPACE
, /* 49 */
133 SID_ATTR_CHAR_AUTOKERN
,
134 SID_ATTR_CHAR_OVERLINE
,
135 SID_SET_SUPER_SCRIPT
,
139 // SID_TEXTDIRECTION_LEFT_TO_RIGHT, /* 907 */
140 // SID_TEXTDIRECTION_TOP_TO_BOTTOM,
141 SID_ATTR_CHAR_SCALEWIDTH
, /* 911 */
142 SID_ATTR_CHAR_RELIEF
,
143 SID_CLIPBOARD_FORMAT_ITEMS
, /* 922 */
144 SID_ATTR_PARA_LEFT_TO_RIGHT
, /* 950 */
145 SID_ATTR_PARA_RIGHT_TO_LEFT
,
149 // slots which we are not responsible for on the SfxShell level, but
150 // need to handle during the "paragraph attributes" and/or "character
151 // attributes" dialogs
152 static SfxSlotId pDialogSlots
[] =
155 SID_ATTR_PARA_HANGPUNCTUATION
,
156 SID_ATTR_PARA_FORBIDDEN_RULES
,
157 SID_ATTR_PARA_SCRIPTSPACE
,
158 SID_ATTR_CHAR_LATIN_LANGUAGE
,
159 SID_ATTR_CHAR_CJK_LANGUAGE
,
160 SID_ATTR_CHAR_CTL_LANGUAGE
,
161 SID_ATTR_CHAR_LATIN_FONT
,
162 SID_ATTR_CHAR_CJK_FONT
,
163 SID_ATTR_CHAR_CTL_FONT
,
164 SID_ATTR_CHAR_LATIN_FONTHEIGHT
,
165 SID_ATTR_CHAR_CJK_FONTHEIGHT
,
166 SID_ATTR_CHAR_CTL_FONTHEIGHT
,
167 SID_ATTR_CHAR_LATIN_WEIGHT
,
168 SID_ATTR_CHAR_CJK_WEIGHT
,
169 SID_ATTR_CHAR_CTL_WEIGHT
,
170 SID_ATTR_CHAR_LATIN_POSTURE
,
171 SID_ATTR_CHAR_CJK_POSTURE
,
172 SID_ATTR_CHAR_CTL_POSTURE
,
173 SID_ATTR_CHAR_EMPHASISMARK
,
177 //====================================================================
178 //= FmFocusListenerAdapter
179 //====================================================================
180 typedef ::cppu::WeakImplHelper1
< XFocusListener
181 > FmFocusListenerAdapter_Base
;
182 class FmFocusListenerAdapter
: public FmFocusListenerAdapter_Base
185 IFocusObserver
* m_pObserver
;
186 Reference
< XWindow
> m_xWindow
;
189 FmFocusListenerAdapter( const Reference
< XControl
>& _rxControl
, IFocusObserver
* _pObserver
);
191 // clean up the instance
195 ~FmFocusListenerAdapter();
198 virtual void SAL_CALL
focusGained( const FocusEvent
& e
) throw (RuntimeException
);
199 virtual void SAL_CALL
focusLost( const FocusEvent
& e
) throw (RuntimeException
);
200 virtual void SAL_CALL
disposing( const EventObject
& Source
) throw (RuntimeException
);
203 //--------------------------------------------------------------------
204 DBG_NAME( FmFocusListenerAdapter
)
205 //--------------------------------------------------------------------
206 FmFocusListenerAdapter::FmFocusListenerAdapter( const Reference
< XControl
>& _rxControl
, IFocusObserver
* _pObserver
)
207 :m_pObserver( _pObserver
)
208 ,m_xWindow( _rxControl
, UNO_QUERY
)
210 DBG_CTOR( FmFocusListenerAdapter
, NULL
);
212 DBG_ASSERT( m_xWindow
.is(), "FmFocusListenerAdapter::FmFocusListenerAdapter: invalid control!" );
213 osl_incrementInterlockedCount( &m_refCount
);
217 if ( m_xWindow
.is() )
218 m_xWindow
->addFocusListener( this );
220 catch( const Exception
& )
222 DBG_UNHANDLED_EXCEPTION();
225 osl_decrementInterlockedCount( &m_refCount
);
228 //--------------------------------------------------------------------
229 FmFocusListenerAdapter::~FmFocusListenerAdapter()
234 DBG_DTOR( FmFocusListenerAdapter
, NULL
);
237 //--------------------------------------------------------------------
238 void FmFocusListenerAdapter::dispose()
240 if ( m_xWindow
.is() )
242 m_xWindow
->removeFocusListener( this );
247 //--------------------------------------------------------------------
248 void SAL_CALL
FmFocusListenerAdapter::focusGained( const FocusEvent
& e
) throw (RuntimeException
)
251 m_pObserver
->focusGained( e
);
254 //--------------------------------------------------------------------
255 void SAL_CALL
FmFocusListenerAdapter::focusLost( const FocusEvent
& e
) throw (RuntimeException
)
258 m_pObserver
->focusLost( e
);
261 //--------------------------------------------------------------------
262 void SAL_CALL
FmFocusListenerAdapter::disposing( const EventObject
& Source
) throw (RuntimeException
)
265 DBG_ASSERT( Source
.Source
== m_xWindow
, "FmFocusListenerAdapter::disposing: where did this come from?" );
269 //====================================================================
270 //= FmMouseListenerAdapter
271 //====================================================================
272 typedef ::cppu::WeakImplHelper1
< XMouseListener
273 > FmMouseListenerAdapter_Base
;
274 class FmMouseListenerAdapter
: public FmMouseListenerAdapter_Base
277 IContextRequestObserver
* m_pObserver
;
278 Reference
< XWindow
> m_xWindow
;
281 FmMouseListenerAdapter( const Reference
< XControl
>& _rxControl
, IContextRequestObserver
* _pObserver
);
283 // clean up the instance
287 ~FmMouseListenerAdapter();
290 virtual void SAL_CALL
mousePressed( const awt::MouseEvent
& e
) throw (RuntimeException
);
291 virtual void SAL_CALL
mouseReleased( const awt::MouseEvent
& e
) throw (RuntimeException
);
292 virtual void SAL_CALL
mouseEntered( const awt::MouseEvent
& e
) throw (RuntimeException
);
293 virtual void SAL_CALL
mouseExited( const awt::MouseEvent
& e
) throw (RuntimeException
);
294 virtual void SAL_CALL
disposing( const EventObject
& Source
) throw (RuntimeException
);
297 //====================================================================
298 //= FmMouseListenerAdapter
299 //====================================================================
300 //--------------------------------------------------------------------
301 DBG_NAME( FmMouseListenerAdapter
)
302 //--------------------------------------------------------------------
303 FmMouseListenerAdapter::FmMouseListenerAdapter( const Reference
< XControl
>& _rxControl
, IContextRequestObserver
* _pObserver
)
304 :m_pObserver( _pObserver
)
305 ,m_xWindow( _rxControl
, UNO_QUERY
)
307 DBG_CTOR( FmMouseListenerAdapter
, NULL
);
309 DBG_ASSERT( m_xWindow
.is(), "FmMouseListenerAdapter::FmMouseListenerAdapter: invalid control!" );
310 osl_incrementInterlockedCount( &m_refCount
);
314 if ( m_xWindow
.is() )
315 m_xWindow
->addMouseListener( this );
317 catch( const Exception
& )
319 DBG_UNHANDLED_EXCEPTION();
322 osl_decrementInterlockedCount( &m_refCount
);
325 //--------------------------------------------------------------------
326 FmMouseListenerAdapter::~FmMouseListenerAdapter()
331 DBG_DTOR( FmMouseListenerAdapter
, NULL
);
334 //--------------------------------------------------------------------
335 void FmMouseListenerAdapter::dispose()
337 if ( m_xWindow
.is() )
339 m_xWindow
->removeMouseListener( this );
344 //--------------------------------------------------------------------
345 void SAL_CALL
FmMouseListenerAdapter::mousePressed( const awt::MouseEvent
& _rEvent
) throw (::com::sun::star::uno::RuntimeException
)
347 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
348 // is this a request for a context menu?
349 if ( _rEvent
.PopupTrigger
)
352 m_pObserver
->contextMenuRequested( _rEvent
);
356 //--------------------------------------------------------------------
357 void SAL_CALL
FmMouseListenerAdapter::mouseReleased( const awt::MouseEvent
& /*e*/ ) throw (::com::sun::star::uno::RuntimeException
)
362 //--------------------------------------------------------------------
363 void SAL_CALL
FmMouseListenerAdapter::mouseEntered( const awt::MouseEvent
& /*e*/ ) throw (::com::sun::star::uno::RuntimeException
)
368 //--------------------------------------------------------------------
369 void SAL_CALL
FmMouseListenerAdapter::mouseExited( const awt::MouseEvent
& /*e*/ ) throw (::com::sun::star::uno::RuntimeException
)
374 //--------------------------------------------------------------------
375 void SAL_CALL
FmMouseListenerAdapter::disposing( const EventObject
& Source
) throw (RuntimeException
)
378 DBG_ASSERT( Source
.Source
== m_xWindow
, "FmMouseListenerAdapter::disposing: where did this come from?" );
382 //====================================================================
383 //= FmTextControlShell
384 //====================================================================
385 //------------------------------------------------------------------------
388 //....................................................................
389 void lcl_translateUnoStateToItem( SfxSlotId _nSlot
, const Any
& _rUnoState
, SfxItemSet
& _rSet
)
391 WhichId nWhich
= _rSet
.GetPool()->GetWhich( _nSlot
);
392 if ( !_rUnoState
.hasValue() )
394 if ( ( _nSlot
!= SID_CUT
)
395 && ( _nSlot
!= SID_COPY
)
396 && ( _nSlot
!= SID_PASTE
)
399 _rSet
.InvalidateItem( nWhich
);
404 switch ( _rUnoState
.getValueType().getTypeClass() )
406 case TypeClass_BOOLEAN
:
408 sal_Bool bState
= sal_False
;
409 _rUnoState
>>= bState
;
410 if ( _nSlot
== SID_ATTR_PARA_SCRIPTSPACE
)
411 _rSet
.Put( SvxScriptSpaceItem( bState
, nWhich
) );
413 _rSet
.Put( SfxBoolItem( nWhich
, bState
) );
419 Sequence
< PropertyValue
> aComplexState
;
420 if ( _rUnoState
>>= aComplexState
)
422 if ( !aComplexState
.getLength() )
423 _rSet
.InvalidateItem( nWhich
);
426 SfxAllItemSet
aAllItems( _rSet
);
427 TransformParameters( _nSlot
, aComplexState
, aAllItems
);
428 const SfxPoolItem
* pTransformed
= aAllItems
.GetItem( nWhich
);
429 OSL_ENSURE( pTransformed
, "lcl_translateUnoStateToItem: non-empty parameter sequence leading to empty item?" );
431 _rSet
.Put( *pTransformed
);
433 _rSet
.InvalidateItem( nWhich
);
438 DBG_ERROR( "lcl_translateUnoStateToItem: invalid state!" );
445 //....................................................................
446 ::rtl::OUString
lcl_getUnoSlotName( SfxApplication
&, SfxSlotId _nSlotId
)
448 ::rtl::OUString sSlotUnoName
;
450 SfxSlotPool
& rSlotPool
= SfxSlotPool::GetSlotPool( NULL
);
451 const SfxSlot
* pSlot
= rSlotPool
.GetSlot( _nSlotId
);
453 const sal_Char
* pAsciiUnoName
= NULL
;
456 pAsciiUnoName
= pSlot
->GetUnoName();
460 // some hard-coded slots, which do not have a UNO name at SFX level, but which
461 // we nevertheless need to transport via UNO mechanisms, so we need a name
464 case SID_ATTR_PARA_HANGPUNCTUATION
: pAsciiUnoName
= "AllowHangingPunctuation"; break;
465 case SID_ATTR_PARA_FORBIDDEN_RULES
: pAsciiUnoName
= "ApplyForbiddenCharacterRules"; break;
466 case SID_ATTR_PARA_SCRIPTSPACE
: pAsciiUnoName
= "UseScriptSpacing"; break;
472 sSlotUnoName
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:" ) );
473 sSlotUnoName
+= ::rtl::OUString::createFromAscii( pAsciiUnoName
);
475 #if OSL_DEBUG_LEVEL > 0
478 ::rtl::OString
sMessage( "lcl_getUnoSlotName: invalid slot id, or invalid slot, or no UNO name!\n" );
479 sMessage
+= "(slot id: ";
480 sMessage
+= ::rtl::OString::valueOf( (sal_Int32
)_nSlotId
);
482 DBG_ERROR( sMessage
);
488 //....................................................................
489 bool lcl_determineReadOnly( const Reference
< XControl
>& _rxControl
)
491 bool bIsReadOnlyModel
= true;
494 Reference
< XPropertySet
> xModelProps
;
495 if ( _rxControl
.is() )
496 xModelProps
= xModelProps
.query( _rxControl
->getModel() );
497 Reference
< XPropertySetInfo
> xModelPropInfo
;
498 if ( xModelProps
.is() )
499 xModelPropInfo
= xModelProps
->getPropertySetInfo();
501 if ( !xModelPropInfo
.is() || !xModelPropInfo
->hasPropertyByName( FM_PROP_READONLY
) )
502 bIsReadOnlyModel
= true;
505 sal_Bool bReadOnly
= sal_True
;
506 xModelProps
->getPropertyValue( FM_PROP_READONLY
) >>= bReadOnly
;
507 bIsReadOnlyModel
= bReadOnly
;
510 catch( const Exception
& )
512 DBG_UNHANDLED_EXCEPTION();
514 return bIsReadOnlyModel
;
517 //....................................................................
518 static Window
* lcl_getWindow( const Reference
< XControl
>& _rxControl
)
520 Window
* pWindow
= NULL
;
523 Reference
< XWindowPeer
> xControlPeer
;
524 if ( _rxControl
.is() )
525 xControlPeer
= _rxControl
->getPeer();
526 if ( xControlPeer
.is() )
527 pWindow
= VCLUnoHelper::GetWindow( xControlPeer
);
529 catch( const Exception
& )
531 DBG_UNHANDLED_EXCEPTION();
537 //....................................................................
538 bool lcl_isRichText( const Reference
< XControl
>& _rxControl
)
540 if ( !_rxControl
.is() )
543 bool bIsRichText
= false;
546 Reference
< XPropertySet
> xModelProps( _rxControl
->getModel(), UNO_QUERY
);
547 Reference
< XPropertySetInfo
> xPSI
;
548 if ( xModelProps
.is() )
549 xPSI
= xModelProps
->getPropertySetInfo();
550 ::rtl::OUString sRichTextPropertyName
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "RichText" ) );
551 if ( xPSI
.is() && xPSI
->hasPropertyByName( sRichTextPropertyName
) )
553 OSL_VERIFY( xModelProps
->getPropertyValue( sRichTextPropertyName
) >>= bIsRichText
);
556 catch( const Exception
& )
558 DBG_UNHANDLED_EXCEPTION();
564 //------------------------------------------------------------------------
565 FmTextControlShell::FmTextControlShell( SfxViewFrame
* _pFrame
)
566 :m_bActiveControl( false )
567 ,m_bActiveControlIsReadOnly( true )
568 ,m_bActiveControlIsRichText( false )
569 ,m_pViewFrame( _pFrame
)
570 ,m_rBindings( _pFrame
->GetBindings() )
571 ,m_bNeedClipboardInvalidation( true )
573 m_aClipboardInvalidation
.SetTimeoutHdl( LINK( this, FmTextControlShell
, OnInvalidateClipboard
) );
574 m_aClipboardInvalidation
.SetTimeout( 200 );
577 //------------------------------------------------------------------------
578 FmTextControlShell::~FmTextControlShell()
583 //------------------------------------------------------------------------
584 IMPL_LINK( FmTextControlShell
, OnInvalidateClipboard
, void*, /*_pNotInterestedIn*/ )
586 if ( m_bNeedClipboardInvalidation
)
588 DBG_TRACE( "FmTextControlShell::ClipBoard: invalidating clipboard slots" );
589 m_rBindings
.Invalidate( SID_CUT
);
590 m_rBindings
.Invalidate( SID_COPY
);
591 m_rBindings
.Invalidate( SID_PASTE
);
592 m_bNeedClipboardInvalidation
= false;
597 //------------------------------------------------------------------------
598 void FmTextControlShell::transferFeatureStatesToItemSet( ControlFeatures
& _rDispatchers
, SfxAllItemSet
& _rSet
, bool _bTranslateLatin
)
600 SfxItemPool
& rPool
= *_rSet
.GetPool();
602 for ( ControlFeatures::const_iterator aFeature
= _rDispatchers
.begin();
603 aFeature
!= _rDispatchers
.end();
607 SfxSlotId
nSlotId( aFeature
->first
);
608 #if OSL_DEBUG_LEVEL > 0
609 ::rtl::OUString sUnoSlotName
;
611 sUnoSlotName
= lcl_getUnoSlotName( *SFX_APP(), nSlotId
);
613 sUnoSlotName
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "<unknown>" ) );
614 ::rtl::OString
sUnoSlotNameAscii( "\"" );
615 sUnoSlotNameAscii
+= ::rtl::OString( sUnoSlotName
.getStr(), sUnoSlotName
.getLength(), RTL_TEXTENCODING_ASCII_US
);
616 sUnoSlotNameAscii
+= "\"";
619 if ( _bTranslateLatin
)
621 // A rich text control offers a dispatcher for the "Font" slot/feature.
622 // Sadly, the semantics of the dispatches is that the feature "Font" depends
623 // on the current cursor position: If it's on latin text, it's the "latin font"
624 // which is set up at the control. If it's on CJK text, it's the "CJK font", and
625 // aequivalent for "CTL font".
626 // The same holds for some other font related features/slots.
627 // Thus, we have separate dispatches for "Latin Font", "Latin Font Size", etc,
628 // which are only "virtual", in a sense that there exist no item with this id.
629 // So when we encounter such a dispatcher for, say, "Latin Font", we need to
630 // put an item into the set which has the "Font" id.
634 case SID_ATTR_CHAR_LATIN_FONT
: nSlotId
= SID_ATTR_CHAR_FONT
; break;
635 case SID_ATTR_CHAR_LATIN_FONTHEIGHT
:nSlotId
= SID_ATTR_CHAR_FONTHEIGHT
; break;
636 case SID_ATTR_CHAR_LATIN_LANGUAGE
: nSlotId
= SID_ATTR_CHAR_LANGUAGE
; break;
637 case SID_ATTR_CHAR_LATIN_POSTURE
: nSlotId
= SID_ATTR_CHAR_POSTURE
; break;
638 case SID_ATTR_CHAR_LATIN_WEIGHT
: nSlotId
= SID_ATTR_CHAR_WEIGHT
; break;
642 WhichId nWhich
= rPool
.GetWhich( nSlotId
);
643 bool bIsInPool
= rPool
.IsInRange( nWhich
);
646 #if OSL_DEBUG_LEVEL > 0
647 bool bFeatureIsEnabled
= aFeature
->second
->isFeatureEnabled();
648 ::rtl::OString
sMessage( "FmTextControlShell::transferFeatureStatesToItemSet: found a feature state for " );
649 sMessage
+= sUnoSlotNameAscii
;
650 if ( !bFeatureIsEnabled
)
651 sMessage
+= " (disabled)";
652 DBG_TRACE( sMessage
);
655 lcl_translateUnoStateToItem( nSlotId
, aFeature
->second
->getFeatureState(), _rSet
);
657 #if OSL_DEBUG_LEVEL > 0
660 ::rtl::OString
sMessage( "FmTextControlShell::transferFeatureStatesToItemSet: found a feature state for " );
661 sMessage
+= sUnoSlotNameAscii
;
662 sMessage
+= ", but could not translate it into an item!";
663 DBG_TRACE( sMessage
);
669 //------------------------------------------------------------------------
670 void FmTextControlShell::executeAttributeDialog( AttributeSet _eSet
, SfxRequest
& _rReq
)
672 const SvxFontListItem
* pFontList
= PTR_CAST( SvxFontListItem
, m_pViewFrame
->GetObjectShell()->GetItem( SID_ATTR_CHAR_FONTLIST
) );
673 DBG_ASSERT( pFontList
, "FmTextControlShell::executeAttributeDialog: no font list item!" );
677 SfxItemPool
* pPool
= EditEngine::CreatePool();
678 pPool
->FreezeIdRanges();
679 ::std::auto_ptr
< SfxItemSet
> pPureItems( new SfxItemSet( *pPool
) );
681 // put the current states of the items into the set
682 ::std::auto_ptr
< SfxAllItemSet
> pCurrentItems( new SfxAllItemSet( *pPureItems
) );
683 transferFeatureStatesToItemSet( m_aControlFeatures
, *pCurrentItems
);
685 // additional items, which we are not responsible for at the SfxShell level,
686 // but which need to be forwarded to the dialog, anyway
687 ControlFeatures aAdditionalFestures
;
688 fillFeatureDispatchers( m_xActiveControl
, pDialogSlots
, aAdditionalFestures
);
689 transferFeatureStatesToItemSet( aAdditionalFestures
, *pCurrentItems
, true );
691 ::std::auto_ptr
< SfxTabDialog
> pDialog ( _eSet
== eCharAttribs
692 ? static_cast< SfxTabDialog
* >( new TextControlCharAttribDialog( NULL
, *pCurrentItems
, *pFontList
) )
693 : static_cast< SfxTabDialog
* >( new TextControlParaAttribDialog( NULL
, *pCurrentItems
) ) );
694 if ( RET_OK
== pDialog
->Execute() )
696 const SfxItemSet
& rModifiedItems
= *pDialog
->GetOutputItemSet();
697 for ( WhichId nWhich
= pPool
->GetFirstWhich(); nWhich
<= pPool
->GetLastWhich(); ++nWhich
)
699 if ( rModifiedItems
.GetItemState( nWhich
) == SFX_ITEM_SET
)
701 SfxSlotId nSlotForItemSet
= pPool
->GetSlotId( nWhich
);
702 const SfxPoolItem
* pModifiedItem
= rModifiedItems
.GetItem( nWhich
);
705 SfxSlotId nSlotForDispatcher
= nSlotForItemSet
;
706 switch ( nSlotForDispatcher
)
708 case SID_ATTR_CHAR_FONT
: nSlotForDispatcher
= SID_ATTR_CHAR_LATIN_FONT
; break;
709 case SID_ATTR_CHAR_FONTHEIGHT
:nSlotForDispatcher
= SID_ATTR_CHAR_LATIN_FONTHEIGHT
; break;
710 case SID_ATTR_CHAR_LANGUAGE
: nSlotForDispatcher
= SID_ATTR_CHAR_LATIN_LANGUAGE
; break;
711 case SID_ATTR_CHAR_POSTURE
: nSlotForDispatcher
= SID_ATTR_CHAR_LATIN_POSTURE
; break;
712 case SID_ATTR_CHAR_WEIGHT
: nSlotForDispatcher
= SID_ATTR_CHAR_LATIN_WEIGHT
; break;
715 // do we already have a dispatcher for this slot/feature?
716 ControlFeatures::const_iterator aFeaturePos
= m_aControlFeatures
.find( nSlotForDispatcher
);
717 bool bFound
= aFeaturePos
!= m_aControlFeatures
.end( );
721 aFeaturePos
= aAdditionalFestures
.find( nSlotForDispatcher
);
722 bFound
= aFeaturePos
!= aAdditionalFestures
.end( );
727 Sequence
< PropertyValue
> aArgs
;
728 // temporarily put the modified item into a "clean" set,
729 // and let TransformItems calc the respective UNO parameters
730 pPureItems
->Put( *pModifiedItem
);
731 TransformItems( nSlotForItemSet
, *pPureItems
, aArgs
);
732 pPureItems
->ClearItem( nWhich
);
734 if ( ( nSlotForItemSet
== SID_ATTR_PARA_HANGPUNCTUATION
)
735 || ( nSlotForItemSet
== SID_ATTR_PARA_FORBIDDEN_RULES
)
736 || ( nSlotForItemSet
== SID_ATTR_PARA_SCRIPTSPACE
)
739 // these are no UNO slots, they need special handling since TransformItems cannot
741 DBG_ASSERT( aArgs
.getLength() == 0, "FmTextControlShell::executeAttributeDialog: these are no UNO slots - are they?" );
743 const SfxBoolItem
* pBoolItem
= PTR_CAST( SfxBoolItem
, pModifiedItem
);
744 DBG_ASSERT( pBoolItem
, "FmTextControlShell::executeAttributeDialog: no bool item?!" );
748 aArgs
[ 0 ].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Enable" ) );
749 aArgs
[ 0 ].Value
<<= (sal_Bool
)pBoolItem
->GetValue();
754 aFeaturePos
->second
->dispatch( aArgs
);
756 #if OSL_DEBUG_LEVEL > 0
759 ::rtl::OString
sError( "FmTextControShell::executeAttributeDialog: Could not handle the following item:" );
760 sError
+= "\n SlotID: "; sError
+= ::rtl::OString::valueOf( (sal_Int32
)nSlotForItemSet
);
761 sError
+= "\n WhichID: "; sError
+= ::rtl::OString::valueOf( (sal_Int32
)nWhich
);
762 sError
+= "\n UNO name: ";
764 ::rtl::OUString sUnoSlotName
= lcl_getUnoSlotName( *SFX_APP(), nSlotForItemSet
);
765 if ( sUnoSlotName
.getLength() )
766 sError
+= ::rtl::OString( sUnoSlotName
.getStr(), sUnoSlotName
.getLength(), RTL_TEXTENCODING_ASCII_US
);
768 sError
+= "unknown (no SfxSlot)";
769 DBG_ERROR( sError
.getStr() );
774 _rReq
.Done( rModifiedItems
);
778 pCurrentItems
.reset();
780 SfxItemPool::Free(pPool
);
783 //------------------------------------------------------------------------
784 bool FmTextControlShell::executeSelectAll( )
788 if ( m_xActiveTextComponent
.is() )
790 sal_Int32 nTextLen
= m_xActiveTextComponent
->getText().getLength();
791 m_xActiveTextComponent
->setSelection( awt::Selection( 0, nTextLen
) );
795 catch( const Exception
& )
797 DBG_UNHANDLED_EXCEPTION();
799 return false; // not handled
802 //------------------------------------------------------------------------
803 bool FmTextControlShell::executeClipboardSlot( SfxSlotId _nSlot
)
807 if ( m_xActiveTextComponent
.is() )
814 ::rtl::OUString
sSelectedText( m_xActiveTextComponent
->getSelectedText() );
815 ::svt::OStringTransfer::CopyString( sSelectedText
, lcl_getWindow( m_xActiveControl
) );
816 if ( SID_CUT
== _nSlot
)
818 awt::Selection
aSelection( m_xActiveTextComponent
->getSelection() );
819 m_xActiveTextComponent
->insertText( aSelection
, ::rtl::OUString() );
825 ::rtl::OUString sClipboardContent
;
826 OSL_VERIFY( ::svt::OStringTransfer::PasteString( sClipboardContent
, lcl_getWindow( m_xActiveControl
) ) );
827 awt::Selection
aSelection( m_xActiveTextComponent
->getSelection() );
828 m_xActiveTextComponent
->insertText( aSelection
, sClipboardContent
);
832 OSL_ENSURE( sal_False
, "FmTextControlShell::executeClipboardSlot: invalid slot!" );
837 catch( const Exception
& )
839 DBG_UNHANDLED_EXCEPTION();
841 return false; // not handled
844 //------------------------------------------------------------------------
845 void FmTextControlShell::ExecuteTextAttribute( SfxRequest
& _rReq
)
847 SfxSlotId nSlot
= _rReq
.GetSlot();
849 ControlFeatures::const_iterator aFeaturePos
= m_aControlFeatures
.find( nSlot
);
850 if ( aFeaturePos
== m_aControlFeatures
.end() )
856 executeAttributeDialog( eCharAttribs
, _rReq
);
860 executeAttributeDialog( eParaAttribs
, _rReq
);
870 executeClipboardSlot( nSlot
);
874 DBG_ASSERT( aFeaturePos
!= m_aControlFeatures
.end(), "FmTextControShell::ExecuteTextAttribute: I have no such dispatcher, and cannot handle it at all!" );
880 // slots which are dispatched to the control
884 case SID_ATTR_CHAR_STRIKEOUT
:
885 case SID_ATTR_CHAR_UNDERLINE
:
886 case SID_ATTR_CHAR_OVERLINE
:
888 SfxItemSet
aToggled( *_rReq
.GetArgs() );
890 lcl_translateUnoStateToItem( nSlot
, aFeaturePos
->second
->getFeatureState(), aToggled
);
891 WhichId nWhich
= aToggled
.GetPool()->GetWhich( nSlot
);
892 const SfxPoolItem
* pItem
= aToggled
.GetItem( nWhich
);
893 if ( ( SID_ATTR_CHAR_UNDERLINE
== nSlot
) || ( SID_ATTR_CHAR_OVERLINE
== nSlot
) )
895 const SvxOverlineItem
* pTextLine
= PTR_CAST( SvxOverlineItem
, pItem
);
896 DBG_ASSERT( pTextLine
, "FmTextControlShell::ExecuteTextAttribute: ooops - no underline/overline item!" );
899 FontUnderline eTL
= pTextLine
->GetLineStyle();
900 if ( SID_ATTR_CHAR_UNDERLINE
== nSlot
) {
901 aToggled
.Put( SvxUnderlineItem( eTL
== UNDERLINE_SINGLE
? UNDERLINE_NONE
: UNDERLINE_SINGLE
, nWhich
) );
903 aToggled
.Put( SvxOverlineItem( eTL
== UNDERLINE_SINGLE
? UNDERLINE_NONE
: UNDERLINE_SINGLE
, nWhich
) );
909 const SvxCrossedOutItem
* pCrossedOut
= PTR_CAST( SvxCrossedOutItem
, pItem
);
910 DBG_ASSERT( pCrossedOut
, "FmTextControlShell::ExecuteTextAttribute: ooops - no CrossedOut item!" );
913 FontStrikeout eFS
= pCrossedOut
->GetStrikeout();
914 aToggled
.Put( SvxCrossedOutItem( eFS
== STRIKEOUT_SINGLE
? STRIKEOUT_NONE
: STRIKEOUT_SINGLE
, nWhich
) );
918 Sequence
< PropertyValue
> aArguments
;
919 TransformItems( nSlot
, aToggled
, aArguments
);
920 aFeaturePos
->second
->dispatch( aArguments
);
924 case SID_ATTR_CHAR_FONTHEIGHT
:
925 case SID_ATTR_CHAR_FONT
:
926 case SID_ATTR_CHAR_POSTURE
:
927 case SID_ATTR_CHAR_WEIGHT
:
928 case SID_ATTR_CHAR_SHADOWED
:
929 case SID_ATTR_CHAR_CONTOUR
:
930 case SID_SET_SUPER_SCRIPT
:
931 case SID_SET_SUB_SCRIPT
:
933 const SfxItemSet
* pArgs
= _rReq
.GetArgs();
934 Sequence
< PropertyValue
> aArgs
;
936 TransformItems( nSlot
, *pArgs
, aArgs
);
937 aFeaturePos
->second
->dispatch( aArgs
);
942 if ( aFeaturePos
->second
->isFeatureEnabled() )
943 aFeaturePos
->second
->dispatch();
950 //------------------------------------------------------------------------
951 void FmTextControlShell::GetTextAttributeState( SfxItemSet
& _rSet
)
953 SfxWhichIter
aIter( _rSet
);
954 sal_uInt16 nSlot
= aIter
.FirstWhich();
957 if ( ( nSlot
== SID_ATTR_PARA_LEFT_TO_RIGHT
)
958 || ( nSlot
== SID_ATTR_PARA_RIGHT_TO_LEFT
)
961 if ( !SvtLanguageOptions().IsCTLFontEnabled() )
963 _rSet
.DisableItem( nSlot
);
964 nSlot
= aIter
.NextWhich();
969 ControlFeatures::const_iterator aFeaturePos
= m_aControlFeatures
.find( nSlot
);
970 if ( aFeaturePos
!= m_aControlFeatures
.end() )
972 if ( aFeaturePos
->second
->isFeatureEnabled() )
973 lcl_translateUnoStateToItem( nSlot
, aFeaturePos
->second
->getFeatureState(), _rSet
);
975 _rSet
.DisableItem( nSlot
);
979 bool bDisable
= false;
981 bool bNeedWriteableControl
= false;
982 bool bNeedTextComponent
= false;
983 bool bNeedSelection
= false;
989 bDisable
|= m_aControlFeatures
.empty();
990 bNeedWriteableControl
= true;
994 bNeedSelection
= true;
995 bNeedTextComponent
= true;
996 bNeedWriteableControl
= true;
997 DBG_TRACE( "FmTextControlShell::ClipBoard: need to invalidate again" );
998 m_bNeedClipboardInvalidation
= true;
1003 Window
* pActiveControlVCLWindow
= lcl_getWindow( m_xActiveControl
);
1004 if ( pActiveControlVCLWindow
)
1006 TransferableDataHelper
aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pActiveControlVCLWindow
) );
1007 bDisable
|= !aDataHelper
.HasFormat( SOT_FORMAT_STRING
);
1012 bNeedTextComponent
= true;
1013 bNeedWriteableControl
= true;
1018 bNeedTextComponent
= true;
1019 bNeedSelection
= true;
1023 bNeedTextComponent
= true;
1027 // slot is unknown at all
1031 OSL_POSTCOND( !bNeedSelection
|| bNeedTextComponent
, "FmTextControlShell::GetTextAttributeState: bNeedSelection should imply bNeedTextComponent!" );
1033 if ( !bDisable
&& bNeedWriteableControl
)
1034 bDisable
|= !IsActiveControl( ) || m_bActiveControlIsReadOnly
;
1036 if ( !bDisable
&& bNeedTextComponent
)
1037 bDisable
|= !m_xActiveTextComponent
.is();
1039 if ( !bDisable
&& bNeedSelection
)
1041 awt::Selection aSelection
= m_xActiveTextComponent
->getSelection();
1042 bDisable
|= aSelection
.Min
== aSelection
.Max
;
1046 _rSet
.DisableItem( nSlot
);
1049 nSlot
= aIter
.NextWhich();
1053 //------------------------------------------------------------------------
1054 bool FmTextControlShell::IsActiveControl( bool _bCountRichTextOnly
) const
1056 if ( _bCountRichTextOnly
&& !m_bActiveControlIsRichText
)
1059 return m_bActiveControl
;
1062 //------------------------------------------------------------------------
1063 void FmTextControlShell::dispose()
1065 if ( IsActiveControl() )
1066 controlDeactivated();
1067 if ( isControllerListening() )
1068 stopControllerListening();
1071 //------------------------------------------------------------------------
1072 void FmTextControlShell::designModeChanged( bool /*_bNewDesignMode*/ )
1074 m_rBindings
.Invalidate( pTextControlSlots
);
1077 //------------------------------------------------------------------------
1078 void FmTextControlShell::formActivated( const Reference
< XFormController
>& _rxController
)
1080 #if OSL_DEBUG_LEVEL > 0
1081 ::rtl::OString
sTrace( "FmTextControlShell::formActivated: 0x" );
1082 sTrace
+= ::rtl::OString::valueOf( (sal_IntPtr
)_rxController
.get(), 16 );
1083 DBG_TRACE( sTrace
);
1086 DBG_ASSERT( _rxController
.is(), "FmTextControlShell::formActivated: invalid controller!" );
1087 if ( !_rxController
.is() )
1090 // sometimes, a form controller notifies activations, even if it's already activated
1091 if ( m_xActiveController
== _rxController
)
1096 startControllerListening( _rxController
);
1097 controlActivated( _rxController
->getCurrentControl() );
1099 catch( const Exception
& )
1101 DBG_UNHANDLED_EXCEPTION();
1105 //------------------------------------------------------------------------
1106 void FmTextControlShell::formDeactivated( const Reference
< XFormController
>& _rxController
)
1108 #if OSL_DEBUG_LEVEL > 0
1109 ::rtl::OString
sTrace( "FmTextControlShell::formDeactivated: 0x" );
1110 sTrace
+= ::rtl::OString::valueOf( (sal_IntPtr
)_rxController
.get(), 16 );
1111 DBG_TRACE( sTrace
);
1113 (void)_rxController
;
1115 if ( IsActiveControl() )
1116 controlDeactivated();
1117 if ( isControllerListening() )
1118 stopControllerListening();
1121 //------------------------------------------------------------------------
1122 void FmTextControlShell::startControllerListening( const Reference
< XFormController
>& _rxController
)
1124 OSL_PRECOND( _rxController
.is(), "FmTextControlShell::startControllerListening: invalid controller!" );
1125 if ( !_rxController
.is() )
1128 OSL_PRECOND( !isControllerListening(), "FmTextControlShell::startControllerListening: already listening!" );
1129 if ( isControllerListening() )
1130 stopControllerListening( );
1131 DBG_ASSERT( !isControllerListening(), "FmTextControlShell::startControllerListening: inconsistence!" );
1135 Sequence
< Reference
< XControl
> > aControls( _rxController
->getControls() );
1136 m_aControlObservers
.resize( 0 );
1137 m_aControlObservers
.reserve( aControls
.getLength() );
1139 const Reference
< XControl
>* pControls
= aControls
.getConstArray();
1140 const Reference
< XControl
>* pControlsEnd
= pControls
+ aControls
.getLength();
1141 for ( ; pControls
!= pControlsEnd
; ++pControls
)
1143 m_aControlObservers
.push_back( FocusListenerAdapter( new FmFocusListenerAdapter( *pControls
, this ) ) );
1146 catch( const Exception
& )
1148 DBG_UNHANDLED_EXCEPTION();
1151 m_xActiveController
= _rxController
;
1154 //------------------------------------------------------------------------
1155 void FmTextControlShell::stopControllerListening( )
1157 OSL_PRECOND( isControllerListening(), "FmTextControlShell::stopControllerListening: inconsistence!" );
1159 // dispose all listeners associated with the controls of the active controller
1160 for ( FocusListenerAdapters::iterator aLoop
= m_aControlObservers
.begin();
1161 aLoop
!= m_aControlObservers
.end();
1165 (*aLoop
)->dispose();
1168 FocusListenerAdapters aEmpty
;
1169 m_aControlObservers
.swap( aEmpty
);
1171 m_xActiveController
.clear();
1174 //------------------------------------------------------------------------
1175 void FmTextControlShell::implClearActiveControlRef()
1177 // no more features for this control
1178 for ( ControlFeatures::iterator aLoop
= m_aControlFeatures
.begin();
1179 aLoop
!= m_aControlFeatures
.end();
1183 aLoop
->second
->dispose();
1186 ControlFeatures aEmpty
;
1187 m_aControlFeatures
.swap( aEmpty
);
1189 if ( m_aContextMenuObserver
.get() )
1191 m_aContextMenuObserver
->dispose();
1192 m_aContextMenuObserver
= MouseListenerAdapter();
1195 if ( m_xActiveTextComponent
.is() )
1197 DBG_TRACE( "FmTextControlShell::ClipBoard: stopping timer for clipboard invalidation" );
1198 m_aClipboardInvalidation
.Stop();
1200 // no more active control
1201 m_xActiveControl
.clear();
1202 m_xActiveTextComponent
.clear();
1203 m_bActiveControlIsReadOnly
= true;
1204 m_bActiveControlIsRichText
= false;
1205 m_bActiveControl
= false;
1208 //------------------------------------------------------------------------
1209 void FmTextControlShell::controlDeactivated( )
1211 DBG_ASSERT( IsActiveControl(), "FmTextControlShell::controlDeactivated: no active control!" );
1213 m_bActiveControl
= false;
1215 m_rBindings
.Invalidate( pTextControlSlots
);
1218 //------------------------------------------------------------------------
1219 void FmTextControlShell::controlActivated( const Reference
< XControl
>& _rxControl
)
1221 // ensure that all knittings with the previously active control are lost
1222 if ( m_xActiveControl
.is() )
1223 implClearActiveControlRef();
1224 DBG_ASSERT( m_aControlFeatures
.empty(), "FmTextControlShell::controlActivated: should have no dispatchers when I'm here!" );
1226 #if OSL_DEBUG_LEVEL > 0
1228 Sequence
< Reference
< XControl
> > aActiveControls
;
1229 if ( m_xActiveController
.is() )
1230 aActiveControls
= m_xActiveController
->getControls();
1232 bool bFoundThisControl
= false;
1234 const Reference
< XControl
>* pControls
= aActiveControls
.getConstArray();
1235 const Reference
< XControl
>* pControlsEnd
= pControls
+ aActiveControls
.getLength();
1236 for ( ; ( pControls
!= pControlsEnd
) && !bFoundThisControl
; ++pControls
)
1238 if ( *pControls
== _rxControl
)
1239 bFoundThisControl
= true;
1241 DBG_ASSERT( bFoundThisControl
, "FmTextControlShell::controlActivated: only controls which belong to the active controller can be activated!" );
1244 // ask the control for dispatchers for our text-related slots
1245 fillFeatureDispatchers( _rxControl
, pTextControlSlots
, m_aControlFeatures
);
1247 // remember this control
1248 m_xActiveControl
= _rxControl
;
1249 m_xActiveTextComponent
= m_xActiveTextComponent
.query( _rxControl
);
1250 m_bActiveControlIsReadOnly
= lcl_determineReadOnly( m_xActiveControl
);
1251 m_bActiveControlIsRichText
= lcl_isRichText( m_xActiveControl
);
1253 // if we found a rich text control, we need context menu support
1254 if ( m_bActiveControlIsRichText
)
1256 DBG_ASSERT( NULL
== m_aContextMenuObserver
.get(), "FmTextControlShell::controlActivated: already have an observer!" );
1257 m_aContextMenuObserver
= MouseListenerAdapter( new FmMouseListenerAdapter( _rxControl
, this ) );
1260 if ( m_xActiveTextComponent
.is() )
1262 DBG_TRACE( "FmTextControlShell::ClipBoard: starting timer for clipboard invalidation" );
1263 m_aClipboardInvalidation
.Start();
1266 m_bActiveControl
= true;
1268 m_rBindings
.Invalidate( pTextControlSlots
);
1271 m_pViewFrame
->UIFeatureChanged();
1273 // don't call the activation handler if we don't have any slots we can serve
1274 // The activation handler is used to put the shell on the top of the dispatcher stack,
1275 // so it's preferred when slots are distributed.
1276 // Note that this is a slight hack, to prevent that we grab slots from the SfxDispatcher
1277 // which should be served by other shells (e.g. Cut/Copy/Paste).
1278 // A real solution would be a forwarding-mechanism for slots: We should be on the top
1279 // if we're active, but if we cannot handle the slot, then we need to tell the dispatcher
1280 // to skip our shell, and pass the slot to the next one. However, this mechanism is not
1281 // not in place in SFX.
1282 // Another possibility would be to have dedicated shells for the slots which we might
1283 // or might not be able to serve. However, this could probably increase the number of
1284 // shells too much (In theory, nearly every slot could have an own shell then).
1286 // #i51621# / 2005-08-19 / frank.schoenheit@sun.com
1287 bool bHaveAnyServeableSlots
= m_xActiveTextComponent
.is() || !m_aControlFeatures
.empty();
1288 if ( m_aControlActivationHandler
.IsSet() && bHaveAnyServeableSlots
)
1289 m_aControlActivationHandler
.Call( NULL
);
1291 m_bNeedClipboardInvalidation
= true;
1294 //------------------------------------------------------------------------
1295 void FmTextControlShell::fillFeatureDispatchers( const Reference
< XControl
> _rxControl
, SfxSlotId
* _pZeroTerminatedSlots
,
1296 ControlFeatures
& _rDispatchers
)
1298 Reference
< XDispatchProvider
> xProvider( _rxControl
, UNO_QUERY
);
1299 SfxApplication
* pApplication
= SFX_APP();
1300 DBG_ASSERT( pApplication
, "FmTextControlShell::fillFeatureDispatchers: no SfxApplication!" );
1301 if ( xProvider
.is() && pApplication
)
1303 SfxSlotId
* pSlots
= _pZeroTerminatedSlots
;
1306 FmTextControlFeature
* pDispatcher
= implGetFeatureDispatcher( xProvider
, pApplication
, *pSlots
);
1308 _rDispatchers
.insert( ControlFeatures::value_type( *pSlots
, ControlFeature( pDispatcher
) ) );
1315 //------------------------------------------------------------------------
1316 void FmTextControlShell::impl_parseURL_nothrow( URL
& _rURL
)
1320 if ( !m_xURLTransformer
.is() )
1322 ::comphelper::ComponentContext
aContext( ::comphelper::getProcessServiceFactory() );
1323 aContext
.createComponent( "com.sun.star.util.URLTransformer", m_xURLTransformer
);
1325 if ( m_xURLTransformer
.is() )
1326 m_xURLTransformer
->parseStrict( _rURL
);
1328 catch( const Exception
& )
1330 DBG_UNHANDLED_EXCEPTION();
1334 //------------------------------------------------------------------------
1335 FmTextControlFeature
* FmTextControlShell::implGetFeatureDispatcher( const Reference
< XDispatchProvider
>& _rxProvider
, SfxApplication
* _pApplication
, SfxSlotId _nSlot
)
1337 OSL_PRECOND( _rxProvider
.is() && _pApplication
, "FmTextControlShell::implGetFeatureDispatcher: invalid arg(s)!" );
1339 aFeatureURL
.Complete
= lcl_getUnoSlotName( *_pApplication
, _nSlot
);
1340 impl_parseURL_nothrow( aFeatureURL
);
1341 Reference
< XDispatch
> xDispatcher
= _rxProvider
->queryDispatch( aFeatureURL
, ::rtl::OUString(), 0xFF );
1342 if ( xDispatcher
.is() )
1343 return new FmTextControlFeature( xDispatcher
, aFeatureURL
, _nSlot
, this );
1347 //------------------------------------------------------------------------
1348 void FmTextControlShell::Invalidate( SfxSlotId _nSlot
)
1350 m_rBindings
.Invalidate( _nSlot
);
1351 // despite this method being called "Invalidate", we also update here - this gives more immediate
1352 // feedback in the UI
1353 m_rBindings
.Update( _nSlot
);
1356 //------------------------------------------------------------------------
1357 void FmTextControlShell::focusGained( const ::com::sun::star::awt::FocusEvent
& _rEvent
)
1359 Reference
< XControl
> xControl( _rEvent
.Source
, UNO_QUERY
);
1361 #if OSL_DEBUG_LEVEL > 0
1362 ::rtl::OString
sTrace( "FmTextControlShell::focusGained: 0x" );
1363 sTrace
+= ::rtl::OString::valueOf( (sal_IntPtr
)xControl
.get(), 16 );
1364 DBG_TRACE( sTrace
);
1367 DBG_ASSERT( xControl
.is(), "FmTextControlShell::focusGained: suspicious focus event!" );
1368 if ( xControl
.is() )
1369 controlActivated( xControl
);
1372 //------------------------------------------------------------------------
1373 void FmTextControlShell::focusLost( const ::com::sun::star::awt::FocusEvent
& _rEvent
)
1375 Reference
< XControl
> xControl( _rEvent
.Source
, UNO_QUERY
);
1377 #if OSL_DEBUG_LEVEL > 0
1378 ::rtl::OString
sTrace( "FmTextControlShell::focusLost: 0x" );
1379 sTrace
+= ::rtl::OString::valueOf( (sal_IntPtr
)xControl
.get(), 16 );
1380 DBG_TRACE( sTrace
);
1383 m_bActiveControl
= false;
1386 //------------------------------------------------------------------------
1387 void FmTextControlShell::ForgetActiveControl()
1389 implClearActiveControlRef();
1392 //------------------------------------------------------------------------
1393 void FmTextControlShell::contextMenuRequested( const awt::MouseEvent
& /*_rEvent*/ )
1395 m_rBindings
.GetDispatcher()->ExecutePopup( SVX_RES( RID_FM_TEXTATTRIBUTE_MENU
) );
1398 //........................................................................
1400 //........................................................................