/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
// slots which we are not responsible for on the SfxShell level, but // need to handle during the "paragraph attributes" and/or "character // attributes" dialogs static SfxSlotId pDialogSlots[] =
{
SID_ATTR_TABSTOP,
SID_ATTR_PARA_HANGPUNCTUATION,
SID_ATTR_PARA_FORBIDDEN_RULES,
SID_ATTR_PARA_SCRIPTSPACE,
SID_ATTR_CHAR_LATIN_LANGUAGE,
SID_ATTR_CHAR_CJK_LANGUAGE,
SID_ATTR_CHAR_CTL_LANGUAGE,
SID_ATTR_CHAR_LATIN_FONT,
SID_ATTR_CHAR_CJK_FONT,
SID_ATTR_CHAR_CTL_FONT,
SID_ATTR_CHAR_LATIN_FONTHEIGHT,
SID_ATTR_CHAR_CJK_FONTHEIGHT,
SID_ATTR_CHAR_CTL_FONTHEIGHT,
SID_ATTR_CHAR_LATIN_WEIGHT,
SID_ATTR_CHAR_CJK_WEIGHT,
SID_ATTR_CHAR_CTL_WEIGHT,
SID_ATTR_CHAR_LATIN_POSTURE,
SID_ATTR_CHAR_CJK_POSTURE,
SID_ATTR_CHAR_CTL_POSTURE,
SID_ATTR_CHAR_EMPHASISMARK,
0
};
typedef ::cppu::WeakImplHelper < css::awt::XFocusListener
> FmFocusListenerAdapter_Base; class FmFocusListenerAdapter : public FmFocusListenerAdapter_Base
{ private:
IFocusObserver* m_pObserver;
Reference< css::awt::XWindow > m_xWindow;
void FmMouseListenerAdapter::dispose()
{ if ( m_xWindow.is() )
{
m_xWindow->removeMouseListener( this );
m_xWindow.clear();
}
}
void SAL_CALL FmMouseListenerAdapter::mousePressed( const css::awt::MouseEvent& _rEvent )
{
SolarMutexGuard aGuard; // is this a request for a context menu? if ( _rEvent.PopupTrigger )
{ if ( m_pObserver )
m_pObserver->contextMenuRequested();
}
}
void SAL_CALL FmMouseListenerAdapter::mouseReleased( const css::awt::MouseEvent& /*e*/ )
{ // not interested in
}
void SAL_CALL FmMouseListenerAdapter::mouseEntered( const css::awt::MouseEvent& /*e*/ )
{ // not interested in
}
void SAL_CALL FmMouseListenerAdapter::mouseExited( const css::awt::MouseEvent& /*e*/ )
{ // not interested in
}
void SAL_CALL FmMouseListenerAdapter::disposing( const EventObject& Source )
{
DBG_ASSERT( Source.Source == m_xWindow, "FmMouseListenerAdapter::disposing: where did this come from?" );
m_xWindow.clear();
}
OUString sUnoName; if ( pSlot )
{
sUnoName = pSlot->GetCommand();
} else
{ // some hard-coded slots, which do not have a UNO name at SFX level, but which // we nevertheless need to transport via UNO mechanisms, so we need a name switch ( _nSlotId )
{ case SID_ATTR_PARA_HANGPUNCTUATION: sUnoName = ".uno:AllowHangingPunctuation"; break; case SID_ATTR_PARA_FORBIDDEN_RULES: sUnoName = ".uno:ApplyForbiddenCharacterRules"; break; case SID_ATTR_PARA_SCRIPTSPACE: sUnoName = ".uno:UseScriptSpacing"; break;
}
}
if (sUnoName.isEmpty())
{
SAL_WARN( "svx", "lcl_getUnoSlotName: invalid slot id, or invalid slot, or no UNO name! " "(slot id: " << _nSlotId << ")");
} return sUnoName;
}
if ( _bTranslateLatin )
{ // A rich text control offers a dispatcher for the "Font" slot/feature. // Sadly, the semantics of the dispatches is that the feature "Font" depends // on the current cursor position: If it's on latin text, it's the "latin font" // which is set up at the control. If it's on CJK text, it's the "CJK font", and // equivalent for "CTL font". // The same holds for some other font related features/slots. // Thus, we have separate dispatches for "Latin Font", "Latin Font Size", etc, // which are only "virtual", in a sense that there exist no item with this id. // So when we encounter such a dispatcher for, say, "Latin Font", we need to // put an item into the set which has the "Font" id.
switch ( nSlotId )
{ case SID_ATTR_CHAR_LATIN_FONT: nSlotId = SID_ATTR_CHAR_FONT; break; case SID_ATTR_CHAR_LATIN_FONTHEIGHT:nSlotId = SID_ATTR_CHAR_FONTHEIGHT; break; case SID_ATTR_CHAR_LATIN_LANGUAGE: nSlotId = SID_ATTR_CHAR_LANGUAGE; break; case SID_ATTR_CHAR_LATIN_POSTURE: nSlotId = SID_ATTR_CHAR_POSTURE; break; case SID_ATTR_CHAR_LATIN_WEIGHT: nSlotId = SID_ATTR_CHAR_WEIGHT; break;
}
}
WhichId nWhich = rPool.GetWhichIDFromSlotID( nSlotId ); bool bIsInPool = rPool.IsInRange( nWhich ); if ( bIsInPool )
{ #if OSL_DEBUG_LEVEL > 0 bool bFeatureIsEnabled = rFeature.second->isFeatureEnabled();
OString sMessage = "found a feature state for " + sUnoSlotNameAscii; if ( !bFeatureIsEnabled )
sMessage += " (disabled)";
SAL_INFO("svx.form", sMessage ); #endif
lcl_translateUnoStateToItem( nSlotId, rFeature.second->getFeatureState(), _rSet );
} #if OSL_DEBUG_LEVEL > 0 else
{
SAL_WARN("svx.form", "found a feature state for " << sUnoSlotNameAscii << ", but could not translate it into an item!" );
} #endif
}
}
void FmTextControlShell::executeAttributeDialog( AttributeSet _eSet, SfxRequest& rReq )
{ const SvxFontListItem* pFontList = dynamic_cast<const SvxFontListItem*>( m_pViewFrame->GetObjectShell()->GetItem( SID_ATTR_CHAR_FONTLIST ) );
DBG_ASSERT( pFontList, "FmTextControlShell::executeAttributeDialog: no font list item!" ); if ( !pFontList ) return;
// put the current states of the items into the set
std::optional<SfxAllItemSet> xCurrentItems(( SfxAllItemSet( *xPureItems ) ));
transferFeatureStatesToItemSet( m_aControlFeatures, *xCurrentItems, false );
// additional items, which we are not responsible for at the SfxShell level, // but which need to be forwarded to the dialog, anyway
ControlFeatures aAdditionalFestures;
fillFeatureDispatchers( m_xActiveControl, pDialogSlots, aAdditionalFestures );
transferFeatureStatesToItemSet( aAdditionalFestures, *xCurrentItems, true );
SfxSlotId nSlotForDispatcher = nSlotForItemSet; switch ( nSlotForDispatcher )
{ case SID_ATTR_CHAR_FONT: nSlotForDispatcher = SID_ATTR_CHAR_LATIN_FONT; break; case SID_ATTR_CHAR_FONTHEIGHT:nSlotForDispatcher = SID_ATTR_CHAR_LATIN_FONTHEIGHT; break; case SID_ATTR_CHAR_LANGUAGE: nSlotForDispatcher = SID_ATTR_CHAR_LATIN_LANGUAGE; break; case SID_ATTR_CHAR_POSTURE: nSlotForDispatcher = SID_ATTR_CHAR_LATIN_POSTURE; break; case SID_ATTR_CHAR_WEIGHT: nSlotForDispatcher = SID_ATTR_CHAR_LATIN_WEIGHT; break;
}
// do we already have a dispatcher for this slot/feature?
ControlFeatures::const_iterator aFeaturePos = m_aControlFeatures.find( nSlotForDispatcher ); bool bFound = aFeaturePos != m_aControlFeatures.end( );
if ( bFound )
{
Sequence< PropertyValue > aArgs; // temporarily put the modified item into a "clean" set, // and let TransformItems calc the respective UNO parameters
xPureItems->Put( *pModifiedItem );
TransformItems( nSlotForItemSet, *xPureItems, aArgs );
xPureItems->ClearItem( nWhich );
if ( ( nSlotForItemSet == SID_ATTR_PARA_HANGPUNCTUATION )
|| ( nSlotForItemSet == SID_ATTR_PARA_FORBIDDEN_RULES )
|| ( nSlotForItemSet == SID_ATTR_PARA_SCRIPTSPACE )
)
{ // these are no UNO slots, they need special handling since TransformItems cannot // handle them
DBG_ASSERT( !aArgs.hasElements(), "FmTextControlShell::executeAttributeDialog: these are no UNO slots - are they?" );
ControlFeatures::const_iterator aFeaturePos = m_aControlFeatures.find( nSlot ); if ( aFeaturePos == m_aControlFeatures.end() )
{ // special slots switch ( nSlot )
{ case SID_CHAR_DLG:
executeAttributeDialog( eCharAttribs, _rReq ); break;
case SID_PARA_DLG:
executeAttributeDialog( eParaAttribs, _rReq ); break;
case SID_SELECTALL:
executeSelectAll(); break;
case SID_CUT: case SID_COPY: case SID_PASTE:
executeClipboardSlot( nSlot ); break;
default:
DBG_ASSERT( aFeaturePos != m_aControlFeatures.end(), "FmTextControShell::ExecuteTextAttribute: I have no such dispatcher, and cannot handle it at all!" ); return;
}
} else
{ // slots which are dispatched to the control
switch ( nSlot )
{ case SID_ATTR_CHAR_STRIKEOUT: case SID_ATTR_CHAR_UNDERLINE: case SID_ATTR_CHAR_OVERLINE:
{
SfxItemSet aToggled( *_rReq.GetArgs() );
case SID_ATTR_CHAR_FONTHEIGHT: case SID_ATTR_CHAR_FONT: case SID_ATTR_CHAR_POSTURE: case SID_ATTR_CHAR_WEIGHT: case SID_ATTR_CHAR_SHADOWED: case SID_ATTR_CHAR_CONTOUR: case SID_SET_SUPER_SCRIPT: case SID_SET_SUB_SCRIPT:
{ const SfxItemSet* pArgs = _rReq.GetArgs();
Sequence< PropertyValue > aArgs; if ( pArgs )
TransformItems( nSlot, *pArgs, aArgs );
aFeaturePos->second->dispatch( aArgs );
} break;
void FmTextControlShell::implClearActiveControlRef()
{ // no more features for this control for (auto& rFeature : m_aControlFeatures)
{
rFeature.second->dispose();
}
ControlFeatures().swap(m_aControlFeatures);
if ( m_aContextMenuObserver )
{
m_aContextMenuObserver->dispose();
m_aContextMenuObserver = MouseListenerAdapter();
}
if ( m_xActiveTextComponent.is() )
{
SAL_INFO("svx.form", "stopping timer for clipboard invalidation" );
m_aClipboardInvalidation.Stop();
} // no more active control
m_xActiveControl.clear();
m_xActiveTextComponent.clear();
m_bActiveControlIsReadOnly = true;
m_bActiveControlIsRichText = false;
m_bActiveControl = false;
}
void FmTextControlShell::controlDeactivated( )
{
DBG_ASSERT( IsActiveControl(), "FmTextControlShell::controlDeactivated: no active control!" );
m_bActiveControl = false;
m_rBindings.Invalidate( pTextControlSlots );
}
void FmTextControlShell::controlActivated( const Reference< css::awt::XControl >& _rxControl )
{ // ensure that all knittings with the previously active control are lost if ( m_xActiveControl.is() )
implClearActiveControlRef();
DBG_ASSERT( m_aControlFeatures.empty(), "FmTextControlShell::controlActivated: should have no dispatchers when I'm here!" );
const Reference< css::awt::XControl >* pControls = aActiveControls.getConstArray(); const Reference< css::awt::XControl >* pControlsEnd = pControls + aActiveControls.getLength(); for ( ; ( pControls != pControlsEnd ) && !bFoundThisControl; ++pControls )
{ if ( *pControls == _rxControl )
bFoundThisControl = true;
}
DBG_ASSERT( bFoundThisControl, "FmTextControlShell::controlActivated: only controls which belong to the active controller can be activated!" );
} #endif // ask the control for dispatchers for our text-related slots
fillFeatureDispatchers( _rxControl, pTextControlSlots, m_aControlFeatures );
// remember this control
m_xActiveControl = _rxControl;
m_xActiveTextComponent.set(_rxControl, css::uno::UNO_QUERY);
m_bActiveControlIsReadOnly = lcl_determineReadOnly( m_xActiveControl );
m_bActiveControlIsRichText = lcl_isRichText( m_xActiveControl );
// if we found a rich text control, we need context menu support if ( m_bActiveControlIsRichText )
{
DBG_ASSERT( !m_aContextMenuObserver, "FmTextControlShell::controlActivated: already have an observer!" );
m_aContextMenuObserver = MouseListenerAdapter( new FmMouseListenerAdapter( _rxControl, this ) );
}
if ( m_xActiveTextComponent.is() )
{
SAL_INFO("svx.form", "starting timer for clipboard invalidation" );
m_aClipboardInvalidation.Start();
}
m_bActiveControl = true;
m_rBindings.Invalidate( pTextControlSlots );
if ( m_pViewFrame )
m_pViewFrame->UIFeatureChanged();
// don't call the activation handler if we don't have any slots we can serve // The activation handler is used to put the shell on the top of the dispatcher stack, // so it's preferred when slots are distributed. // Note that this is a slight hack, to prevent that we grab slots from the SfxDispatcher // which should be served by other shells (e.g. Cut/Copy/Paste). // A real solution would be a forwarding-mechanism for slots: We should be on the top // if we're active, but if we cannot handle the slot, then we need to tell the dispatcher // to skip our shell, and pass the slot to the next one. However, this mechanism is not // not in place in SFX. // Another possibility would be to have dedicated shells for the slots which we might // or might not be able to serve. However, this could probably increase the number of // shells too much (In theory, nearly every slot could have an own shell then).
// #i51621# / 2005-08-19 / frank.schoenheit@sun.com // bool bHaveAnyServeableSlots = m_xActiveTextComponent.is() || !m_aControlFeatures.empty(); // LEM: not calling m_aControlActivatonHandler causes fdo#63695, so disable this hack for now.
m_aControlActivationHandler.Call( nullptr );
void FmTextControlShell::Invalidate( SfxSlotId _nSlot )
{
m_rBindings.Invalidate( _nSlot ); // despite this method being called "Invalidate", we also update here - this gives more immediate // feedback in the UI
m_rBindings.Update( _nSlot );
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.