update dev300-m58
[ooovba.git] / svx / source / form / fmtextcontrolshell.cxx
blob7555b3d30d5addc738178ef020ac26eb8793f9fa
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
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"
34 #include "fmprop.hrc"
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>
81 #include <memory>
83 //........................................................................
84 namespace svx
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[] =
104 SID_CUT,
105 SID_COPY,
106 SID_PASTE,
107 SID_SELECTALL,
108 // SID_ATTR_TABSTOP, /* 2 */
109 SID_ATTR_CHAR_FONT,
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,
118 SID_ATTR_CHAR_COLOR,
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,
136 SID_SET_SUB_SCRIPT,
137 SID_CHAR_DLG,
138 SID_PARA_DLG,
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[] =
154 SID_ATTR_TABSTOP,
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
184 private:
185 IFocusObserver* m_pObserver;
186 Reference< XWindow > m_xWindow;
188 public:
189 FmFocusListenerAdapter( const Reference< XControl >& _rxControl, IFocusObserver* _pObserver );
191 // clean up the instance
192 void dispose();
194 protected:
195 ~FmFocusListenerAdapter();
197 protected:
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()
231 acquire();
232 dispose();
234 DBG_DTOR( FmFocusListenerAdapter, NULL );
237 //--------------------------------------------------------------------
238 void FmFocusListenerAdapter::dispose()
240 if ( m_xWindow.is() )
242 m_xWindow->removeFocusListener( this );
243 m_xWindow.clear();
247 //--------------------------------------------------------------------
248 void SAL_CALL FmFocusListenerAdapter::focusGained( const FocusEvent& e ) throw (RuntimeException)
250 if ( m_pObserver )
251 m_pObserver->focusGained( e );
254 //--------------------------------------------------------------------
255 void SAL_CALL FmFocusListenerAdapter::focusLost( const FocusEvent& e ) throw (RuntimeException)
257 if ( m_pObserver )
258 m_pObserver->focusLost( e );
261 //--------------------------------------------------------------------
262 void SAL_CALL FmFocusListenerAdapter::disposing( const EventObject& Source ) throw (RuntimeException)
264 (void)Source;
265 DBG_ASSERT( Source.Source == m_xWindow, "FmFocusListenerAdapter::disposing: where did this come from?" );
266 m_xWindow.clear();
269 //====================================================================
270 //= FmMouseListenerAdapter
271 //====================================================================
272 typedef ::cppu::WeakImplHelper1 < XMouseListener
273 > FmMouseListenerAdapter_Base;
274 class FmMouseListenerAdapter : public FmMouseListenerAdapter_Base
276 private:
277 IContextRequestObserver* m_pObserver;
278 Reference< XWindow > m_xWindow;
280 public:
281 FmMouseListenerAdapter( const Reference< XControl >& _rxControl, IContextRequestObserver* _pObserver );
283 // clean up the instance
284 void dispose();
286 protected:
287 ~FmMouseListenerAdapter();
289 protected:
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()
328 acquire();
329 dispose();
331 DBG_DTOR( FmMouseListenerAdapter, NULL );
334 //--------------------------------------------------------------------
335 void FmMouseListenerAdapter::dispose()
337 if ( m_xWindow.is() )
339 m_xWindow->removeMouseListener( this );
340 m_xWindow.clear();
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 )
351 if ( m_pObserver )
352 m_pObserver->contextMenuRequested( _rEvent );
356 //--------------------------------------------------------------------
357 void SAL_CALL FmMouseListenerAdapter::mouseReleased( const awt::MouseEvent& /*e*/ ) throw (::com::sun::star::uno::RuntimeException)
359 // not interested in
362 //--------------------------------------------------------------------
363 void SAL_CALL FmMouseListenerAdapter::mouseEntered( const awt::MouseEvent& /*e*/ ) throw (::com::sun::star::uno::RuntimeException)
365 // not interested in
368 //--------------------------------------------------------------------
369 void SAL_CALL FmMouseListenerAdapter::mouseExited( const awt::MouseEvent& /*e*/ ) throw (::com::sun::star::uno::RuntimeException)
371 // not interested in
374 //--------------------------------------------------------------------
375 void SAL_CALL FmMouseListenerAdapter::disposing( const EventObject& Source ) throw (RuntimeException)
377 (void)Source;
378 DBG_ASSERT( Source.Source == m_xWindow, "FmMouseListenerAdapter::disposing: where did this come from?" );
379 m_xWindow.clear();
382 //====================================================================
383 //= FmTextControlShell
384 //====================================================================
385 //------------------------------------------------------------------------
386 namespace
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 );
402 else
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 ) );
412 else
413 _rSet.Put( SfxBoolItem( nWhich, bState ) );
415 break;
417 default:
419 Sequence< PropertyValue > aComplexState;
420 if ( _rUnoState >>= aComplexState )
422 if ( !aComplexState.getLength() )
423 _rSet.InvalidateItem( nWhich );
424 else
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?" );
430 if ( pTransformed )
431 _rSet.Put( *pTransformed );
432 else
433 _rSet.InvalidateItem( nWhich );
436 else
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;
454 if ( pSlot )
456 pAsciiUnoName = pSlot->GetUnoName();
458 else
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
462 switch ( _nSlotId )
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;
470 if ( pAsciiUnoName )
472 sSlotUnoName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:" ) );
473 sSlotUnoName += ::rtl::OUString::createFromAscii( pAsciiUnoName );
475 #if OSL_DEBUG_LEVEL > 0
476 else
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 );
481 sMessage += ")";
482 DBG_ERROR( sMessage );
484 #endif
485 return sSlotUnoName;
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;
503 else
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();
534 return pWindow;
537 //....................................................................
538 bool lcl_isRichText( const Reference< XControl >& _rxControl )
540 if ( !_rxControl.is() )
541 return false;
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();
560 return bIsRichText;
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()
580 dispose();
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;
594 return 0L;
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();
604 ++aFeature
607 SfxSlotId nSlotId( aFeature->first );
608 #if OSL_DEBUG_LEVEL > 0
609 ::rtl::OUString sUnoSlotName;
610 if ( SFX_APP() )
611 sUnoSlotName = lcl_getUnoSlotName( *SFX_APP(), nSlotId );
612 else
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 += "\"";
617 #endif
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.
632 switch ( nSlotId )
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 );
644 if ( bIsInPool )
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 );
653 #endif
655 lcl_translateUnoStateToItem( nSlotId, aFeature->second->getFeatureState(), _rSet );
657 #if OSL_DEBUG_LEVEL > 0
658 else
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 );
665 #endif
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!" );
674 if ( !pFontList )
675 return;
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( );
719 if ( !bFound )
721 aFeaturePos = aAdditionalFestures.find( nSlotForDispatcher );
722 bFound = aFeaturePos != aAdditionalFestures.end( );
725 if ( bFound )
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
740 // handle them
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?!" );
745 if ( pBoolItem )
747 aArgs.realloc( 1 );
748 aArgs[ 0 ].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Enable" ) );
749 aArgs[ 0 ].Value <<= (sal_Bool)pBoolItem->GetValue();
753 // dispatch this
754 aFeaturePos->second->dispatch( aArgs );
756 #if OSL_DEBUG_LEVEL > 0
757 else
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 );
767 else
768 sError += "unknown (no SfxSlot)";
769 DBG_ERROR( sError.getStr() );
771 #endif
774 _rReq.Done( rModifiedItems );
777 pDialog.reset();
778 pCurrentItems.reset();
779 pPureItems.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 ) );
792 return true;
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() )
809 switch ( _nSlot )
811 case SID_COPY:
812 case SID_CUT:
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() );
822 break;
823 case SID_PASTE:
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 );
830 break;
831 default:
832 OSL_ENSURE( sal_False, "FmTextControlShell::executeClipboardSlot: invalid slot!" );
834 return true;
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() )
852 // special slots
853 switch ( nSlot )
855 case SID_CHAR_DLG:
856 executeAttributeDialog( eCharAttribs, _rReq );
857 break;
859 case SID_PARA_DLG:
860 executeAttributeDialog( eParaAttribs, _rReq );
861 break;
863 case SID_SELECTALL:
864 executeSelectAll();
865 break;
867 case SID_CUT:
868 case SID_COPY:
869 case SID_PASTE:
870 executeClipboardSlot( nSlot );
871 break;
873 default:
874 DBG_ASSERT( aFeaturePos != m_aControlFeatures.end(), "FmTextControShell::ExecuteTextAttribute: I have no such dispatcher, and cannot handle it at all!" );
875 return;
878 else
880 // slots which are dispatched to the control
882 switch ( nSlot )
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!" );
897 if ( pTextLine )
899 FontUnderline eTL = pTextLine->GetLineStyle();
900 if ( SID_ATTR_CHAR_UNDERLINE == nSlot ) {
901 aToggled.Put( SvxUnderlineItem( eTL == UNDERLINE_SINGLE ? UNDERLINE_NONE : UNDERLINE_SINGLE, nWhich ) );
902 } else {
903 aToggled.Put( SvxOverlineItem( eTL == UNDERLINE_SINGLE ? UNDERLINE_NONE : UNDERLINE_SINGLE, nWhich ) );
907 else
909 const SvxCrossedOutItem* pCrossedOut = PTR_CAST( SvxCrossedOutItem, pItem );
910 DBG_ASSERT( pCrossedOut, "FmTextControlShell::ExecuteTextAttribute: ooops - no CrossedOut item!" );
911 if ( pCrossedOut )
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 );
922 break;
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;
935 if ( pArgs )
936 TransformItems( nSlot, *pArgs, aArgs );
937 aFeaturePos->second->dispatch( aArgs );
939 break;
941 default:
942 if ( aFeaturePos->second->isFeatureEnabled() )
943 aFeaturePos->second->dispatch();
944 break;
947 _rReq.Done();
950 //------------------------------------------------------------------------
951 void FmTextControlShell::GetTextAttributeState( SfxItemSet& _rSet )
953 SfxWhichIter aIter( _rSet );
954 sal_uInt16 nSlot = aIter.FirstWhich();
955 while ( nSlot )
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();
965 continue;
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 );
974 else
975 _rSet.DisableItem( nSlot );
977 else
979 bool bDisable = false;
981 bool bNeedWriteableControl = false;
982 bool bNeedTextComponent = false;
983 bool bNeedSelection = false;
985 switch ( nSlot )
987 case SID_CHAR_DLG:
988 case SID_PARA_DLG:
989 bDisable |= m_aControlFeatures.empty();
990 bNeedWriteableControl = true;
991 break;
993 case SID_CUT:
994 bNeedSelection = true;
995 bNeedTextComponent = true;
996 bNeedWriteableControl = true;
997 DBG_TRACE( "FmTextControlShell::ClipBoard: need to invalidate again" );
998 m_bNeedClipboardInvalidation = true;
999 break;
1001 case SID_PASTE:
1003 Window* pActiveControlVCLWindow = lcl_getWindow( m_xActiveControl );
1004 if ( pActiveControlVCLWindow )
1006 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pActiveControlVCLWindow) );
1007 bDisable |= !aDataHelper.HasFormat( SOT_FORMAT_STRING );
1009 else
1010 bDisable |= true;
1012 bNeedTextComponent = true;
1013 bNeedWriteableControl = true;
1015 break;
1017 case SID_COPY:
1018 bNeedTextComponent = true;
1019 bNeedSelection = true;
1020 break;
1022 case SID_SELECTALL:
1023 bNeedTextComponent = true;
1024 break;
1026 default:
1027 // slot is unknown at all
1028 bDisable |= true;
1029 break;
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;
1045 if ( bDisable )
1046 _rSet.DisableItem( nSlot );
1049 nSlot = aIter.NextWhich();
1053 //------------------------------------------------------------------------
1054 bool FmTextControlShell::IsActiveControl( bool _bCountRichTextOnly ) const
1056 if ( _bCountRichTextOnly && !m_bActiveControlIsRichText )
1057 return false;
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 );
1084 #endif
1086 DBG_ASSERT( _rxController.is(), "FmTextControlShell::formActivated: invalid controller!" );
1087 if ( !_rxController.is() )
1088 return;
1090 // sometimes, a form controller notifies activations, even if it's already activated
1091 if ( m_xActiveController == _rxController )
1092 return;
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 );
1112 #endif
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() )
1126 return;
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();
1162 ++aLoop
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();
1180 ++aLoop
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!" );
1243 #endif
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 );
1270 if ( m_pViewFrame )
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;
1304 while ( *pSlots )
1306 FmTextControlFeature* pDispatcher = implGetFeatureDispatcher( xProvider, pApplication, *pSlots );
1307 if ( pDispatcher )
1308 _rDispatchers.insert( ControlFeatures::value_type( *pSlots, ControlFeature( pDispatcher ) ) );
1310 ++pSlots;
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)!" );
1338 URL aFeatureURL;
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 );
1344 return NULL;
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 );
1365 #endif
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 );
1381 #endif
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 //........................................................................
1399 } // namespace svx
1400 //........................................................................