Version 4.3.0.0.beta1, tag libreoffice-4.3.0.0.beta1
[LibreOffice.git] / svx / source / form / fmtextcontrolshell.cxx
blobbc46692250ec0ffb148408c05719d07a20e1161e
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/processfactory.hxx>
45 #include <cppuhelper/implbase1.hxx>
46 #include <sfx2/app.hxx>
47 #include <sfx2/bindings.hxx>
48 #include <sfx2/dispatch.hxx>
49 #include <sfx2/msgpool.hxx>
50 #include <sfx2/objsh.hxx>
51 #include <sfx2/request.hxx>
52 #include <sfx2/sfxuno.hxx>
53 #include <sfx2/viewfrm.hxx>
54 #include <svl/eitem.hxx>
55 #include <svl/intitem.hxx>
56 #include <svl/itempool.hxx>
57 #include <svl/languageoptions.hxx>
58 #include <svtools/stringtransfer.hxx>
59 #include <svl/whiter.hxx>
60 #include <toolkit/helper/vclunohelper.hxx>
61 #include <tools/diagnose_ex.h>
62 #include <vcl/msgbox.hxx>
63 #include <vcl/outdev.hxx>
64 #include <osl/mutex.hxx>
67 namespace svx
71 using namespace ::com::sun::star;
72 using namespace ::com::sun::star::uno;
73 using namespace ::com::sun::star::awt;
74 using namespace ::com::sun::star::form;
75 using namespace ::com::sun::star::form::runtime;
76 using namespace ::com::sun::star::lang;
77 using namespace ::com::sun::star::frame;
78 using namespace ::com::sun::star::util;
79 using namespace ::com::sun::star::beans;
80 using namespace ::com::sun::star::container;
83 typedef sal_uInt16 WhichId;
86 static SfxSlotId pTextControlSlots[] =
88 SID_CLIPBOARD_FORMAT_ITEMS,
89 SID_CUT,
90 SID_COPY,
91 SID_PASTE,
92 SID_SELECTALL,
93 // SID_ATTR_TABSTOP, /* 2 */
94 SID_ATTR_CHAR_FONT,
95 SID_ATTR_CHAR_POSTURE,
96 SID_ATTR_CHAR_WEIGHT,
97 SID_ATTR_CHAR_SHADOWED,
98 SID_ATTR_CHAR_WORDLINEMODE,
99 SID_ATTR_CHAR_CONTOUR,
100 SID_ATTR_CHAR_STRIKEOUT,
101 SID_ATTR_CHAR_UNDERLINE,
102 SID_ATTR_CHAR_FONTHEIGHT,
103 SID_ATTR_CHAR_COLOR,
104 SID_ATTR_CHAR_KERNING,
105 SID_ATTR_CHAR_LANGUAGE, /* 20 */
106 SID_ATTR_CHAR_ESCAPEMENT,
107 SID_ATTR_PARA_ADJUST, /* 28 */
108 SID_ATTR_PARA_ADJUST_LEFT,
109 SID_ATTR_PARA_ADJUST_RIGHT,
110 SID_ATTR_PARA_ADJUST_CENTER,
111 SID_ATTR_PARA_ADJUST_BLOCK,
112 SID_ATTR_PARA_LINESPACE, /* 33 */
113 SID_ATTR_PARA_LINESPACE_10,
114 SID_ATTR_PARA_LINESPACE_15,
115 SID_ATTR_PARA_LINESPACE_20,
116 SID_ATTR_LRSPACE, /* 48 */
117 SID_ATTR_ULSPACE, /* 49 */
118 SID_ATTR_CHAR_AUTOKERN,
119 SID_SET_SUPER_SCRIPT,
120 SID_SET_SUB_SCRIPT,
121 SID_CHAR_DLG,
122 SID_PARA_DLG,
123 // SID_TEXTDIRECTION_LEFT_TO_RIGHT, /* 907 */
124 // SID_TEXTDIRECTION_TOP_TO_BOTTOM,
125 SID_ATTR_CHAR_SCALEWIDTH, /* 911 */
126 SID_ATTR_CHAR_RELIEF,
127 SID_ATTR_PARA_LEFT_TO_RIGHT, /* 950 */
128 SID_ATTR_PARA_RIGHT_TO_LEFT,
129 SID_ATTR_CHAR_OVERLINE,
133 // slots which we are not responsible for on the SfxShell level, but
134 // need to handle during the "paragraph attributes" and/or "character
135 // attributes" dialogs
136 static SfxSlotId pDialogSlots[] =
138 SID_ATTR_TABSTOP,
139 SID_ATTR_PARA_HANGPUNCTUATION,
140 SID_ATTR_PARA_FORBIDDEN_RULES,
141 SID_ATTR_PARA_SCRIPTSPACE,
142 SID_ATTR_CHAR_LATIN_LANGUAGE,
143 SID_ATTR_CHAR_CJK_LANGUAGE,
144 SID_ATTR_CHAR_CTL_LANGUAGE,
145 SID_ATTR_CHAR_LATIN_FONT,
146 SID_ATTR_CHAR_CJK_FONT,
147 SID_ATTR_CHAR_CTL_FONT,
148 SID_ATTR_CHAR_LATIN_FONTHEIGHT,
149 SID_ATTR_CHAR_CJK_FONTHEIGHT,
150 SID_ATTR_CHAR_CTL_FONTHEIGHT,
151 SID_ATTR_CHAR_LATIN_WEIGHT,
152 SID_ATTR_CHAR_CJK_WEIGHT,
153 SID_ATTR_CHAR_CTL_WEIGHT,
154 SID_ATTR_CHAR_LATIN_POSTURE,
155 SID_ATTR_CHAR_CJK_POSTURE,
156 SID_ATTR_CHAR_CTL_POSTURE,
157 SID_ATTR_CHAR_EMPHASISMARK,
162 //= FmFocusListenerAdapter
164 typedef ::cppu::WeakImplHelper1 < XFocusListener
165 > FmFocusListenerAdapter_Base;
166 class FmFocusListenerAdapter : public FmFocusListenerAdapter_Base
168 private:
169 IFocusObserver* m_pObserver;
170 Reference< XWindow > m_xWindow;
172 public:
173 FmFocusListenerAdapter( const Reference< XControl >& _rxControl, IFocusObserver* _pObserver );
175 // clean up the instance
176 void dispose();
178 protected:
179 virtual ~FmFocusListenerAdapter();
181 protected:
182 virtual void SAL_CALL focusGained( const FocusEvent& e ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
183 virtual void SAL_CALL focusLost( const FocusEvent& e ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
184 virtual void SAL_CALL disposing( const EventObject& Source ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
189 FmFocusListenerAdapter::FmFocusListenerAdapter( const Reference< XControl >& _rxControl, IFocusObserver* _pObserver )
190 :m_pObserver( _pObserver )
191 ,m_xWindow( _rxControl, UNO_QUERY )
194 DBG_ASSERT( m_xWindow.is(), "FmFocusListenerAdapter::FmFocusListenerAdapter: invalid control!" );
195 osl_atomic_increment( &m_refCount );
199 if ( m_xWindow.is() )
200 m_xWindow->addFocusListener( this );
202 catch( const Exception& )
204 DBG_UNHANDLED_EXCEPTION();
207 osl_atomic_decrement( &m_refCount );
211 FmFocusListenerAdapter::~FmFocusListenerAdapter()
213 acquire();
214 dispose();
219 void FmFocusListenerAdapter::dispose()
221 if ( m_xWindow.is() )
223 m_xWindow->removeFocusListener( this );
224 m_xWindow.clear();
229 void SAL_CALL FmFocusListenerAdapter::focusGained( const FocusEvent& e ) throw (RuntimeException, std::exception)
231 if ( m_pObserver )
232 m_pObserver->focusGained( e );
236 void SAL_CALL FmFocusListenerAdapter::focusLost( const FocusEvent& e ) throw (RuntimeException, std::exception)
238 if ( m_pObserver )
239 m_pObserver->focusLost( e );
243 void SAL_CALL FmFocusListenerAdapter::disposing( const EventObject& Source ) throw (RuntimeException, std::exception)
245 (void)Source;
246 DBG_ASSERT( Source.Source == m_xWindow, "FmFocusListenerAdapter::disposing: where did this come from?" );
247 m_xWindow.clear();
251 //= FmMouseListenerAdapter
253 typedef ::cppu::WeakImplHelper1 < XMouseListener
254 > FmMouseListenerAdapter_Base;
255 class FmMouseListenerAdapter : public FmMouseListenerAdapter_Base
257 private:
258 IContextRequestObserver* m_pObserver;
259 Reference< XWindow > m_xWindow;
261 public:
262 FmMouseListenerAdapter( const Reference< XControl >& _rxControl, IContextRequestObserver* _pObserver );
264 // clean up the instance
265 void dispose();
267 protected:
268 virtual ~FmMouseListenerAdapter();
270 protected:
271 virtual void SAL_CALL mousePressed( const awt::MouseEvent& e ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
272 virtual void SAL_CALL mouseReleased( const awt::MouseEvent& e ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
273 virtual void SAL_CALL mouseEntered( const awt::MouseEvent& e ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
274 virtual void SAL_CALL mouseExited( const awt::MouseEvent& e ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
275 virtual void SAL_CALL disposing( const EventObject& Source ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
279 //= FmMouseListenerAdapter
283 FmMouseListenerAdapter::FmMouseListenerAdapter( const Reference< XControl >& _rxControl, IContextRequestObserver* _pObserver )
284 :m_pObserver( _pObserver )
285 ,m_xWindow( _rxControl, UNO_QUERY )
288 DBG_ASSERT( m_xWindow.is(), "FmMouseListenerAdapter::FmMouseListenerAdapter: invalid control!" );
289 osl_atomic_increment( &m_refCount );
293 if ( m_xWindow.is() )
294 m_xWindow->addMouseListener( this );
296 catch( const Exception& )
298 DBG_UNHANDLED_EXCEPTION();
301 osl_atomic_decrement( &m_refCount );
305 FmMouseListenerAdapter::~FmMouseListenerAdapter()
307 acquire();
308 dispose();
313 void FmMouseListenerAdapter::dispose()
315 if ( m_xWindow.is() )
317 m_xWindow->removeMouseListener( this );
318 m_xWindow.clear();
323 void SAL_CALL FmMouseListenerAdapter::mousePressed( const awt::MouseEvent& _rEvent ) throw (::com::sun::star::uno::RuntimeException, std::exception)
325 SolarMutexGuard aGuard;
326 // is this a request for a context menu?
327 if ( _rEvent.PopupTrigger )
329 if ( m_pObserver )
330 m_pObserver->contextMenuRequested( _rEvent );
335 void SAL_CALL FmMouseListenerAdapter::mouseReleased( const awt::MouseEvent& /*e*/ ) throw (::com::sun::star::uno::RuntimeException, std::exception)
337 // not interested in
341 void SAL_CALL FmMouseListenerAdapter::mouseEntered( const awt::MouseEvent& /*e*/ ) throw (::com::sun::star::uno::RuntimeException, std::exception)
343 // not interested in
347 void SAL_CALL FmMouseListenerAdapter::mouseExited( const awt::MouseEvent& /*e*/ ) throw (::com::sun::star::uno::RuntimeException, std::exception)
349 // not interested in
353 void SAL_CALL FmMouseListenerAdapter::disposing( const EventObject& Source ) throw (RuntimeException, std::exception)
355 (void)Source;
356 DBG_ASSERT( Source.Source == m_xWindow, "FmMouseListenerAdapter::disposing: where did this come from?" );
357 m_xWindow.clear();
361 //= FmTextControlShell
364 namespace
367 void lcl_translateUnoStateToItem( SfxSlotId _nSlot, const Any& _rUnoState, SfxItemSet& _rSet )
369 WhichId nWhich = _rSet.GetPool()->GetWhich( _nSlot );
370 if ( !_rUnoState.hasValue() )
372 if ( ( _nSlot != SID_CUT )
373 && ( _nSlot != SID_COPY )
374 && ( _nSlot != SID_PASTE )
377 _rSet.InvalidateItem( nWhich );
380 else
382 switch ( _rUnoState.getValueType().getTypeClass() )
384 case TypeClass_BOOLEAN:
386 bool bState = false;
387 _rUnoState >>= bState;
388 if ( _nSlot == SID_ATTR_PARA_SCRIPTSPACE )
389 _rSet.Put( SvxScriptSpaceItem( bState, nWhich ) );
390 else
391 _rSet.Put( SfxBoolItem( nWhich, bState ) );
393 break;
395 default:
397 Sequence< PropertyValue > aComplexState;
398 if ( _rUnoState >>= aComplexState )
400 if ( !aComplexState.getLength() )
401 _rSet.InvalidateItem( nWhich );
402 else
404 SfxAllItemSet aAllItems( _rSet );
405 TransformParameters( _nSlot, aComplexState, aAllItems );
406 const SfxPoolItem* pTransformed = aAllItems.GetItem( nWhich );
407 OSL_ENSURE( pTransformed, "lcl_translateUnoStateToItem: non-empty parameter sequence leading to empty item?" );
408 if ( pTransformed )
409 _rSet.Put( *pTransformed );
410 else
411 _rSet.InvalidateItem( nWhich );
414 else
416 OSL_FAIL( "lcl_translateUnoStateToItem: invalid state!" );
424 OUString lcl_getUnoSlotName( SfxApplication&, SfxSlotId _nSlotId )
426 OUString sSlotUnoName;
428 SfxSlotPool& rSlotPool = SfxSlotPool::GetSlotPool( NULL );
429 const SfxSlot* pSlot = rSlotPool.GetSlot( _nSlotId );
431 const sal_Char* pAsciiUnoName = NULL;
432 if ( pSlot )
434 pAsciiUnoName = pSlot->GetUnoName();
436 else
438 // some hard-coded slots, which do not have a UNO name at SFX level, but which
439 // we nevertheless need to transport via UNO mechanisms, so we need a name
440 switch ( _nSlotId )
442 case SID_ATTR_PARA_HANGPUNCTUATION: pAsciiUnoName = "AllowHangingPunctuation"; break;
443 case SID_ATTR_PARA_FORBIDDEN_RULES: pAsciiUnoName = "ApplyForbiddenCharacterRules"; break;
444 case SID_ATTR_PARA_SCRIPTSPACE: pAsciiUnoName = "UseScriptSpacing"; break;
448 if ( pAsciiUnoName )
450 sSlotUnoName = ".uno:";
451 sSlotUnoName += OUString::createFromAscii( pAsciiUnoName );
453 #if OSL_DEBUG_LEVEL > 0
454 else
456 OString sMessage( "lcl_getUnoSlotName: invalid slot id, or invalid slot, or no UNO name!\n" );
457 sMessage += "(slot id: ";
458 sMessage += OString::number( _nSlotId );
459 sMessage += ")";
460 OSL_FAIL( sMessage.getStr() );
462 #endif
463 return sSlotUnoName;
467 bool lcl_determineReadOnly( const Reference< XControl >& _rxControl )
469 bool bIsReadOnlyModel = true;
472 Reference< XPropertySet > xModelProps;
473 if ( _rxControl.is() )
474 xModelProps = xModelProps.query( _rxControl->getModel() );
475 Reference< XPropertySetInfo > xModelPropInfo;
476 if ( xModelProps.is() )
477 xModelPropInfo = xModelProps->getPropertySetInfo();
479 if ( !xModelPropInfo.is() || !xModelPropInfo->hasPropertyByName( FM_PROP_READONLY ) )
480 bIsReadOnlyModel = true;
481 else
483 bool bReadOnly = true;
484 xModelProps->getPropertyValue( FM_PROP_READONLY ) >>= bReadOnly;
485 bIsReadOnlyModel = bReadOnly;
488 catch( const Exception& )
490 DBG_UNHANDLED_EXCEPTION();
492 return bIsReadOnlyModel;
496 static Window* lcl_getWindow( const Reference< XControl >& _rxControl )
498 Window* pWindow = NULL;
501 Reference< XWindowPeer > xControlPeer;
502 if ( _rxControl.is() )
503 xControlPeer = _rxControl->getPeer();
504 if ( xControlPeer.is() )
505 pWindow = VCLUnoHelper::GetWindow( xControlPeer );
507 catch( const Exception& )
509 DBG_UNHANDLED_EXCEPTION();
512 return pWindow;
516 bool lcl_isRichText( const Reference< XControl >& _rxControl )
518 if ( !_rxControl.is() )
519 return false;
521 bool bIsRichText = false;
524 Reference< XPropertySet > xModelProps( _rxControl->getModel(), UNO_QUERY );
525 Reference< XPropertySetInfo > xPSI;
526 if ( xModelProps.is() )
527 xPSI = xModelProps->getPropertySetInfo();
528 OUString sRichTextPropertyName = "RichText";
529 if ( xPSI.is() && xPSI->hasPropertyByName( sRichTextPropertyName ) )
531 OSL_VERIFY( xModelProps->getPropertyValue( sRichTextPropertyName ) >>= bIsRichText );
534 catch( const Exception& )
536 DBG_UNHANDLED_EXCEPTION();
538 return bIsRichText;
543 FmTextControlShell::FmTextControlShell( SfxViewFrame* _pFrame )
544 :m_bActiveControl( false )
545 ,m_bActiveControlIsReadOnly( true )
546 ,m_bActiveControlIsRichText( false )
547 ,m_pViewFrame( _pFrame )
548 ,m_rBindings( _pFrame->GetBindings() )
549 ,m_bNeedClipboardInvalidation( true )
551 m_aClipboardInvalidation.SetTimeoutHdl( LINK( this, FmTextControlShell, OnInvalidateClipboard ) );
552 m_aClipboardInvalidation.SetTimeout( 200 );
556 FmTextControlShell::~FmTextControlShell()
558 dispose();
562 IMPL_LINK( FmTextControlShell, OnInvalidateClipboard, void*, /*_pNotInterestedIn*/ )
564 if ( m_bNeedClipboardInvalidation )
566 OSL_TRACE( "FmTextControlShell::ClipBoard: invalidating clipboard slots" );
567 m_rBindings.Invalidate( SID_CUT );
568 m_rBindings.Invalidate( SID_COPY );
569 m_rBindings.Invalidate( SID_PASTE );
570 m_bNeedClipboardInvalidation = false;
572 return 0L;
576 void FmTextControlShell::transferFeatureStatesToItemSet( ControlFeatures& _rDispatchers, SfxAllItemSet& _rSet, bool _bTranslateLatin )
578 SfxItemPool& rPool = *_rSet.GetPool();
580 for ( ControlFeatures::const_iterator aFeature = _rDispatchers.begin();
581 aFeature != _rDispatchers.end();
582 ++aFeature
585 SfxSlotId nSlotId( aFeature->first );
586 #if OSL_DEBUG_LEVEL > 0
587 OUString sUnoSlotName;
588 if ( SFX_APP() )
589 sUnoSlotName = lcl_getUnoSlotName( *SFX_APP(), nSlotId );
590 else
591 sUnoSlotName = "<unknown>";
592 OString sUnoSlotNameAscii( "\"" );
593 sUnoSlotNameAscii += OString( sUnoSlotName.getStr(), sUnoSlotName.getLength(), RTL_TEXTENCODING_ASCII_US );
594 sUnoSlotNameAscii += "\"";
595 #endif
597 if ( _bTranslateLatin )
599 // A rich text control offers a dispatcher for the "Font" slot/feature.
600 // Sadly, the semantics of the dispatches is that the feature "Font" depends
601 // on the current cursor position: If it's on latin text, it's the "latin font"
602 // which is set up at the control. If it's on CJK text, it's the "CJK font", and
603 // aequivalent for "CTL font".
604 // The same holds for some other font related features/slots.
605 // Thus, we have separate dispatches for "Latin Font", "Latin Font Size", etc,
606 // which are only "virtual", in a sense that there exist no item with this id.
607 // So when we encounter such a dispatcher for, say, "Latin Font", we need to
608 // put an item into the set which has the "Font" id.
610 switch ( nSlotId )
612 case SID_ATTR_CHAR_LATIN_FONT: nSlotId = SID_ATTR_CHAR_FONT; break;
613 case SID_ATTR_CHAR_LATIN_FONTHEIGHT:nSlotId = SID_ATTR_CHAR_FONTHEIGHT; break;
614 case SID_ATTR_CHAR_LATIN_LANGUAGE: nSlotId = SID_ATTR_CHAR_LANGUAGE; break;
615 case SID_ATTR_CHAR_LATIN_POSTURE: nSlotId = SID_ATTR_CHAR_POSTURE; break;
616 case SID_ATTR_CHAR_LATIN_WEIGHT: nSlotId = SID_ATTR_CHAR_WEIGHT; break;
620 WhichId nWhich = rPool.GetWhich( nSlotId );
621 bool bIsInPool = rPool.IsInRange( nWhich );
622 if ( bIsInPool )
624 #if OSL_DEBUG_LEVEL > 0
625 bool bFeatureIsEnabled = aFeature->second->isFeatureEnabled();
626 OString sMessage( "FmTextControlShell::transferFeatureStatesToItemSet: found a feature state for " );
627 sMessage += sUnoSlotNameAscii;
628 if ( !bFeatureIsEnabled )
629 sMessage += " (disabled)";
630 OSL_TRACE( "%s", sMessage.getStr() );
631 #endif
633 lcl_translateUnoStateToItem( nSlotId, aFeature->second->getFeatureState(), _rSet );
635 #if OSL_DEBUG_LEVEL > 0
636 else
638 OString sMessage( "FmTextControlShell::transferFeatureStatesToItemSet: found a feature state for " );
639 sMessage += sUnoSlotNameAscii;
640 sMessage += ", but could not translate it into an item!";
641 OSL_TRACE( "%s", sMessage.getStr() );
643 #endif
648 void FmTextControlShell::executeAttributeDialog( AttributeSet _eSet, SfxRequest& _rReq )
650 const SvxFontListItem* pFontList = PTR_CAST( SvxFontListItem, m_pViewFrame->GetObjectShell()->GetItem( SID_ATTR_CHAR_FONTLIST ) );
651 DBG_ASSERT( pFontList, "FmTextControlShell::executeAttributeDialog: no font list item!" );
652 if ( !pFontList )
653 return;
655 SfxItemPool* pPool = EditEngine::CreatePool();
656 pPool->FreezeIdRanges();
657 boost::scoped_ptr< SfxItemSet > xPureItems( new SfxItemSet( *pPool ) );
659 // put the current states of the items into the set
660 boost::scoped_ptr<SfxAllItemSet> xCurrentItems( new SfxAllItemSet( *xPureItems ) );
661 transferFeatureStatesToItemSet( m_aControlFeatures, *xCurrentItems );
663 // additional items, which we are not responsible for at the SfxShell level,
664 // but which need to be forwarded to the dialog, anyway
665 ControlFeatures aAdditionalFestures;
666 fillFeatureDispatchers( m_xActiveControl, pDialogSlots, aAdditionalFestures );
667 transferFeatureStatesToItemSet( aAdditionalFestures, *xCurrentItems, true );
669 boost::scoped_ptr<SfxTabDialog> xDialog ( _eSet == eCharAttribs
670 ? static_cast< SfxTabDialog* >( new TextControlCharAttribDialog( NULL, *xCurrentItems, *pFontList ) )
671 : static_cast< SfxTabDialog* >( new TextControlParaAttribDialog( NULL, *xCurrentItems ) ) );
672 if ( RET_OK == xDialog->Execute() )
674 const SfxItemSet& rModifiedItems = *xDialog->GetOutputItemSet();
675 for ( WhichId nWhich = pPool->GetFirstWhich(); nWhich <= pPool->GetLastWhich(); ++nWhich )
677 if ( rModifiedItems.GetItemState( nWhich ) == SFX_ITEM_SET )
679 SfxSlotId nSlotForItemSet = pPool->GetSlotId( nWhich );
680 const SfxPoolItem* pModifiedItem = rModifiedItems.GetItem( nWhich );
683 SfxSlotId nSlotForDispatcher = nSlotForItemSet;
684 switch ( nSlotForDispatcher )
686 case SID_ATTR_CHAR_FONT: nSlotForDispatcher = SID_ATTR_CHAR_LATIN_FONT; break;
687 case SID_ATTR_CHAR_FONTHEIGHT:nSlotForDispatcher = SID_ATTR_CHAR_LATIN_FONTHEIGHT; break;
688 case SID_ATTR_CHAR_LANGUAGE: nSlotForDispatcher = SID_ATTR_CHAR_LATIN_LANGUAGE; break;
689 case SID_ATTR_CHAR_POSTURE: nSlotForDispatcher = SID_ATTR_CHAR_LATIN_POSTURE; break;
690 case SID_ATTR_CHAR_WEIGHT: nSlotForDispatcher = SID_ATTR_CHAR_LATIN_WEIGHT; break;
693 // do we already have a dispatcher for this slot/feature?
694 ControlFeatures::const_iterator aFeaturePos = m_aControlFeatures.find( nSlotForDispatcher );
695 bool bFound = aFeaturePos != m_aControlFeatures.end( );
697 if ( !bFound )
699 aFeaturePos = aAdditionalFestures.find( nSlotForDispatcher );
700 bFound = aFeaturePos != aAdditionalFestures.end( );
703 if ( bFound )
705 Sequence< PropertyValue > aArgs;
706 // temporarily put the modified item into a "clean" set,
707 // and let TransformItems calc the respective UNO parameters
708 xPureItems->Put( *pModifiedItem );
709 TransformItems( nSlotForItemSet, *xPureItems, aArgs );
710 xPureItems->ClearItem( nWhich );
712 if ( ( nSlotForItemSet == SID_ATTR_PARA_HANGPUNCTUATION )
713 || ( nSlotForItemSet == SID_ATTR_PARA_FORBIDDEN_RULES )
714 || ( nSlotForItemSet == SID_ATTR_PARA_SCRIPTSPACE )
717 // these are no UNO slots, they need special handling since TransformItems cannot
718 // handle them
719 DBG_ASSERT( aArgs.getLength() == 0, "FmTextControlShell::executeAttributeDialog: these are no UNO slots - are they?" );
721 const SfxBoolItem* pBoolItem = PTR_CAST( SfxBoolItem, pModifiedItem );
722 DBG_ASSERT( pBoolItem, "FmTextControlShell::executeAttributeDialog: no bool item?!" );
723 if ( pBoolItem )
725 aArgs.realloc( 1 );
726 aArgs[ 0 ].Name = "Enable";
727 aArgs[ 0 ].Value <<= pBoolItem->GetValue();
731 // dispatch this
732 aFeaturePos->second->dispatch( aArgs );
734 #if OSL_DEBUG_LEVEL > 0
735 else
737 OString sError( "FmTextControShell::executeAttributeDialog: Could not handle the following item:" );
738 sError += "\n SlotID: "; sError += OString::number( nSlotForItemSet );
739 sError += "\n WhichID: "; sError += OString::number( nWhich );
740 sError += "\n UNO name: ";
742 OUString sUnoSlotName = lcl_getUnoSlotName( *SFX_APP(), nSlotForItemSet );
743 if ( !sUnoSlotName.isEmpty() )
744 sError += OString( sUnoSlotName.getStr(), sUnoSlotName.getLength(), RTL_TEXTENCODING_ASCII_US );
745 else
746 sError += "unknown (no SfxSlot)";
747 OSL_FAIL( sError.getStr() );
749 #endif
752 _rReq.Done( rModifiedItems );
755 xDialog.reset();
756 xCurrentItems.reset();
757 xPureItems.reset();
758 SfxItemPool::Free(pPool);
762 bool FmTextControlShell::executeSelectAll( )
766 if ( m_xActiveTextComponent.is() )
768 sal_Int32 nTextLen = m_xActiveTextComponent->getText().getLength();
769 m_xActiveTextComponent->setSelection( awt::Selection( 0, nTextLen ) );
770 return true;
773 catch( const Exception& )
775 DBG_UNHANDLED_EXCEPTION();
777 return false; // not handled
781 bool FmTextControlShell::executeClipboardSlot( SfxSlotId _nSlot )
785 if ( m_xActiveTextComponent.is() )
787 switch ( _nSlot )
789 case SID_COPY:
790 case SID_CUT:
792 OUString sSelectedText( m_xActiveTextComponent->getSelectedText() );
793 ::svt::OStringTransfer::CopyString( sSelectedText, lcl_getWindow( m_xActiveControl ) );
794 if ( SID_CUT == _nSlot )
796 awt::Selection aSelection( m_xActiveTextComponent->getSelection() );
797 m_xActiveTextComponent->insertText( aSelection, OUString() );
800 break;
801 case SID_PASTE:
803 OUString sClipboardContent;
804 OSL_VERIFY( ::svt::OStringTransfer::PasteString( sClipboardContent, lcl_getWindow( m_xActiveControl ) ) );
805 awt::Selection aSelection( m_xActiveTextComponent->getSelection() );
806 m_xActiveTextComponent->insertText( aSelection, sClipboardContent );
808 break;
809 default:
810 OSL_FAIL( "FmTextControlShell::executeClipboardSlot: invalid slot!" );
812 return true;
815 catch( const Exception& )
817 DBG_UNHANDLED_EXCEPTION();
819 return false; // not handled
823 void FmTextControlShell::ExecuteTextAttribute( SfxRequest& _rReq )
825 SfxSlotId nSlot = _rReq.GetSlot();
827 ControlFeatures::const_iterator aFeaturePos = m_aControlFeatures.find( nSlot );
828 if ( aFeaturePos == m_aControlFeatures.end() )
830 // special slots
831 switch ( nSlot )
833 case SID_CHAR_DLG:
834 executeAttributeDialog( eCharAttribs, _rReq );
835 break;
837 case SID_PARA_DLG:
838 executeAttributeDialog( eParaAttribs, _rReq );
839 break;
841 case SID_SELECTALL:
842 executeSelectAll();
843 break;
845 case SID_CUT:
846 case SID_COPY:
847 case SID_PASTE:
848 executeClipboardSlot( nSlot );
849 break;
851 default:
852 DBG_ASSERT( aFeaturePos != m_aControlFeatures.end(), "FmTextControShell::ExecuteTextAttribute: I have no such dispatcher, and cannot handle it at all!" );
853 return;
856 else
858 // slots which are dispatched to the control
860 switch ( nSlot )
862 case SID_ATTR_CHAR_STRIKEOUT:
863 case SID_ATTR_CHAR_UNDERLINE:
864 case SID_ATTR_CHAR_OVERLINE:
866 SfxItemSet aToggled( *_rReq.GetArgs() );
868 lcl_translateUnoStateToItem( nSlot, aFeaturePos->second->getFeatureState(), aToggled );
869 WhichId nWhich = aToggled.GetPool()->GetWhich( nSlot );
870 const SfxPoolItem* pItem = aToggled.GetItem( nWhich );
871 if ( ( SID_ATTR_CHAR_UNDERLINE == nSlot ) || ( SID_ATTR_CHAR_OVERLINE == nSlot ) )
873 const SvxOverlineItem* pTextLine = PTR_CAST( SvxOverlineItem, pItem );
874 DBG_ASSERT( pTextLine, "FmTextControlShell::ExecuteTextAttribute: ooops - no underline/overline item!" );
875 if ( pTextLine )
877 FontUnderline eTL = pTextLine->GetLineStyle();
878 if ( SID_ATTR_CHAR_UNDERLINE == nSlot ) {
879 aToggled.Put( SvxUnderlineItem( eTL == UNDERLINE_SINGLE ? UNDERLINE_NONE : UNDERLINE_SINGLE, nWhich ) );
880 } else {
881 aToggled.Put( SvxOverlineItem( eTL == UNDERLINE_SINGLE ? UNDERLINE_NONE : UNDERLINE_SINGLE, nWhich ) );
885 else
887 const SvxCrossedOutItem* pCrossedOut = PTR_CAST( SvxCrossedOutItem, pItem );
888 DBG_ASSERT( pCrossedOut, "FmTextControlShell::ExecuteTextAttribute: ooops - no CrossedOut item!" );
889 if ( pCrossedOut )
891 FontStrikeout eFS = pCrossedOut->GetStrikeout();
892 aToggled.Put( SvxCrossedOutItem( eFS == STRIKEOUT_SINGLE ? STRIKEOUT_NONE : STRIKEOUT_SINGLE, nWhich ) );
896 Sequence< PropertyValue > aArguments;
897 TransformItems( nSlot, aToggled, aArguments );
898 aFeaturePos->second->dispatch( aArguments );
900 break;
902 case SID_ATTR_CHAR_FONTHEIGHT:
903 case SID_ATTR_CHAR_FONT:
904 case SID_ATTR_CHAR_POSTURE:
905 case SID_ATTR_CHAR_WEIGHT:
906 case SID_ATTR_CHAR_SHADOWED:
907 case SID_ATTR_CHAR_CONTOUR:
908 case SID_SET_SUPER_SCRIPT:
909 case SID_SET_SUB_SCRIPT:
911 const SfxItemSet* pArgs = _rReq.GetArgs();
912 Sequence< PropertyValue > aArgs;
913 if ( pArgs )
914 TransformItems( nSlot, *pArgs, aArgs );
915 aFeaturePos->second->dispatch( aArgs );
917 break;
919 default:
920 if ( aFeaturePos->second->isFeatureEnabled() )
921 aFeaturePos->second->dispatch();
922 break;
925 _rReq.Done();
929 void FmTextControlShell::GetTextAttributeState( SfxItemSet& _rSet )
931 SfxWhichIter aIter( _rSet );
932 sal_uInt16 nSlot = aIter.FirstWhich();
933 while ( nSlot )
935 if ( ( nSlot == SID_ATTR_PARA_LEFT_TO_RIGHT )
936 || ( nSlot == SID_ATTR_PARA_RIGHT_TO_LEFT )
939 if ( !SvtLanguageOptions().IsCTLFontEnabled() )
941 _rSet.DisableItem( nSlot );
942 nSlot = aIter.NextWhich();
943 continue;
947 ControlFeatures::const_iterator aFeaturePos = m_aControlFeatures.find( nSlot );
948 if ( aFeaturePos != m_aControlFeatures.end() )
950 if ( aFeaturePos->second->isFeatureEnabled() )
951 lcl_translateUnoStateToItem( nSlot, aFeaturePos->second->getFeatureState(), _rSet );
952 else
953 _rSet.DisableItem( nSlot );
955 else
957 bool bDisable = false;
959 bool bNeedWriteableControl = false;
960 bool bNeedTextComponent = false;
961 bool bNeedSelection = false;
963 switch ( nSlot )
965 case SID_CHAR_DLG:
966 case SID_PARA_DLG:
967 bDisable |= m_aControlFeatures.empty();
968 bNeedWriteableControl = true;
969 break;
971 case SID_CUT:
972 bNeedSelection = true;
973 bNeedTextComponent = true;
974 bNeedWriteableControl = true;
975 OSL_TRACE( "FmTextControlShell::ClipBoard: need to invalidate again" );
976 m_bNeedClipboardInvalidation = true;
977 break;
979 case SID_PASTE:
981 Window* pActiveControlVCLWindow = lcl_getWindow( m_xActiveControl );
982 if ( pActiveControlVCLWindow )
984 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pActiveControlVCLWindow) );
985 bDisable |= !aDataHelper.HasFormat( SOT_FORMAT_STRING );
987 else
988 bDisable |= true;
990 bNeedTextComponent = true;
991 bNeedWriteableControl = true;
993 break;
995 case SID_COPY:
996 bNeedTextComponent = true;
997 bNeedSelection = true;
998 break;
1000 case SID_SELECTALL:
1001 bNeedTextComponent = true;
1002 break;
1004 default:
1005 // slot is unknown at all
1006 bDisable |= true;
1007 break;
1009 SAL_WARN_IF( bNeedSelection && !bNeedTextComponent, "svx.form", "FmTextControlShell::GetTextAttributeState: bNeedSelection should imply bNeedTextComponent!" );
1011 if ( !bDisable && bNeedWriteableControl )
1012 bDisable |= !IsActiveControl( ) || m_bActiveControlIsReadOnly;
1014 if ( !bDisable && bNeedTextComponent )
1015 bDisable |= !m_xActiveTextComponent.is();
1017 if ( !bDisable && bNeedSelection )
1019 awt::Selection aSelection = m_xActiveTextComponent->getSelection();
1020 bDisable |= aSelection.Min == aSelection.Max;
1023 if ( bDisable )
1024 _rSet.DisableItem( nSlot );
1027 nSlot = aIter.NextWhich();
1032 bool FmTextControlShell::IsActiveControl( bool _bCountRichTextOnly ) const
1034 if ( _bCountRichTextOnly && !m_bActiveControlIsRichText )
1035 return false;
1037 return m_bActiveControl;
1041 void FmTextControlShell::dispose()
1043 if ( IsActiveControl() )
1044 controlDeactivated();
1045 if ( isControllerListening() )
1046 stopControllerListening();
1050 void FmTextControlShell::designModeChanged( bool /*_bNewDesignMode*/ )
1052 m_rBindings.Invalidate( pTextControlSlots );
1056 void FmTextControlShell::formActivated( const Reference< XFormController >& _rxController )
1058 #if OSL_DEBUG_LEVEL > 0
1059 OString sTrace( "FmTextControlShell::formActivated: 0x" );
1060 sTrace += OString::number( (sal_IntPtr)_rxController.get(), 16 );
1061 OSL_TRACE( "%s", sTrace.getStr() );
1062 #endif
1064 DBG_ASSERT( _rxController.is(), "FmTextControlShell::formActivated: invalid controller!" );
1065 if ( !_rxController.is() )
1066 return;
1068 // sometimes, a form controller notifies activations, even if it's already activated
1069 if ( m_xActiveController == _rxController )
1070 return;
1074 startControllerListening( _rxController );
1075 controlActivated( _rxController->getCurrentControl() );
1077 catch( const Exception& )
1079 DBG_UNHANDLED_EXCEPTION();
1084 void FmTextControlShell::formDeactivated( const Reference< XFormController >& _rxController )
1086 #if OSL_DEBUG_LEVEL > 0
1087 OString sTrace( "FmTextControlShell::formDeactivated: 0x" );
1088 sTrace += OString::number( (sal_IntPtr)_rxController.get(), 16 );
1089 OSL_TRACE( "%s", sTrace.getStr() );
1090 #endif
1091 (void)_rxController;
1093 if ( IsActiveControl() )
1094 controlDeactivated();
1095 if ( isControllerListening() )
1096 stopControllerListening();
1100 void FmTextControlShell::startControllerListening( const Reference< XFormController >& _rxController )
1102 OSL_PRECOND( _rxController.is(), "FmTextControlShell::startControllerListening: invalid controller!" );
1103 if ( !_rxController.is() )
1104 return;
1106 OSL_PRECOND( !isControllerListening(), "FmTextControlShell::startControllerListening: already listening!" );
1107 if ( isControllerListening() )
1108 stopControllerListening( );
1109 DBG_ASSERT( !isControllerListening(), "FmTextControlShell::startControllerListening: inconsistence!" );
1113 Sequence< Reference< XControl > > aControls( _rxController->getControls() );
1114 m_aControlObservers.resize( 0 );
1115 m_aControlObservers.reserve( aControls.getLength() );
1117 const Reference< XControl >* pControls = aControls.getConstArray();
1118 const Reference< XControl >* pControlsEnd = pControls + aControls.getLength();
1119 for ( ; pControls != pControlsEnd; ++pControls )
1121 m_aControlObservers.push_back( FocusListenerAdapter( new FmFocusListenerAdapter( *pControls, this ) ) );
1124 catch( const Exception& )
1126 DBG_UNHANDLED_EXCEPTION();
1129 m_xActiveController = _rxController;
1133 void FmTextControlShell::stopControllerListening( )
1135 OSL_PRECOND( isControllerListening(), "FmTextControlShell::stopControllerListening: inconsistence!" );
1137 // dispose all listeners associated with the controls of the active controller
1138 for ( FocusListenerAdapters::iterator aLoop = m_aControlObservers.begin();
1139 aLoop != m_aControlObservers.end();
1140 ++aLoop
1143 (*aLoop)->dispose();
1146 FocusListenerAdapters aEmpty;
1147 m_aControlObservers.swap( aEmpty );
1149 m_xActiveController.clear();
1153 void FmTextControlShell::implClearActiveControlRef()
1155 // no more features for this control
1156 for ( ControlFeatures::iterator aLoop = m_aControlFeatures.begin();
1157 aLoop != m_aControlFeatures.end();
1158 ++aLoop
1161 aLoop->second->dispose();
1164 ControlFeatures aEmpty;
1165 m_aControlFeatures.swap( aEmpty );
1167 if ( m_aContextMenuObserver.get() )
1169 m_aContextMenuObserver->dispose();
1170 m_aContextMenuObserver = MouseListenerAdapter();
1173 if ( m_xActiveTextComponent.is() )
1175 OSL_TRACE( "FmTextControlShell::ClipBoard: stopping timer for clipboard invalidation" );
1176 m_aClipboardInvalidation.Stop();
1178 // no more active control
1179 m_xActiveControl.clear();
1180 m_xActiveTextComponent.clear();
1181 m_bActiveControlIsReadOnly = true;
1182 m_bActiveControlIsRichText = false;
1183 m_bActiveControl = false;
1187 void FmTextControlShell::controlDeactivated( )
1189 DBG_ASSERT( IsActiveControl(), "FmTextControlShell::controlDeactivated: no active control!" );
1191 m_bActiveControl = false;
1193 m_rBindings.Invalidate( pTextControlSlots );
1197 void FmTextControlShell::controlActivated( const Reference< XControl >& _rxControl )
1199 // ensure that all knittings with the previously active control are lost
1200 if ( m_xActiveControl.is() )
1201 implClearActiveControlRef();
1202 DBG_ASSERT( m_aControlFeatures.empty(), "FmTextControlShell::controlActivated: should have no dispatchers when I'm here!" );
1204 #if OSL_DEBUG_LEVEL > 0
1206 Sequence< Reference< XControl > > aActiveControls;
1207 if ( m_xActiveController.is() )
1208 aActiveControls = m_xActiveController->getControls();
1210 bool bFoundThisControl = false;
1212 const Reference< XControl >* pControls = aActiveControls.getConstArray();
1213 const Reference< XControl >* pControlsEnd = pControls + aActiveControls.getLength();
1214 for ( ; ( pControls != pControlsEnd ) && !bFoundThisControl; ++pControls )
1216 if ( *pControls == _rxControl )
1217 bFoundThisControl = true;
1219 DBG_ASSERT( bFoundThisControl, "FmTextControlShell::controlActivated: only controls which belong to the active controller can be activated!" );
1221 #endif
1222 // ask the control for dispatchers for our text-related slots
1223 fillFeatureDispatchers( _rxControl, pTextControlSlots, m_aControlFeatures );
1225 // remember this control
1226 m_xActiveControl = _rxControl;
1227 m_xActiveTextComponent = m_xActiveTextComponent.query( _rxControl );
1228 m_bActiveControlIsReadOnly = lcl_determineReadOnly( m_xActiveControl );
1229 m_bActiveControlIsRichText = lcl_isRichText( m_xActiveControl );
1231 // if we found a rich text control, we need context menu support
1232 if ( m_bActiveControlIsRichText )
1234 DBG_ASSERT( NULL == m_aContextMenuObserver.get(), "FmTextControlShell::controlActivated: already have an observer!" );
1235 m_aContextMenuObserver = MouseListenerAdapter( new FmMouseListenerAdapter( _rxControl, this ) );
1238 if ( m_xActiveTextComponent.is() )
1240 OSL_TRACE( "FmTextControlShell::ClipBoard: starting timer for clipboard invalidation" );
1241 m_aClipboardInvalidation.Start();
1244 m_bActiveControl = true;
1246 m_rBindings.Invalidate( pTextControlSlots );
1248 if ( m_pViewFrame )
1249 m_pViewFrame->UIFeatureChanged();
1251 // don't call the activation handler if we don't have any slots we can serve
1252 // The activation handler is used to put the shell on the top of the dispatcher stack,
1253 // so it's preferred when slots are distributed.
1254 // Note that this is a slight hack, to prevent that we grab slots from the SfxDispatcher
1255 // which should be served by other shells (e.g. Cut/Copy/Paste).
1256 // A real solution would be a forwarding-mechanism for slots: We should be on the top
1257 // if we're active, but if we cannot handle the slot, then we need to tell the dispatcher
1258 // to skip our shell, and pass the slot to the next one. However, this mechanism is not
1259 // not in place in SFX.
1260 // Another possibility would be to have dedicated shells for the slots which we might
1261 // or might not be able to serve. However, this could probably increase the number of
1262 // shells too much (In theory, nearly every slot could have an own shell then).
1264 // #i51621# / 2005-08-19 / frank.schoenheit@sun.com
1265 // bool bHaveAnyServeableSlots = m_xActiveTextComponent.is() || !m_aControlFeatures.empty();
1266 // LEM: not calling m_aControlActivatonHandler causes fdo#63695, so disable this hack for now.
1267 if ( m_aControlActivationHandler.IsSet() /* && bHaveAnyServeableSlots */ )
1268 m_aControlActivationHandler.Call( NULL );
1270 m_bNeedClipboardInvalidation = true;
1274 void FmTextControlShell::fillFeatureDispatchers( const Reference< XControl > _rxControl, SfxSlotId* _pZeroTerminatedSlots,
1275 ControlFeatures& _rDispatchers )
1277 Reference< XDispatchProvider > xProvider( _rxControl, UNO_QUERY );
1278 SfxApplication* pApplication = SFX_APP();
1279 DBG_ASSERT( pApplication, "FmTextControlShell::fillFeatureDispatchers: no SfxApplication!" );
1280 if ( xProvider.is() && pApplication )
1282 SfxSlotId* pSlots = _pZeroTerminatedSlots;
1283 while ( *pSlots )
1285 FmTextControlFeature* pDispatcher = implGetFeatureDispatcher( xProvider, pApplication, *pSlots );
1286 if ( pDispatcher )
1287 _rDispatchers.insert( ControlFeatures::value_type( *pSlots, ControlFeature( pDispatcher ) ) );
1289 ++pSlots;
1295 void FmTextControlShell::impl_parseURL_nothrow( URL& _rURL )
1299 if ( !m_xURLTransformer.is() )
1301 m_xURLTransformer = util::URLTransformer::create( ::comphelper::getProcessComponentContext() );
1303 if ( m_xURLTransformer.is() )
1304 m_xURLTransformer->parseStrict( _rURL );
1306 catch( const Exception& )
1308 DBG_UNHANDLED_EXCEPTION();
1313 FmTextControlFeature* FmTextControlShell::implGetFeatureDispatcher( const Reference< XDispatchProvider >& _rxProvider, SfxApplication* _pApplication, SfxSlotId _nSlot )
1315 OSL_PRECOND( _rxProvider.is() && _pApplication, "FmTextControlShell::implGetFeatureDispatcher: invalid arg(s)!" );
1316 URL aFeatureURL;
1317 aFeatureURL.Complete = lcl_getUnoSlotName( *_pApplication, _nSlot );
1318 impl_parseURL_nothrow( aFeatureURL );
1319 Reference< XDispatch > xDispatcher = _rxProvider->queryDispatch( aFeatureURL, OUString(), 0xFF );
1320 if ( xDispatcher.is() )
1321 return new FmTextControlFeature( xDispatcher, aFeatureURL, _nSlot, this );
1322 return NULL;
1326 void FmTextControlShell::Invalidate( SfxSlotId _nSlot )
1328 m_rBindings.Invalidate( _nSlot );
1329 // despite this method being called "Invalidate", we also update here - this gives more immediate
1330 // feedback in the UI
1331 m_rBindings.Update( _nSlot );
1335 void FmTextControlShell::focusGained( const ::com::sun::star::awt::FocusEvent& _rEvent )
1337 Reference< XControl > xControl( _rEvent.Source, UNO_QUERY );
1339 #if OSL_DEBUG_LEVEL > 0
1340 OString sTrace( "FmTextControlShell::focusGained: 0x" );
1341 sTrace += OString::number( (sal_IntPtr)xControl.get(), 16 );
1342 OSL_TRACE( "%s", sTrace.getStr() );
1343 #endif
1345 DBG_ASSERT( xControl.is(), "FmTextControlShell::focusGained: suspicious focus event!" );
1346 if ( xControl.is() )
1347 controlActivated( xControl );
1351 void FmTextControlShell::focusLost( const ::com::sun::star::awt::FocusEvent& _rEvent )
1353 Reference< XControl > xControl( _rEvent.Source, UNO_QUERY );
1355 #if OSL_DEBUG_LEVEL > 0
1356 OString sTrace( "FmTextControlShell::focusLost: 0x" );
1357 sTrace += OString::number( (sal_IntPtr)xControl.get(), 16 );
1358 OSL_TRACE( "%s", sTrace.getStr() );
1359 #endif
1361 m_bActiveControl = false;
1365 void FmTextControlShell::ForgetActiveControl()
1367 implClearActiveControlRef();
1371 void FmTextControlShell::contextMenuRequested( const awt::MouseEvent& /*_rEvent*/ )
1373 m_rBindings.GetDispatcher()->ExecutePopup( SVX_RES( RID_FM_TEXTATTRIBUTE_MENU ) );
1377 } // namespace svx
1380 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */