/* -*- 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 . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define MAX_MRU_FONTNAME_ENTRIES 5 // don't make more than 15 entries visible at once #define MAX_STYLES_ENTRIES 15 // namespaces using namespace ::editeng; using namespace ::com::sun::star; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::frame; using namespace ::com::sun::star::beans; using namespace ::com::sun::star::lang; SFX_IMPL_TOOLBOX_CONTROL( SvxStyleToolBoxControl, SfxTemplateItem ); SFX_IMPL_TOOLBOX_CONTROL( SvxSimpleUndoRedoController, SfxStringItem ); class SvxStyleBox_Impl : public ComboBox { using Window::IsVisible; public: SvxStyleBox_Impl( vcl::Window* pParent, const OUString& rCommand, SfxStyleFamily eFamily, const Reference< XDispatchProvider >& rDispatchProvider, const Reference< XFrame >& _xFrame,const OUString& rClearFormatKey, const OUString& rMoreKey, bool bInSpecialMode ); virtual ~SvxStyleBox_Impl() override; virtual void dispose() override; void SetFamily( SfxStyleFamily eNewFamily ); bool IsVisible() const { return bVisible; } virtual bool PreNotify( NotifyEvent& rNEvt ) override; virtual bool EventNotify( NotifyEvent& rNEvt ) override; virtual void DataChanged( const DataChangedEvent& rDCEvt ) override; virtual void StateChanged( StateChangedType nStateChange ) override; virtual void UserDraw( const UserDrawEvent& rUDEvt ) override; void SetVisibilityListener( const Link& aVisListener ) { aVisibilityListener = aVisListener; } void SetDefaultStyle( const OUString& rDefault ) { sDefaultStyle = rDefault; } virtual boost::property_tree::ptree DumpAsPropertyTree() override; protected: /// Calculate the optimal width of the dropdown. Very expensive operation, triggers lots of font measurement. DECL_LINK(CalcOptimalExtraUserWidth, VclWindowEvent&, void); virtual void Select() override; private: SfxStyleFamily eStyleFamily; sal_Int32 nCurSel; bool bRelease; Size const aLogicalSize; Link aVisibilityListener; bool bVisible; Reference< XDispatchProvider > m_xDispatchProvider; Reference< XFrame > m_xFrame; OUString const m_aCommand; OUString const aClearFormatKey; OUString const aMoreKey; OUString sDefaultStyle; bool const bInSpecialMode; VclPtr m_pButtons[MAX_STYLES_ENTRIES]; VclBuilder m_aBuilder; VclPtr m_pMenu; void ReleaseFocus(); static Color TestColorsVisible(const Color &FontCol, const Color &BackCol); static void UserDrawEntry(const UserDrawEvent& rUDEvt, const OUString &rStyleName); void SetupEntry(vcl::RenderContext& rRenderContext, vcl::Window* pParent, sal_Int32 nItem, const tools::Rectangle& rRect, const OUString& rStyleName, bool bIsNotSelected); static bool AdjustFontForItemHeight(OutputDevice* pDevice, tools::Rectangle const & rTextRect, long nHeight); void SetOptimalSize(); DECL_LINK( MenuSelectHdl, Menu *, bool ); DECL_STATIC_LINK(SvxStyleBox_Impl, ShowMoreHdl, void*, void); }; class SvxFontNameBox_Impl : public FontNameBox { using Window::Update; private: const FontList* pFontList; ::std::unique_ptr m_aOwnFontList; vcl::Font aCurFont; Size const aLogicalSize; OUString aCurText; sal_uInt16 nFtCount; bool bRelease; Reference< XDispatchProvider > m_xDispatchProvider; Reference< XFrame > m_xFrame; bool mbEndPreview; bool mbCheckingUnknownFont; void ReleaseFocus_Impl(); void EnableControls_Impl(); void EndPreview() { Sequence< PropertyValue > aArgs; SfxToolBoxControl::Dispatch( m_xDispatchProvider, ".uno:CharEndPreviewFontName", aArgs ); } DECL_LINK( CheckAndMarkUnknownFont, VclWindowEvent&, void ); void SetOptimalSize(); protected: virtual void Select() override; virtual void DataChanged( const DataChangedEvent& rDCEvt ) override; public: SvxFontNameBox_Impl( vcl::Window* pParent, const Reference< XDispatchProvider >& rDispatchProvider,const Reference< XFrame >& _xFrame , WinBits nStyle ); virtual ~SvxFontNameBox_Impl() override; virtual void dispose() override; void FillList(); void Update( const css::awt::FontDescriptor* pFontDesc ); sal_uInt16 GetListCount() const { return nFtCount; } void Clear() { FontNameBox::Clear(); nFtCount = 0; } void Fill( const FontList* pList ) { FontNameBox::Fill( pList ); nFtCount = pList->GetFontNameCount(); } virtual void UserDraw( const UserDrawEvent& rUDEvt ) override; virtual bool PreNotify( NotifyEvent& rNEvt ) override; virtual bool EventNotify( NotifyEvent& rNEvt ) override; virtual Reference< css::accessibility::XAccessible > CreateAccessible() override; void SetOwnFontList(::std::unique_ptr && _aOwnFontList) { m_aOwnFontList = std::move(_aOwnFontList); } virtual boost::property_tree::ptree DumpAsPropertyTree() override; }; // SelectHdl needs the Modifiers, get them in MouseButtonUp class SvxFrmValueSet_Impl : public ValueSet { sal_uInt16 nModifier; virtual void MouseButtonUp( const MouseEvent& rMEvt ) override; public: SvxFrmValueSet_Impl(vcl::Window* pParent, WinBits nWinStyle) : ValueSet(pParent, nWinStyle), nModifier(0) {} sal_uInt16 GetModifier() const {return nModifier;} }; void SvxFrmValueSet_Impl::MouseButtonUp( const MouseEvent& rMEvt ) { nModifier = rMEvt.GetModifier(); ValueSet::MouseButtonUp(rMEvt); } class SvxFrameWindow_Impl : public svtools::ToolbarPopup { private: VclPtr aFrameSet; svt::ToolboxController& mrController; std::vector aImgVec; bool bParagraphMode; void InitImageList(); void CalcSizeValueSet(); DECL_LINK( SelectHdl, ValueSet*, void ); protected: virtual void GetFocus() override; virtual void KeyInput( const KeyEvent& rKEvt ) override; public: SvxFrameWindow_Impl( svt::ToolboxController& rController, vcl::Window* pParentWindow ); virtual ~SvxFrameWindow_Impl() override; virtual void dispose() override; virtual void statusChanged( const css::frame::FeatureStateEvent& rEvent ) override; virtual void DataChanged( const DataChangedEvent& rDCEvt ) override; }; namespace { class LineListBox final : public ListBox { public: typedef Color (*ColorFunc)(Color); typedef Color (*ColorDistFunc)(Color, Color); LineListBox( vcl::Window* pParent ); virtual ~LineListBox() override; virtual void dispose() override; /** Set the width in Twips */ void SetWidth( long nWidth ) { long nOldWidth = m_nWidth; m_nWidth = nWidth; UpdateEntries( nOldWidth ); } void SetNone( const OUString& sNone ) { m_sNone = sNone; } using ListBox::InsertEntry; /** Insert a listbox entry with all widths in Twips. */ void InsertEntry(const BorderWidthImpl& rWidthImpl, SvxBorderLineStyle nStyle, long nMinWidth = 0, ColorFunc pColor1Fn = &sameColor, ColorFunc pColor2Fn = &sameColor, ColorDistFunc pColorDistFn = &sameDistColor); SvxBorderLineStyle GetEntryStyle( sal_Int32 nPos ) const; SvxBorderLineStyle GetSelectEntryStyle() const; void SetSourceUnit( FieldUnit eNewUnit ) { eSourceUnit = eNewUnit; } const Color& GetColor() const { return aColor; } private: void ImpGetLine(long nLine1, long nLine2, long nDistance, Color nColor1, Color nColor2, Color nColorDist, SvxBorderLineStyle nStyle, BitmapEx& rBmp); using Window::ImplInit; void UpdatePaintLineColor(); // returns sal_True if maPaintCol has changed virtual void DataChanged( const DataChangedEvent& rDCEvt ) override; void UpdateEntries( long nOldWidth ); sal_Int32 GetStylePos( sal_Int32 nListPos, long nWidth ); const Color& GetPaintColor() const { return maPaintCol; } Color GetColorLine1( sal_Int32 nPos ); Color GetColorLine2( sal_Int32 nPos ); Color GetColorDist( sal_Int32 nPos ); LineListBox( const LineListBox& ) = delete; LineListBox& operator =( const LineListBox& ) = delete; std::vector> m_vLineList; long m_nWidth; OUString m_sNone; ScopedVclPtr aVirDev; Size aTxtSize; Color const aColor; Color maPaintCol; FieldUnit eSourceUnit; }; SvxBorderLineStyle LineListBox::GetSelectEntryStyle() const { SvxBorderLineStyle nStyle = SvxBorderLineStyle::SOLID; sal_Int32 nPos = GetSelectedEntryPos(); if ( nPos != LISTBOX_ENTRY_NOTFOUND ) { if (!m_sNone.isEmpty()) nPos--; nStyle = GetEntryStyle( nPos ); } return nStyle; } void LineListBox::ImpGetLine( long nLine1, long nLine2, long nDistance, Color aColor1, Color aColor2, Color aColorDist, SvxBorderLineStyle nStyle, BitmapEx& rBmp ) { //TODO, rather than including the " " text to force //the line height, better would be do drop //this calculation and draw a bitmap of height //equal to normal text line and center the //line within that long nMinWidth = GetTextWidth("----------"); Size aSize = CalcSubEditSize(); aSize.setWidth( std::max(nMinWidth, aSize.Width()) ); aSize.AdjustWidth( -(aTxtSize.Width()) ); aSize.AdjustWidth( -6 ); aSize.setHeight( aTxtSize.Height() ); // SourceUnit to Twips if ( eSourceUnit == FieldUnit::POINT ) { nLine1 /= 5; nLine2 /= 5; nDistance /= 5; } // Paint the lines aSize = aVirDev->PixelToLogic( aSize ); long nPix = aVirDev->PixelToLogic( Size( 0, 1 ) ).Height(); sal_uInt32 n1 = nLine1; sal_uInt32 n2 = nLine2; long nDist = nDistance; n1 += nPix-1; n1 -= n1%nPix; if ( n2 ) { nDist += nPix-1; nDist -= nDist%nPix; n2 += nPix-1; n2 -= n2%nPix; } long nVirHeight = n1+nDist+n2; if ( nVirHeight > aSize.Height() ) aSize.setHeight( nVirHeight ); // negative width should not be drawn if ( aSize.Width() <= 0 ) return; Size aVirSize = aVirDev->LogicToPixel( aSize ); if ( aVirDev->GetOutputSizePixel() != aVirSize ) aVirDev->SetOutputSizePixel( aVirSize ); aVirDev->SetFillColor( aColorDist ); aVirDev->DrawRect( tools::Rectangle( Point(), aSize ) ); aVirDev->SetFillColor( aColor1 ); double y1 = double( n1 ) / 2; svtools::DrawLine( *aVirDev, basegfx::B2DPoint( 0, y1 ), basegfx::B2DPoint( aSize.Width( ), y1 ), n1, nStyle ); if ( n2 ) { double y2 = n1 + nDist + double( n2 ) / 2; aVirDev->SetFillColor( aColor2 ); svtools::DrawLine( *aVirDev, basegfx::B2DPoint( 0, y2 ), basegfx::B2DPoint( aSize.Width(), y2 ), n2, SvxBorderLineStyle::SOLID ); } rBmp = aVirDev->GetBitmapEx( Point(), Size( aSize.Width(), n1+nDist+n2 ) ); } LineListBox::LineListBox( vcl::Window* pParent ) : ListBox( pParent, WB_BORDER ), m_nWidth( 5 ), m_sNone( ), aVirDev( VclPtr::Create() ), aColor( COL_BLACK ), maPaintCol( COL_BLACK ) { aTxtSize.setWidth( GetTextWidth( " " ) ); aTxtSize.setHeight( GetTextHeight() ); eSourceUnit = FieldUnit::POINT; aVirDev->SetLineColor(); aVirDev->SetMapMode( MapMode( MapUnit::MapTwip ) ); UpdatePaintLineColor(); } LineListBox::~LineListBox() { disposeOnce(); } void LineListBox::dispose() { m_vLineList.clear(); ListBox::dispose(); } sal_Int32 LineListBox::GetStylePos( sal_Int32 nListPos, long nWidth ) { sal_Int32 nPos = LISTBOX_ENTRY_NOTFOUND; if (!m_sNone.isEmpty()) nListPos--; sal_Int32 n = 0; size_t i = 0; size_t nCount = m_vLineList.size(); while ( nPos == LISTBOX_ENTRY_NOTFOUND && i < nCount ) { auto& pData = m_vLineList[ i ]; if ( pData->GetMinWidth() <= nWidth ) { if ( nListPos == n ) nPos = static_cast(i); n++; } i++; } return nPos; } void LineListBox::InsertEntry( const BorderWidthImpl& rWidthImpl, SvxBorderLineStyle nStyle, long nMinWidth, ColorFunc pColor1Fn, ColorFunc pColor2Fn, ColorDistFunc pColorDistFn ) { m_vLineList.emplace_back(new ImpLineListData( rWidthImpl, nStyle, nMinWidth, pColor1Fn, pColor2Fn, pColorDistFn)); } SvxBorderLineStyle LineListBox::GetEntryStyle( sal_Int32 nPos ) const { ImpLineListData* pData = (0 <= nPos && static_cast(nPos) < m_vLineList.size()) ? m_vLineList[ nPos ].get() : nullptr; return pData ? pData->GetStyle() : SvxBorderLineStyle::NONE; } void LineListBox::UpdatePaintLineColor() { const StyleSettings& rSettings = GetSettings().GetStyleSettings(); Color aNewCol( rSettings.GetWindowColor().IsDark()? rSettings.GetLabelTextColor() : aColor ); bool bRet = aNewCol != maPaintCol; if( bRet ) maPaintCol = aNewCol; } void LineListBox::UpdateEntries( long nOldWidth ) { SetUpdateMode( false ); UpdatePaintLineColor( ); sal_Int32 nSelEntry = GetSelectedEntryPos(); sal_Int32 nTypePos = GetStylePos( nSelEntry, nOldWidth ); // Remove the old entries while ( GetEntryCount( ) > 0 ) ListBox::RemoveEntry( 0 ); // Add the new entries based on the defined width if (!m_sNone.isEmpty()) ListBox::InsertEntry( m_sNone ); sal_uInt16 n = 0; sal_uInt16 nCount = m_vLineList.size( ); while ( n < nCount ) { auto& pData = m_vLineList[ n ]; if ( pData->GetMinWidth() <= m_nWidth ) { BitmapEx aBmp; ImpGetLine( pData->GetLine1ForWidth( m_nWidth ), pData->GetLine2ForWidth( m_nWidth ), pData->GetDistForWidth( m_nWidth ), GetColorLine1( GetEntryCount( ) ), GetColorLine2( GetEntryCount( ) ), GetColorDist( GetEntryCount( ) ), pData->GetStyle(), aBmp ); ListBox::InsertEntry(" ", Image(aBmp)); if ( n == nTypePos ) SelectEntryPos( GetEntryCount() - 1 ); } else if ( n == nTypePos ) SetNoSelection(); n++; } SetUpdateMode( true ); Invalidate(); } Color LineListBox::GetColorLine1( sal_Int32 nPos ) { sal_Int32 nStyle = GetStylePos( nPos, m_nWidth ); if (nStyle == LISTBOX_ENTRY_NOTFOUND) return GetPaintColor( ); auto& pData = m_vLineList[ nStyle ]; return pData->GetColorLine1( GetColor( ) ); } Color LineListBox::GetColorLine2( sal_Int32 nPos ) { sal_Int32 nStyle = GetStylePos( nPos, m_nWidth ); if (nStyle == LISTBOX_ENTRY_NOTFOUND) return GetPaintColor( ); auto& pData = m_vLineList[ nStyle ]; return pData->GetColorLine2( GetColor( ) ); } Color LineListBox::GetColorDist( sal_Int32 nPos ) { Color rResult = GetSettings().GetStyleSettings().GetFieldColor(); sal_Int32 nStyle = GetStylePos( nPos, m_nWidth ); if (nStyle == LISTBOX_ENTRY_NOTFOUND) return rResult; auto& pData = m_vLineList[ nStyle ]; return pData->GetColorDist( GetColor( ), rResult ); } void LineListBox::DataChanged( const DataChangedEvent& rDCEvt ) { ListBox::DataChanged( rDCEvt ); if( ( rDCEvt.GetType() == DataChangedEventType::SETTINGS ) && ( rDCEvt.GetFlags() & AllSettingsFlags::STYLE ) ) UpdateEntries( m_nWidth ); } } class SvxLineWindow_Impl : public svtools::ToolbarPopup { private: VclPtr m_aLineStyleLb; svt::ToolboxController& m_rController; bool m_bIsWriter; DECL_LINK( SelectHdl, ListBox&, void ); protected: virtual void Resize() override; virtual void GetFocus() override; public: SvxLineWindow_Impl( svt::ToolboxController& rController, vcl::Window* pParentWindow ); virtual ~SvxLineWindow_Impl() override { disposeOnce(); } virtual void dispose() override { m_aLineStyleLb.disposeAndClear(); ToolbarPopup::dispose(); } }; class SvxCurrencyList_Impl : public svtools::ToolbarPopup { private: VclPtr m_pCurrencyLb; rtl::Reference m_xControl; OUString& m_rSelectedFormat; LanguageType& m_eSelectedLanguage; std::vector m_aFormatEntries; LanguageType m_eFormatLanguage; DECL_LINK( SelectHdl, ListBox&, void ); public: SvxCurrencyList_Impl( SvxCurrencyToolBoxControl* pControl, vcl::Window* pParentWindow, OUString& rSelectFormat, LanguageType& eSelectLanguage ); virtual ~SvxCurrencyList_Impl() override { disposeOnce(); } virtual void dispose() override; }; class SvxStyleToolBoxControl; class SfxStyleControllerItem_Impl : public SfxStatusListener { public: SfxStyleControllerItem_Impl( const Reference< XDispatchProvider >& rDispatchProvider, sal_uInt16 nSlotId, const OUString& rCommand, SvxStyleToolBoxControl& rTbxCtl ); protected: virtual void StateChanged( SfxItemState eState, const SfxPoolItem* pState ) override; private: SvxStyleToolBoxControl& rControl; }; #define BUTTON_WIDTH 20 #define BUTTON_PADDING 10 #define ITEM_HEIGHT 30 SvxStyleBox_Impl::SvxStyleBox_Impl(vcl::Window* pParent, const OUString& rCommand, SfxStyleFamily eFamily, const Reference< XDispatchProvider >& rDispatchProvider, const Reference< XFrame >& _xFrame, const OUString& rClearFormatKey, const OUString& rMoreKey, bool bInSpec) : ComboBox(pParent, WB_SORT | WB_BORDER | WB_HIDE | WB_DROPDOWN | WB_AUTOHSCROLL) , eStyleFamily( eFamily ) , nCurSel(0) , bRelease( true ) , aLogicalSize(60, 86) , bVisible(false) , m_xDispatchProvider( rDispatchProvider ) , m_xFrame(_xFrame) , m_aCommand( rCommand ) , aClearFormatKey( rClearFormatKey ) , aMoreKey( rMoreKey ) , bInSpecialMode( bInSpec ) , m_aBuilder(nullptr, VclBuilderContainer::getUIRootDir(), "svx/ui/stylemenu.ui", "") , m_pMenu(m_aBuilder.get_menu("menu")) { SetHelpId(HID_STYLE_LISTBOX); m_pMenu->SetSelectHdl( LINK( this, SvxStyleBox_Impl, MenuSelectHdl ) ); for(VclPtr & rpButton : m_pButtons) rpButton = nullptr; SetOptimalSize(); EnableAutocomplete( true ); EnableUserDraw( true ); AddEventListener(LINK(this, SvxStyleBox_Impl, CalcOptimalExtraUserWidth)); SetUserItemSize( Size( 0, ITEM_HEIGHT ) ); set_id("applystyle"); } SvxStyleBox_Impl::~SvxStyleBox_Impl() { disposeOnce(); } void SvxStyleBox_Impl::dispose() { RemoveEventListener(LINK(this, SvxStyleBox_Impl, CalcOptimalExtraUserWidth)); for (VclPtr& rButton : m_pButtons) { rButton.disposeAndClear(); } m_pMenu.clear(); m_aBuilder.disposeBuilder(); ComboBox::dispose(); } void SvxStyleBox_Impl::ReleaseFocus() { if ( !bRelease ) { bRelease = true; return; } if ( m_xFrame.is() && m_xFrame->getContainerWindow().is() ) m_xFrame->getContainerWindow()->setFocus(); } IMPL_LINK( SvxStyleBox_Impl, MenuSelectHdl, Menu*, pMenu, bool) { OUString sEntry = GetSelectedEntry(); OString sMenuIdent = pMenu->GetCurItemIdent(); ReleaseFocus(); // It must be after getting entry pos! if (IsInDropDown()) ToggleDropDown(); Sequence< PropertyValue > aArgs( 2 ); aArgs[0].Name = "Param"; aArgs[0].Value <<= sEntry; aArgs[1].Name = "Family"; aArgs[1].Value <<= sal_Int16( eStyleFamily ); if (sMenuIdent == "update") { SfxToolBoxControl::Dispatch( m_xDispatchProvider, ".uno:StyleUpdateByExample", aArgs ); } else if (sMenuIdent == "edit") { SfxToolBoxControl::Dispatch( m_xDispatchProvider, ".uno:EditStyle", aArgs ); } return false; } IMPL_STATIC_LINK_NOARG(SvxStyleBox_Impl, ShowMoreHdl, void*, void) { SfxViewFrame* pViewFrm = SfxViewFrame::Current(); DBG_ASSERT( pViewFrm, "SvxStyleBox_Impl::Select(): no viewframe" ); if (!pViewFrm) return; pViewFrm->ShowChildWindow(SID_SIDEBAR); ::sfx2::sidebar::Sidebar::ShowPanel("StyleListPanel", pViewFrm->GetFrame().GetFrameInterface(), true); } void SvxStyleBox_Impl::Select() { // Tell base class about selection so that AT get informed about it. ComboBox::Select(); if ( IsTravelSelect() ) return; OUString aSearchEntry( GetText() ); bool bDoIt = true, bClear = false; if( bInSpecialMode ) { if( aSearchEntry == aClearFormatKey && GetSelectedEntryPos() == 0 ) { aSearchEntry = sDefaultStyle; bClear = true; //not only apply default style but also call 'ClearFormatting' Sequence< PropertyValue > aEmptyVals; SfxToolBoxControl::Dispatch( m_xDispatchProvider, ".uno:ResetAttributes", aEmptyVals); } else if( aSearchEntry == aMoreKey && GetSelectedEntryPos() == ( GetEntryCount() - 1 ) ) { Application::PostUserEvent(LINK(nullptr, SvxStyleBox_Impl, ShowMoreHdl)); //tdf#113214 change text back to previous entry SetText(GetSavedValue()); bDoIt = false; } } //Do we need to create a new style? SfxObjectShell *pShell = SfxObjectShell::Current(); SfxStyleSheetBasePool* pPool = pShell->GetStyleSheetPool(); SfxStyleSheetBase* pStyle = nullptr; bool bCreateNew = false; if ( pPool ) { pPool->SetSearchMask( eStyleFamily ); pStyle = pPool->First(); while ( pStyle && pStyle->GetName() != aSearchEntry ) pStyle = pPool->Next(); } if ( !pStyle ) { // cannot find the style for whatever reason // therefore create a new style bCreateNew = true; } /* #i33380# DR 2004-09-03 Moved the following line above the Dispatch() call. This instance may be deleted in the meantime (i.e. when a dialog is opened while in Dispatch()), accessing members will crash in this case. */ ReleaseFocus(); if( bDoIt ) { if ( bClear ) SetText( aSearchEntry ); SaveValue(); Sequence< PropertyValue > aArgs( 2 ); aArgs[0].Value <<= aSearchEntry; aArgs[1].Name = "Family"; aArgs[1].Value <<= sal_Int16( eStyleFamily ); if( bCreateNew ) { aArgs[0].Name = "Param"; SfxToolBoxControl::Dispatch( m_xDispatchProvider, ".uno:StyleNewByExample", aArgs); } else { aArgs[0].Name = "Template"; SfxToolBoxControl::Dispatch( m_xDispatchProvider, m_aCommand, aArgs ); } } } void SvxStyleBox_Impl::SetFamily( SfxStyleFamily eNewFamily ) { eStyleFamily = eNewFamily; } bool SvxStyleBox_Impl::PreNotify( NotifyEvent& rNEvt ) { MouseNotifyEvent nType = rNEvt.GetType(); if ( MouseNotifyEvent::MOUSEBUTTONDOWN == nType || MouseNotifyEvent::GETFOCUS == nType ) nCurSel = GetSelectedEntryPos(); else if ( MouseNotifyEvent::LOSEFOCUS == nType ) { // don't handle before our Select() is called if (!HasFocus() && !HasChildPathFocus() && !IsChild(rNEvt.GetWindow())) SetText( GetSavedValue() ); } return ComboBox::PreNotify( rNEvt ); } bool SvxStyleBox_Impl::EventNotify( NotifyEvent& rNEvt ) { bool bHandled = false; if ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT ) { sal_uInt16 nCode = rNEvt.GetKeyEvent()->GetKeyCode().GetCode(); switch ( nCode ) { case KEY_CONTEXTMENU: { if(IsInDropDown()) { const sal_Int32 nItem = GetSelectedEntryPos() - 1; if(nItem < MAX_STYLES_ENTRIES) m_pButtons[nItem]->ExecuteMenu(); bHandled = true; } break; } case KEY_RETURN: case KEY_TAB: { if ( KEY_TAB == nCode ) bRelease = false; else bHandled = true; Select(); break; } case KEY_ESCAPE: SelectEntryPos( nCurSel ); if ( typeid( *GetParent() ) != typeid( sfx2::sidebar::SidebarToolBox ) ) ReleaseFocus(); bHandled = true; break; } } return bHandled || ComboBox::EventNotify( rNEvt ); } void SvxStyleBox_Impl::DataChanged( const DataChangedEvent& rDCEvt ) { if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) ) { SetOptimalSize(); } ComboBox::DataChanged( rDCEvt ); } void SvxStyleBox_Impl::StateChanged( StateChangedType nStateChange ) { ComboBox::StateChanged( nStateChange ); if ( nStateChange == StateChangedType::Visible ) { bVisible = IsReallyVisible(); aVisibilityListener.Call( *this ); } else if ( nStateChange == StateChangedType::InitShow ) { bVisible = true; aVisibilityListener.Call( *this ); } } bool SvxStyleBox_Impl::AdjustFontForItemHeight(OutputDevice* pDevice, tools::Rectangle const & rTextRect, long nHeight) { if (rTextRect.Bottom() > nHeight) { // the text does not fit, adjust the font size double ratio = static_cast< double >( nHeight ) / rTextRect.Bottom(); vcl::Font aFont(pDevice->GetFont()); Size aPixelSize(aFont.GetFontSize()); aPixelSize.setWidth( aPixelSize.Width() * ratio ); aPixelSize.setHeight( aPixelSize.Height() * ratio ); aFont.SetFontSize(aPixelSize); pDevice->SetFont(aFont); return true; } return false; } void SvxStyleBox_Impl::SetOptimalSize() { Size aSize(LogicToPixel(aLogicalSize, MapMode(MapUnit::MapAppFont))); set_width_request(aSize.Width()); set_height_request(aSize.Height()); SetSizePixel(aSize); } void SvxStyleBox_Impl::UserDrawEntry(const UserDrawEvent& rUDEvt, const OUString &rStyleName) { vcl::RenderContext *pDevice = rUDEvt.GetRenderContext(); // IMG_TXT_DISTANCE in ilstbox.hxx is 6, then 1 is added as // nBorder, and we are adding 1 in order to look better when // italics is present const int nLeftDistance = 8; tools::Rectangle aTextRect; pDevice->GetTextBoundRect(aTextRect, rStyleName); Point aPos( rUDEvt.GetRect().TopLeft() ); aPos.AdjustX(nLeftDistance ); if (!AdjustFontForItemHeight(pDevice, aTextRect, rUDEvt.GetRect().GetHeight())) aPos.AdjustY(( rUDEvt.GetRect().GetHeight() - aTextRect.Bottom() ) / 2 ); pDevice->DrawText(aPos, rStyleName); } void SvxStyleBox_Impl::SetupEntry(vcl::RenderContext& rRenderContext, vcl::Window* pParent, sal_Int32 nItem, const tools::Rectangle& rRect, const OUString& rStyleName, bool bIsNotSelected) { unsigned int nId = rRect.GetHeight() != 0 ? (rRect.getY() / rRect.GetHeight()) : MAX_STYLES_ENTRIES; if (nItem == 0 || nItem == GetEntryCount() - 1) { if(nId < MAX_STYLES_ENTRIES && m_pButtons[nId]) m_pButtons[nId]->Hide(); } else { SfxObjectShell *pShell = SfxObjectShell::Current(); SfxStyleSheetBasePool* pPool = pShell->GetStyleSheetPool(); SfxStyleSheetBase* pStyle = nullptr; if ( pPool ) { pPool->SetSearchMask( eStyleFamily ); pStyle = pPool->First(); while (pStyle && pStyle->GetName() != rStyleName) pStyle = pPool->Next(); } if (pStyle ) { std::unique_ptr const pItemSet(pStyle->GetItemSetForPreview()); if (!pItemSet) return; const SvxFontItem * const pFontItem = pItemSet->GetItem(SID_ATTR_CHAR_FONT); const SvxFontHeightItem * const pFontHeightItem = pItemSet->GetItem(SID_ATTR_CHAR_FONTHEIGHT); if ( pFontItem && pFontHeightItem ) { Size aFontSize( 0, pFontHeightItem->GetHeight() ); Size aPixelSize(rRenderContext.LogicToPixel(aFontSize, MapMode(pShell->GetMapUnit()))); // setup the font properties SvxFont aFont; aFont.SetFamilyName(pFontItem->GetFamilyName()); aFont.SetStyleName(pFontItem->GetStyleName()); aFont.SetFontSize(aPixelSize); const SfxPoolItem *pItem = pItemSet->GetItem( SID_ATTR_CHAR_WEIGHT ); if ( pItem ) aFont.SetWeight( static_cast< const SvxWeightItem* >( pItem )->GetWeight() ); pItem = pItemSet->GetItem( SID_ATTR_CHAR_POSTURE ); if ( pItem ) aFont.SetItalic( static_cast< const SvxPostureItem* >( pItem )->GetPosture() ); pItem = pItemSet->GetItem( SID_ATTR_CHAR_CONTOUR ); if ( pItem ) aFont.SetOutline( static_cast< const SvxContourItem* >( pItem )->GetValue() ); pItem = pItemSet->GetItem( SID_ATTR_CHAR_SHADOWED ); if ( pItem ) aFont.SetShadow( static_cast< const SvxShadowedItem* >( pItem )->GetValue() ); pItem = pItemSet->GetItem( SID_ATTR_CHAR_RELIEF ); if ( pItem ) aFont.SetRelief( static_cast< const SvxCharReliefItem* >( pItem )->GetValue() ); pItem = pItemSet->GetItem( SID_ATTR_CHAR_UNDERLINE ); if ( pItem ) aFont.SetUnderline( static_cast< const SvxUnderlineItem* >( pItem )->GetLineStyle() ); pItem = pItemSet->GetItem( SID_ATTR_CHAR_OVERLINE ); if ( pItem ) aFont.SetOverline( static_cast< const SvxOverlineItem* >( pItem )->GetValue() ); pItem = pItemSet->GetItem( SID_ATTR_CHAR_STRIKEOUT ); if ( pItem ) aFont.SetStrikeout( static_cast< const SvxCrossedOutItem* >( pItem )->GetStrikeout() ); pItem = pItemSet->GetItem( SID_ATTR_CHAR_CASEMAP ); if ( pItem ) aFont.SetCaseMap(static_cast(pItem)->GetCaseMap()); pItem = pItemSet->GetItem( SID_ATTR_CHAR_EMPHASISMARK ); if ( pItem ) aFont.SetEmphasisMark( static_cast< const SvxEmphasisMarkItem* >( pItem )->GetEmphasisMark() ); // setup the device & draw vcl::Font aOldFont(rRenderContext.GetFont()); Color aFontCol = COL_AUTO, aBackCol = COL_AUTO; rRenderContext.SetFont(aFont); pItem = pItemSet->GetItem( SID_ATTR_CHAR_COLOR ); // text color, when nothing is selected if ( (nullptr != pItem) && bIsNotSelected) aFontCol = static_cast< const SvxColorItem* >( pItem )->GetValue(); drawing::FillStyle style = drawing::FillStyle_NONE; // which kind of Fill style is selected pItem = pItemSet->GetItem( XATTR_FILLSTYLE ); // only when ok and not selected if ( (nullptr != pItem) && bIsNotSelected) style = static_cast< const XFillStyleItem* >( pItem )->GetValue(); switch(style) { case drawing::FillStyle_SOLID: { // set background color pItem = pItemSet->GetItem( XATTR_FILLCOLOR ); if ( nullptr != pItem ) aBackCol = static_cast< const XFillColorItem* >( pItem )->GetColorValue(); if ( aBackCol != COL_AUTO ) { rRenderContext.SetFillColor(aBackCol); rRenderContext.DrawRect(rRect); } } break; default: break; //TODO Draw the other background styles: gradient, hatching and bitmap } // when the font and background color are too similar, adjust the Font-Color if( (aFontCol != COL_AUTO) || (aBackCol != COL_AUTO) ) aFontCol = TestColorsVisible(aFontCol, (aBackCol != COL_AUTO) ? aBackCol : rRenderContext.GetBackground().GetColor()); // set text color if ( aFontCol != COL_AUTO ) rRenderContext.SetTextColor(aFontCol); // handle the push-button if (bIsNotSelected) { if (nId < MAX_STYLES_ENTRIES && m_pButtons[nId]) m_pButtons[nId]->Hide(); } else { if (nId < MAX_STYLES_ENTRIES) { if (!m_pButtons[nId] && pParent) { m_pButtons[nId] = VclPtr::Create(pParent, WB_FLATBUTTON | WB_NOPOINTERFOCUS); m_pButtons[nId]->SetSizePixel(Size(BUTTON_WIDTH, rRect.GetHeight())); m_pButtons[nId]->SetPopupMenu(m_pMenu); } m_pButtons[nId]->SetPosPixel(Point(rRect.GetWidth() - BUTTON_WIDTH, rRect.getY())); m_pButtons[nId]->Show(); } } } } } } void SvxStyleBox_Impl::UserDraw( const UserDrawEvent& rUDEvt ) { sal_uInt16 nItem = rUDEvt.GetItemId(); OUString aStyleName( GetEntry( nItem ) ); vcl::RenderContext *pDevice = rUDEvt.GetRenderContext(); pDevice->Push(PushFlags::FILLCOLOR | PushFlags::FONT | PushFlags::TEXTCOLOR); const tools::Rectangle& rRect(rUDEvt.GetRect()); bool bIsNotSelected = rUDEvt.GetItemId() != GetSelectedEntryPos(); SetupEntry(*pDevice, rUDEvt.GetWindow(), nItem, rRect, aStyleName, bIsNotSelected); UserDrawEntry(rUDEvt, aStyleName); pDevice->Pop(); // draw separator, if present DrawEntry( rUDEvt, false, false ); } IMPL_LINK(SvxStyleBox_Impl, CalcOptimalExtraUserWidth, VclWindowEvent&, event, void) { // perform the calculation only when we are opening the dropdown if (event.GetId() != VclEventId::DropdownPreOpen) return; long nMaxNormalFontWidth = 0; sal_Int32 nEntryCount = GetEntryCount(); for (sal_Int32 i = 0; i < nEntryCount; ++i) { OUString sStyleName(GetEntry(i)); tools::Rectangle aTextRectForDefaultFont; GetTextBoundRect(aTextRectForDefaultFont, sStyleName); const long nWidth = aTextRectForDefaultFont.GetWidth(); nMaxNormalFontWidth = std::max(nWidth, nMaxNormalFontWidth); } long nMaxUserDrawFontWidth = nMaxNormalFontWidth; for (sal_Int32 i = 1; i < nEntryCount-1; ++i) { OUString sStyleName(GetEntry(i)); Push(PushFlags::FILLCOLOR | PushFlags::FONT | PushFlags::TEXTCOLOR); SetupEntry(*this /*FIXME rendercontext*/, this, i, tools::Rectangle(0, 0, RECT_MAX, ITEM_HEIGHT), sStyleName, true); tools::Rectangle aTextRectForActualFont; GetTextBoundRect(aTextRectForActualFont, sStyleName); if (AdjustFontForItemHeight(this, aTextRectForActualFont, ITEM_HEIGHT)) { //Font didn't fit, so it was changed, refetch with final font size GetTextBoundRect(aTextRectForActualFont, sStyleName); } Pop(); const long nWidth = aTextRectForActualFont.GetWidth() + BUTTON_WIDTH + BUTTON_PADDING; nMaxUserDrawFontWidth = std::max(nWidth, nMaxUserDrawFontWidth); } SetUserItemSize(Size(nMaxUserDrawFontWidth - nMaxNormalFontWidth, ITEM_HEIGHT)); } // test is the color between Font- and background-color to be identify // return is always the Font-Color // when both light or dark, change the Contrast // in other case do not change the origin color // when the color is R=G=B=128 the DecreaseContrast make 128 the need an exception Color SvxStyleBox_Impl::TestColorsVisible(const Color &FontCol, const Color &BackCol) { const sal_uInt8 ChgVal = 60; // increase/decrease the Contrast Color retCol = FontCol; if ((FontCol.IsDark() == BackCol.IsDark()) && (FontCol.IsBright() == BackCol.IsBright())) { sal_uInt8 lumi = retCol.GetLuminance(); if((lumi > 120) && (lumi < 140)) retCol.DecreaseLuminance(ChgVal / 2); else retCol.DecreaseContrast(ChgVal); } return retCol; } boost::property_tree::ptree SvxStyleBox_Impl::DumpAsPropertyTree() { boost::property_tree::ptree aTree(ComboBox::DumpAsPropertyTree()); boost::property_tree::ptree aEntries; for (int i = 0; i < GetEntryCount(); ++i) { boost::property_tree::ptree aEntry; aEntry.put("", GetEntry(i)); aEntries.push_back(std::make_pair("", aEntry)); } aTree.add_child("entries", aEntries); boost::property_tree::ptree aSelected; for (int i = 0; i < GetSelectedEntryCount(); ++i) { boost::property_tree::ptree aEntry; aEntry.put("", GetSelectedEntryPos(i)); aSelected.push_back(std::make_pair("", aEntry)); } aTree.put("selectedCount", GetSelectedEntryCount()); aTree.add_child("selectedEntries", aSelected); aTree.put("command", ".uno:StyleApply"); return aTree; } static bool lcl_GetDocFontList( const FontList** ppFontList, SvxFontNameBox_Impl* pBox ) { bool bChanged = false; const SfxObjectShell* pDocSh = SfxObjectShell::Current(); const SvxFontListItem* pFontListItem = nullptr; if ( pDocSh ) pFontListItem = static_cast(pDocSh->GetItem( SID_ATTR_CHAR_FONTLIST )); else { ::std::unique_ptr aFontList(new FontList( pBox->GetParent() )); *ppFontList = aFontList.get(); pBox->SetOwnFontList(std::move(aFontList)); bChanged = true; } if ( pFontListItem ) { const FontList* pNewFontList = pFontListItem->GetFontList(); DBG_ASSERT( pNewFontList, "Doc-FontList not available!" ); // No old list, but a new list if ( !*ppFontList && pNewFontList ) { // => take over *ppFontList = pNewFontList; bChanged = true; } else { // Comparing the font lists is not perfect. // When you change the font list in the Doc, you can track // changes here only on the Listbox, because ppFontList // has already been updated. bChanged = ( ( *ppFontList != pNewFontList ) || pBox->GetListCount() != pNewFontList->GetFontNameCount() ); // HACK: Comparing is incomplete if ( bChanged ) *ppFontList = pNewFontList; } if ( pBox ) pBox->Enable(); } else if ( pBox && ( pDocSh || !ppFontList )) { // Disable box only when we have a SfxObjectShell and didn't get a font list OR // we don't have a SfxObjectShell and no current font list. // It's possible that we currently have no SfxObjectShell, but a current font list. // See #i58471: When a user set the focus into the font name combo box and opens // the help window with F1. After closing the help window, we disable the font name // combo box. The SfxObjectShell::Current() method returns in that case zero. But the // font list hasn't changed and therefore the combo box shouldn't be disabled! pBox->Disable(); } // Fill the FontBox, also the new list if necessary if ( pBox && bChanged ) { if ( *ppFontList ) pBox->Fill( *ppFontList ); else pBox->Clear(); } return bChanged; } SvxFontNameBox_Impl::SvxFontNameBox_Impl( vcl::Window* pParent, const Reference< XDispatchProvider >& rDispatchProvider,const Reference< XFrame >& _xFrame, WinBits nStyle ) : FontNameBox ( pParent, nStyle | WinBits( WB_DROPDOWN | WB_AUTOHSCROLL ) ), pFontList ( nullptr ), aLogicalSize ( 60,160 ), nFtCount ( 0 ), bRelease ( true ), m_xDispatchProvider( rDispatchProvider ), m_xFrame (_xFrame), mbEndPreview(false), mbCheckingUnknownFont(false) { SetOptimalSize(); EnableControls_Impl(); GetSubEdit()->AddEventListener( LINK( this, SvxFontNameBox_Impl, CheckAndMarkUnknownFont )); set_id("fontnamecombobox"); } SvxFontNameBox_Impl::~SvxFontNameBox_Impl() { disposeOnce(); } void SvxFontNameBox_Impl::dispose() { GetSubEdit()->RemoveEventListener( LINK( this, SvxFontNameBox_Impl, CheckAndMarkUnknownFont )); FontNameBox::dispose(); } void SvxFontNameBox_Impl::FillList() { // Save old Selection, set back in the end Selection aOldSel = GetSelection(); // Did Doc-Fontlist change? lcl_GetDocFontList( &pFontList, this ); aCurText = GetText(); SetSelection( aOldSel ); } IMPL_LINK( SvxFontNameBox_Impl, CheckAndMarkUnknownFont, VclWindowEvent&, event, void ) { if( event.GetId() != VclEventId::EditModify ) return; if (mbCheckingUnknownFont) //tdf#117537 block rentry return; mbCheckingUnknownFont = true; OUString fontname = GetSubEdit()->GetText(); lcl_GetDocFontList( &pFontList, this ); // If the font is unknown, show it in italic. vcl::Font font = GetControlFont(); if( pFontList != nullptr && pFontList->IsAvailable( fontname )) { if( font.GetItalic() != ITALIC_NONE ) { font.SetItalic( ITALIC_NONE ); SetControlFont( font ); SetQuickHelpText( SvxResId( RID_SVXSTR_CHARFONTNAME )); } } else { if( font.GetItalic() != ITALIC_NORMAL ) { font.SetItalic( ITALIC_NORMAL ); SetControlFont( font ); SetQuickHelpText( SvxResId( RID_SVXSTR_CHARFONTNAME_NOTAVAILABLE )); } } mbCheckingUnknownFont = false; } void SvxFontNameBox_Impl::Update( const css::awt::FontDescriptor* pFontDesc ) { if ( pFontDesc ) { aCurFont.SetFamilyName ( pFontDesc->Name ); aCurFont.SetFamily ( FontFamily( pFontDesc->Family ) ); aCurFont.SetStyleName ( pFontDesc->StyleName ); aCurFont.SetPitch ( FontPitch( pFontDesc->Pitch ) ); aCurFont.SetCharSet ( rtl_TextEncoding( pFontDesc->CharSet ) ); } OUString aCurName = aCurFont.GetFamilyName(); if ( GetText() != aCurName ) SetText( aCurName ); } bool SvxFontNameBox_Impl::PreNotify( NotifyEvent& rNEvt ) { MouseNotifyEvent nType = rNEvt.GetType(); if ( MouseNotifyEvent::MOUSEBUTTONDOWN == nType || MouseNotifyEvent::GETFOCUS == nType ) { EnableControls_Impl(); FillList(); } return FontNameBox::PreNotify( rNEvt ); } bool SvxFontNameBox_Impl::EventNotify( NotifyEvent& rNEvt ) { bool bHandled = false; mbEndPreview = false; if ( rNEvt.GetType() == MouseNotifyEvent::KEYUP ) mbEndPreview = true; if ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT ) { sal_uInt16 nCode = rNEvt.GetKeyEvent()->GetKeyCode().GetCode(); switch ( nCode ) { case KEY_RETURN: case KEY_TAB: { if ( KEY_TAB == nCode ) bRelease = false; else bHandled = true; Select(); break; } case KEY_ESCAPE: SetText( aCurText ); if ( typeid( *GetParent() ) != typeid( sfx2::sidebar::SidebarToolBox ) ) ReleaseFocus_Impl(); EndPreview(); break; } } else if ( MouseNotifyEvent::LOSEFOCUS == rNEvt.GetType() ) { vcl::Window* pFocusWin = Application::GetFocusWindow(); if ( !HasFocus() && GetSubEdit() != pFocusWin ) SetText( GetSavedValue() ); // send EndPreview EndPreview(); } return bHandled || FontNameBox::EventNotify( rNEvt ); } void SvxFontNameBox_Impl::SetOptimalSize() { Size aSize(LogicToPixel(aLogicalSize, MapMode(MapUnit::MapAppFont))); set_width_request(aSize.Width()); set_height_request(aSize.Height()); SetSizePixel(aSize); } void SvxFontNameBox_Impl::DataChanged( const DataChangedEvent& rDCEvt ) { if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) ) { SetOptimalSize(); } else if ( ( rDCEvt.GetType() == DataChangedEventType::FONTS ) || ( rDCEvt.GetType() == DataChangedEventType::DISPLAY ) ) { // The old font list in shell has likely been destroyed at this point, so we need to get // the new one before doing anything further. lcl_GetDocFontList( &pFontList, this ); } FontNameBox::DataChanged( rDCEvt ); } void SvxFontNameBox_Impl::ReleaseFocus_Impl() { if ( !bRelease ) { bRelease = true; return; } if ( m_xFrame.is() && m_xFrame->getContainerWindow().is() ) m_xFrame->getContainerWindow()->setFocus(); } void SvxFontNameBox_Impl::EnableControls_Impl() { SvtFontOptions aFontOpt; bool bEnable = aFontOpt.IsFontHistoryEnabled(); sal_uInt16 nEntries = bEnable ? MAX_MRU_FONTNAME_ENTRIES : 0; if ( GetMaxMRUCount() != nEntries ) { // refill in the next GetFocus-Handler pFontList = nullptr; Clear(); SetMaxMRUCount( nEntries ); } bEnable = aFontOpt.IsFontWYSIWYGEnabled(); EnableWYSIWYG( bEnable ); } void SvxFontNameBox_Impl::UserDraw( const UserDrawEvent& rUDEvt ) { FontNameBox::UserDraw( rUDEvt ); // Hack - GetStyle now contains the currently // selected item in the list box // ItemId contains the id of the current item to draw // or select if ( rUDEvt.GetItemId() == rUDEvt.GetStyle() ) { OUString fontName(GetText()); if (IsInDropDown()) { /* * when in dropdown mode the selected item should be * used and not the current selection */ fontName = GetEntry(rUDEvt.GetItemId()); } Sequence< PropertyValue > aArgs( 1 ); FontMetric aFontMetric( pFontList->Get( fontName, aCurFont.GetWeight(), aCurFont.GetItalic() ) ); SvxFontItem aFontItem( aFontMetric.GetFamilyType(), aFontMetric.GetFamilyName(), aFontMetric.GetStyleName(), aFontMetric.GetPitch(), aFontMetric.GetCharSet(), SID_ATTR_CHAR_FONT ); aFontItem.QueryValue( aArgs[0].Value ); aArgs[0].Name = "CharPreviewFontName"; SfxToolBoxControl::Dispatch( m_xDispatchProvider, ".uno:CharPreviewFontName", aArgs ); } } void SvxFontNameBox_Impl::Select() { FontNameBox::Select(); Sequence< PropertyValue > aArgs( 1 ); std::unique_ptr pFontItem; if ( pFontList ) { FontMetric aFontMetric( pFontList->Get( GetText(), aCurFont.GetWeight(), aCurFont.GetItalic() ) ); aCurFont = aFontMetric; pFontItem.reset( new SvxFontItem( aFontMetric.GetFamilyType(), aFontMetric.GetFamilyName(), aFontMetric.GetStyleName(), aFontMetric.GetPitch(), aFontMetric.GetCharSet(), SID_ATTR_CHAR_FONT ) ); Any a; pFontItem->QueryValue( a ); aArgs[0].Value = a; } if ( !IsTravelSelect() ) { // #i33380# DR 2004-09-03 Moved the following line above the Dispatch() call. // This instance may be deleted in the meantime (i.e. when a dialog is opened // while in Dispatch()), accessing members will crash in this case. ReleaseFocus_Impl(); EndPreview(); if (pFontItem) { aArgs[0].Name = "CharFontName"; SfxToolBoxControl::Dispatch( m_xDispatchProvider, ".uno:CharFontName", aArgs ); } } else { if ( mbEndPreview ) { EndPreview(); return; } if (pFontItem) { aArgs[0].Name = "CharPreviewFontName"; SfxToolBoxControl::Dispatch( m_xDispatchProvider, ".uno:CharPreviewFontName", aArgs ); } } } boost::property_tree::ptree SvxFontNameBox_Impl::DumpAsPropertyTree() { boost::property_tree::ptree aTree(FontNameBox::DumpAsPropertyTree()); boost::property_tree::ptree aEntries; for (int i = 0; i < GetEntryCount(); ++i) { boost::property_tree::ptree aEntry; aEntry.put("", GetEntry(i)); aEntries.push_back(std::make_pair("", aEntry)); } aTree.add_child("entries", aEntries); boost::property_tree::ptree aSelected; for (int i = 0; i < GetSelectedEntryCount(); ++i) { boost::property_tree::ptree aEntry; aEntry.put("", GetSelectedEntryPos(i)); aSelected.push_back(std::make_pair("", aEntry)); } aTree.put("selectedCount", GetSelectedEntryCount()); aTree.add_child("selectedEntries", aSelected); aTree.put("command", ".uno:CharFontName"); return aTree; } SvxColorWindow::SvxColorWindow(const OUString& rCommand, std::shared_ptr const & rPaletteManager, ColorStatus& rColorStatus, sal_uInt16 nSlotId, const Reference< XFrame >& rFrame, vcl::Window* pParentWindow, bool bReuseParentForPicker, ColorSelectFunction const & aFunction): ToolbarPopup( rFrame, pParentWindow, "palette_popup_window", "svx/ui/oldcolorwindow.ui" ), theSlotId( nSlotId ), maCommand( rCommand ), mxParentWindow(pParentWindow), mxPaletteManager( rPaletteManager ), mrColorStatus( rColorStatus ), maColorSelectFunction(aFunction), mbReuseParentForPicker(bReuseParentForPicker) { get(mpPaletteListBox, "palette_listbox"); get(mpButtonAutoColor, "auto_color_button"); get(mpButtonNoneColor, "none_color_button"); get(mpButtonPicker, "color_picker_button"); get(mpColorSet, "colorset"); get(mpRecentColorSet, "recent_colorset"); get(mpAutomaticSeparator, "separator4"); mpColorSet->SetStyle( WinBits(WB_FLATVALUESET | WB_ITEMBORDER | WB_3DLOOK | WB_NO_DIRECTSELECT | WB_TABSTOP) ); mpRecentColorSet->SetStyle( WinBits(WB_FLATVALUESET | WB_ITEMBORDER | WB_3DLOOK | WB_NO_DIRECTSELECT | WB_TABSTOP) ); switch ( theSlotId ) { case SID_ATTR_CHAR_COLOR_BACKGROUND: case SID_BACKGROUND_COLOR: case SID_ATTR_CHAR_BACK_COLOR: case SID_TABLE_CELL_BACKGROUND_COLOR: { mpButtonAutoColor->SetText( SvxResId( RID_SVXSTR_NOFILL ) ); break; } case SID_AUTHOR_COLOR: { mpButtonAutoColor->SetText( SvxResId( RID_SVXSTR_BY_AUTHOR ) ); break; } case SID_BMPMASK_COLOR: { mpButtonAutoColor->SetText( SvxResId( RID_SVXSTR_TRANSPARENT ) ); break; } case SID_ATTR_CHAR_COLOR: case SID_ATTR_CHAR_COLOR2: case SID_EXTRUSION_3D_COLOR: { mpButtonAutoColor->SetText(EditResId(RID_SVXSTR_AUTOMATIC)); break; } case SID_FM_CTL_PROPERTIES: { mpButtonAutoColor->SetText( SvxResId( RID_SVXSTR_DEFAULT ) ); break; } default: { mpButtonAutoColor->Hide(); mpAutomaticSeparator->Hide(); break; } } mpColorSet->SetAccessibleName( GetText() ); mpPaletteListBox->SetStyle( mpPaletteListBox->GetStyle() | WB_BORDER ); mpPaletteListBox->SetSelectHdl( LINK( this, SvxColorWindow, SelectPaletteHdl ) ); mpPaletteListBox->AdaptDropDownLineCountToMaximum(); std::vector aPaletteList = mxPaletteManager->GetPaletteList(); for (const auto& rPalette : aPaletteList ) { mpPaletteListBox->InsertEntry( rPalette ); } OUString aPaletteName( officecfg::Office::Common::UserColors::PaletteName::get() ); mpPaletteListBox->SelectEntry( aPaletteName ); const sal_Int32 nSelectedEntry(mpPaletteListBox->GetSelectedEntryPos()); if (nSelectedEntry != LISTBOX_ENTRY_NOTFOUND) mxPaletteManager->SetPalette(nSelectedEntry); mpButtonAutoColor->SetClickHdl( LINK( this, SvxColorWindow, AutoColorClickHdl ) ); mpButtonNoneColor->SetClickHdl( LINK( this, SvxColorWindow, AutoColorClickHdl ) ); mpButtonPicker->SetClickHdl( LINK( this, SvxColorWindow, OpenPickerClickHdl ) ); mpColorSet->SetSelectHdl( LINK( this, SvxColorWindow, SelectHdl ) ); mpRecentColorSet->SetSelectHdl( LINK( this, SvxColorWindow, SelectHdl ) ); SetHelpId( HID_POPUP_COLOR ); mpColorSet->SetHelpId( HID_POPUP_COLOR_CTRL ); mxPaletteManager->ReloadColorSet(*mpColorSet); const sal_uInt32 nMaxItems(SvxColorValueSet::getMaxRowCount() * SvxColorValueSet::getColumnCount()); Size aSize = mpColorSet->layoutAllVisible(nMaxItems); mpColorSet->set_height_request(aSize.Height()); mpColorSet->set_width_request(aSize.Width()); mxPaletteManager->ReloadRecentColorSet(*mpRecentColorSet); aSize = mpRecentColorSet->layoutAllVisible(mxPaletteManager->GetRecentColorCount()); mpRecentColorSet->set_height_request(aSize.Height()); mpRecentColorSet->set_width_request(aSize.Width()); AddStatusListener( ".uno:ColorTableState" ); AddStatusListener( maCommand ); if ( maCommand == ".uno:FrameLineColor" ) { AddStatusListener( ".uno:BorderTLBR" ); AddStatusListener( ".uno:BorderBLTR" ); } } ColorWindow::ColorWindow(std::shared_ptr const & rPaletteManager, ColorStatus& rColorStatus, sal_uInt16 nSlotId, const Reference< XFrame >& rFrame, weld::Window* pParentWindow, const MenuOrToolMenuButton& rMenuButton, ColorSelectFunction const & aFunction) : ToolbarPopupBase(rFrame) , m_xBuilder(Application::CreateBuilder(rMenuButton.get_widget(), "svx/ui/colorwindow.ui")) , theSlotId(nSlotId) , mpParentWindow(pParentWindow) , maMenuButton(rMenuButton) , mxPaletteManager(rPaletteManager) , mrColorStatus(rColorStatus) , maColorSelectFunction(aFunction) , mxColorSet(new ColorValueSet(m_xBuilder->weld_scrolled_window("colorsetwin"))) , mxRecentColorSet(new ColorValueSet(nullptr)) , mxTopLevel(m_xBuilder->weld_container("palette_popup_window")) , mxPaletteListBox(m_xBuilder->weld_combo_box("palette_listbox")) , mxButtonAutoColor(m_xBuilder->weld_button("auto_color_button")) , mxButtonNoneColor(m_xBuilder->weld_button("none_color_button")) , mxButtonPicker(m_xBuilder->weld_button("color_picker_button")) , mxAutomaticSeparator(m_xBuilder->weld_widget("separator4")) , mxColorSetWin(new weld::CustomWeld(*m_xBuilder, "colorset", *mxColorSet)) , mxRecentColorSetWin(new weld::CustomWeld(*m_xBuilder, "recent_colorset", *mxRecentColorSet)) , mpDefaultButton(nullptr) { mxColorSet->SetStyle( WinBits(WB_FLATVALUESET | WB_ITEMBORDER | WB_3DLOOK | WB_NO_DIRECTSELECT | WB_TABSTOP) ); mxRecentColorSet->SetStyle( WinBits(WB_FLATVALUESET | WB_ITEMBORDER | WB_3DLOOK | WB_NO_DIRECTSELECT | WB_TABSTOP) ); switch ( theSlotId ) { case SID_ATTR_CHAR_COLOR_BACKGROUND: case SID_BACKGROUND_COLOR: case SID_ATTR_CHAR_BACK_COLOR: case SID_TABLE_CELL_BACKGROUND_COLOR: { mxButtonAutoColor->set_label( SvxResId( RID_SVXSTR_NOFILL ) ); break; } case SID_AUTHOR_COLOR: { mxButtonAutoColor->set_label( SvxResId( RID_SVXSTR_BY_AUTHOR ) ); break; } case SID_BMPMASK_COLOR: { mxButtonAutoColor->set_label( SvxResId( RID_SVXSTR_TRANSPARENT ) ); break; } case SID_ATTR_CHAR_COLOR: case SID_ATTR_CHAR_COLOR2: case SID_EXTRUSION_3D_COLOR: { mxButtonAutoColor->set_label(EditResId(RID_SVXSTR_AUTOMATIC)); break; } case SID_FM_CTL_PROPERTIES: { mxButtonAutoColor->set_label( SvxResId( RID_SVXSTR_DEFAULT ) ); break; } default: { mxButtonAutoColor->hide(); mxAutomaticSeparator->hide(); break; } } mxPaletteListBox->connect_changed(LINK(this, ColorWindow, SelectPaletteHdl)); std::vector aPaletteList = mxPaletteManager->GetPaletteList(); mxPaletteListBox->freeze(); for (const auto& rPalette : aPaletteList) mxPaletteListBox->append_text(rPalette); mxPaletteListBox->thaw(); OUString aPaletteName( officecfg::Office::Common::UserColors::PaletteName::get() ); mxPaletteListBox->set_active_text(aPaletteName); const int nSelectedEntry(mxPaletteListBox->get_active()); if (nSelectedEntry != -1) mxPaletteManager->SetPalette(nSelectedEntry); mxButtonAutoColor->connect_clicked(LINK(this, ColorWindow, AutoColorClickHdl)); mxButtonNoneColor->connect_clicked(LINK(this, ColorWindow, AutoColorClickHdl)); mxButtonPicker->connect_clicked(LINK(this, ColorWindow, OpenPickerClickHdl)); mxColorSet->SetSelectHdl(LINK( this, ColorWindow, SelectHdl)); mxRecentColorSet->SetSelectHdl(LINK( this, ColorWindow, SelectHdl)); mxTopLevel->set_help_id(HID_POPUP_COLOR); mxTopLevel->connect_focus_in(LINK(this, ColorWindow, FocusHdl)); mxColorSet->SetHelpId(HID_POPUP_COLOR_CTRL); mxPaletteManager->ReloadColorSet(*mxColorSet); const sal_uInt32 nMaxItems(SvxColorValueSet::getMaxRowCount() * SvxColorValueSet::getColumnCount()); Size aSize = mxColorSet->layoutAllVisible(nMaxItems); mxColorSet->set_size_request(aSize.Width(), aSize.Height()); mxPaletteManager->ReloadRecentColorSet(*mxRecentColorSet); aSize = mxRecentColorSet->layoutAllVisible(mxPaletteManager->GetRecentColorCount()); mxRecentColorSet->set_size_request(aSize.Width(), aSize.Height()); AddStatusListener( ".uno:ColorTableState" ); } IMPL_LINK_NOARG(ColorWindow, FocusHdl, weld::Widget&, void) { mxColorSet->GrabFocus(); } void ColorWindow::ShowNoneButton() { mxButtonNoneColor->show(); } SvxColorWindow::~SvxColorWindow() { disposeOnce(); } ColorWindow::~ColorWindow() { } void SvxColorWindow::dispose() { mpColorSet.clear(); mpRecentColorSet.clear(); mpPaletteListBox.clear(); mpButtonAutoColor.clear(); mpButtonNoneColor.clear(); mpButtonPicker.clear(); mpAutomaticSeparator.clear(); mxParentWindow.clear(); ToolbarPopup::dispose(); } void SvxColorWindow::KeyInput( const KeyEvent& rKEvt ) { mpColorSet->GrabFocus(); mpColorSet->KeyInput(rKEvt); } NamedColor SvxColorWindow::GetSelectEntryColor(ValueSet const * pColorSet) { Color aColor = pColorSet->GetItemColor(pColorSet->GetSelectedItemId()); OUString sColorName = pColorSet->GetItemText(pColorSet->GetSelectedItemId()); return std::make_pair(aColor, sColorName); } NamedColor ColorWindow::GetSelectEntryColor(SvtValueSet const * pColorSet) { Color aColor = pColorSet->GetItemColor(pColorSet->GetSelectedItemId()); OUString sColorName = pColorSet->GetItemText(pColorSet->GetSelectedItemId()); return std::make_pair(aColor, sColorName); } namespace { NamedColor GetAutoColor(sal_uInt16 nSlotId) { Color aColor; OUString sColorName; switch (nSlotId) { case SID_ATTR_CHAR_COLOR_BACKGROUND: case SID_BACKGROUND_COLOR: case SID_ATTR_CHAR_BACK_COLOR: case SID_TABLE_CELL_BACKGROUND_COLOR: aColor = COL_TRANSPARENT; sColorName = SvxResId(RID_SVXSTR_NOFILL); break; case SID_AUTHOR_COLOR: aColor = COL_TRANSPARENT; sColorName = SvxResId(RID_SVXSTR_BY_AUTHOR); break; case SID_BMPMASK_COLOR: aColor = COL_TRANSPARENT; sColorName = SvxResId(RID_SVXSTR_TRANSPARENT); break; case SID_FM_CTL_PROPERTIES: aColor = COL_TRANSPARENT; sColorName = SvxResId(RID_SVXSTR_DEFAULT); break; case SID_ATTR_CHAR_COLOR: case SID_ATTR_CHAR_COLOR2: case SID_EXTRUSION_3D_COLOR: default: aColor = COL_AUTO; sColorName = EditResId(RID_SVXSTR_AUTOMATIC); break; } return std::make_pair(aColor, sColorName); } NamedColor GetNoneColor() { return std::make_pair(COL_NONE_COLOR, SvxResId(RID_SVXSTR_NONE)); } } NamedColor SvxColorWindow::GetSelectEntryColor() const { if (!mpColorSet->IsNoSelection()) return GetSelectEntryColor(mpColorSet); if (!mpRecentColorSet->IsNoSelection()) return GetSelectEntryColor(mpRecentColorSet); if (mpButtonNoneColor->GetStyle() & WB_DEFBUTTON) return GetNoneColor(); return GetAutoColor(); } NamedColor ColorWindow::GetSelectEntryColor() const { if (!mxColorSet->IsNoSelection()) return GetSelectEntryColor(mxColorSet.get()); if (!mxRecentColorSet->IsNoSelection()) return GetSelectEntryColor(mxRecentColorSet.get()); if (mxButtonNoneColor.get() == mpDefaultButton) return GetNoneColor(); return GetAutoColor(); } IMPL_LINK(SvxColorWindow, SelectHdl, ValueSet*, pColorSet, void) { VclPtr xThis(this); NamedColor aNamedColor = GetSelectEntryColor(pColorSet); if ( pColorSet != mpRecentColorSet ) { mxPaletteManager->AddRecentColor(aNamedColor.first, aNamedColor.second); if ( !IsInPopupMode() ) mxPaletteManager->ReloadRecentColorSet(*mpRecentColorSet); } if ( IsInPopupMode() ) EndPopupMode(); maSelectedLink.Call(aNamedColor); maColorSelectFunction(maCommand, aNamedColor); } IMPL_LINK(ColorWindow, SelectHdl, SvtValueSet*, pColorSet, void) { NamedColor aNamedColor = GetSelectEntryColor(pColorSet); if (pColorSet != mxRecentColorSet.get()) { mxPaletteManager->AddRecentColor(aNamedColor.first, aNamedColor.second); if (!maMenuButton.get_active()) mxPaletteManager->ReloadRecentColorSet(*mxRecentColorSet); } if (maMenuButton.get_active()) maMenuButton.set_active(false); maColorSelectFunction(OUString(), aNamedColor); } IMPL_LINK_NOARG(SvxColorWindow, SelectPaletteHdl, ListBox&, void) { sal_Int32 nPos = mpPaletteListBox->GetSelectedEntryPos(); mxPaletteManager->SetPalette( nPos ); mxPaletteManager->ReloadColorSet(*mpColorSet); mpColorSet->layoutToGivenHeight(mpColorSet->GetSizePixel().Height(), mxPaletteManager->GetColorCount()); } IMPL_LINK_NOARG(ColorWindow, SelectPaletteHdl, weld::ComboBox&, void) { int nPos = mxPaletteListBox->get_active(); mxPaletteManager->SetPalette( nPos ); mxPaletteManager->ReloadColorSet(*mxColorSet); mxColorSet->layoutToGivenHeight(mxColorSet->GetOutputSizePixel().Height(), mxPaletteManager->GetColorCount()); } NamedColor SvxColorWindow::GetAutoColor() const { return ::GetAutoColor(theSlotId); } NamedColor ColorWindow::GetAutoColor() const { return ::GetAutoColor(theSlotId); } IMPL_LINK(SvxColorWindow, AutoColorClickHdl, Button*, pButton, void) { VclPtr xThis(this); NamedColor aNamedColor = pButton == mpButtonAutoColor ? GetAutoColor() : GetNoneColor(); mpRecentColorSet->SetNoSelection(); if ( IsInPopupMode() ) EndPopupMode(); maSelectedLink.Call(aNamedColor); maColorSelectFunction(maCommand, aNamedColor); } IMPL_LINK(ColorWindow, AutoColorClickHdl, weld::Button&, rButton, void) { NamedColor aNamedColor = &rButton == mxButtonAutoColor.get() ? GetAutoColor() : GetNoneColor(); mxRecentColorSet->SetNoSelection(); if (maMenuButton.get_active()) maMenuButton.set_active(false); maColorSelectFunction(OUString(), aNamedColor); } IMPL_LINK_NOARG(SvxColorWindow, OpenPickerClickHdl, Button*, void) { VclPtr xThis(this); if ( IsInPopupMode() ) EndPopupMode(); weld::Window* pParentFrame; if (mbReuseParentForPicker) { pParentFrame = mxParentWindow->GetFrameWeld(); } else { const css::uno::Reference xParent = mxFrame->getContainerWindow(); pParentFrame = Application::GetFrameWeld(xParent); } mxPaletteManager->PopupColorPicker(pParentFrame, maCommand, GetSelectEntryColor().first); } IMPL_LINK_NOARG(ColorWindow, OpenPickerClickHdl, weld::Button&, void) { if (maMenuButton.get_active()) maMenuButton.set_active(false); mxPaletteManager->PopupColorPicker(mpParentWindow, OUString(), GetSelectEntryColor().first); } void SvxColorWindow::StartSelection() { mpColorSet->StartSelection(); mpRecentColorSet->StartSelection(); } void SvxColorWindow::SetNoSelection() { mpColorSet->SetNoSelection(); mpRecentColorSet->SetNoSelection(); mpButtonAutoColor->set_property("has-default", "false"); mpButtonNoneColor->set_property("has-default", "false"); } void ColorWindow::SetNoSelection() { mxColorSet->SetNoSelection(); mxRecentColorSet->SetNoSelection(); mpDefaultButton = nullptr; } bool SvxColorWindow::IsNoSelection() const { if (!mpColorSet->IsNoSelection()) return false; if (!mpRecentColorSet->IsNoSelection()) return false; return !mpButtonAutoColor->IsVisible() && !mpButtonNoneColor->IsVisible(); } bool ColorWindow::IsNoSelection() const { if (!mxColorSet->IsNoSelection()) return false; if (!mxRecentColorSet->IsNoSelection()) return false; return !mxButtonAutoColor->get_visible() && !mxButtonNoneColor->get_visible(); } void SvxColorWindow::statusChanged( const css::frame::FeatureStateEvent& rEvent ) { if (rEvent.FeatureURL.Complete == ".uno:ColorTableState") { if (rEvent.IsEnabled && mxPaletteManager->GetPalette() == 0) { mxPaletteManager->ReloadColorSet(*mpColorSet); mpColorSet->layoutToGivenHeight(mpColorSet->GetSizePixel().Height(), mxPaletteManager->GetColorCount()); } } else { mrColorStatus.statusChanged(rEvent); SelectEntry(mrColorStatus.GetColor()); } } void ColorWindow::statusChanged( const css::frame::FeatureStateEvent& rEvent ) { if (rEvent.FeatureURL.Complete == ".uno:ColorTableState") { if (rEvent.IsEnabled && mxPaletteManager->GetPalette() == 0) { mxPaletteManager->ReloadColorSet(*mxColorSet); mxColorSet->layoutToGivenHeight(mxColorSet->GetOutputSizePixel().Height(), mxPaletteManager->GetColorCount()); } } else { mrColorStatus.statusChanged(rEvent); SelectEntry(mrColorStatus.GetColor()); } } bool SvxColorWindow::SelectValueSetEntry(SvxColorValueSet* pColorSet, const Color& rColor) { for (size_t i = 1; i <= pColorSet->GetItemCount(); ++i) { if (rColor == pColorSet->GetItemColor(i)) { pColorSet->SelectItem(i); return true; } } return false; } bool ColorWindow::SelectValueSetEntry(ColorValueSet* pColorSet, const Color& rColor) { for (size_t i = 1; i <= pColorSet->GetItemCount(); ++i) { if (rColor == pColorSet->GetItemColor(i)) { pColorSet->SelectItem(i); return true; } } return false; } void SvxColorWindow::SelectEntry(const NamedColor& rNamedColor) { SetNoSelection(); const Color &rColor = rNamedColor.first; if (rColor == COL_TRANSPARENT || rColor == COL_AUTO) { mpButtonAutoColor->set_property("has-default", "true"); return; } if (mpButtonNoneColor->IsVisible() && rColor == COL_NONE_COLOR) { mpButtonNoneColor->set_property("has-default", "true"); return; } // try current palette bool bFoundColor = SelectValueSetEntry(mpColorSet, rColor); // try recently used if (!bFoundColor) bFoundColor = SelectValueSetEntry(mpRecentColorSet, rColor); // if it's not there, add it there now to the end of the recently used // so its available somewhere handy, but not without trashing the // whole recently used if (!bFoundColor) { const OUString& rColorName = rNamedColor.second; mxPaletteManager->AddRecentColor(rColor, rColorName, false); mxPaletteManager->ReloadRecentColorSet(*mpRecentColorSet); SelectValueSetEntry(mpRecentColorSet, rColor); } } void SvxColorWindow::SelectEntry(const Color& rColor) { OUString sColorName = "#" + rColor.AsRGBHexString().toAsciiUpperCase(); SvxColorWindow::SelectEntry(std::make_pair(rColor, sColorName)); } void ColorWindow::SelectEntry(const NamedColor& rNamedColor) { SetNoSelection(); const Color &rColor = rNamedColor.first; if (mxButtonAutoColor->get_visible() && (rColor == COL_TRANSPARENT || rColor == COL_AUTO)) { mpDefaultButton = mxButtonAutoColor.get(); mxButtonAutoColor->grab_focus(); return; } if (mxButtonNoneColor->get_visible() && rColor == COL_NONE_COLOR) { mpDefaultButton = mxButtonNoneColor.get(); mxButtonNoneColor->grab_focus(); return; } // try current palette bool bFoundColor = SelectValueSetEntry(mxColorSet.get(), rColor); // try recently used if (!bFoundColor) bFoundColor = SelectValueSetEntry(mxRecentColorSet.get(), rColor); // if it's not there, add it there now to the end of the recently used // so its available somewhere handy, but not without trashing the // whole recently used if (!bFoundColor) { const OUString& rColorName = rNamedColor.second; mxPaletteManager->AddRecentColor(rColor, rColorName, false); mxPaletteManager->ReloadRecentColorSet(*mxRecentColorSet); SelectValueSetEntry(mxRecentColorSet.get(), rColor); } } void ColorWindow::SelectEntry(const Color& rColor) { OUString sColorName = "#" + rColor.AsRGBHexString().toAsciiUpperCase(); ColorWindow::SelectEntry(std::make_pair(rColor, sColorName)); } ColorStatus::ColorStatus() : maColor( COL_TRANSPARENT ), maTLBRColor( COL_TRANSPARENT ), maBLTRColor( COL_TRANSPARENT ) { } ColorStatus::~ColorStatus() { } void ColorStatus::statusChanged( const css::frame::FeatureStateEvent& rEvent ) { Color aColor( COL_TRANSPARENT ); css::table::BorderLine2 aTable; if ( rEvent.State >>= aTable ) { SvxBorderLine aLine; SvxBoxItem::LineToSvxLine( aTable, aLine, false ); if ( !aLine.isEmpty() ) aColor = aLine.GetColor(); } else rEvent.State >>= aColor; if ( rEvent.FeatureURL.Path == "BorderTLBR" ) maTLBRColor = aColor; else if ( rEvent.FeatureURL.Path == "BorderBLTR" ) maBLTRColor = aColor; else maColor = aColor; } Color ColorStatus::GetColor() { Color aColor( maColor ); if ( maTLBRColor != COL_TRANSPARENT ) { if ( aColor != maTLBRColor && aColor != COL_TRANSPARENT ) return COL_TRANSPARENT; aColor = maTLBRColor; } if ( maBLTRColor != COL_TRANSPARENT ) { if ( aColor != maBLTRColor && aColor != COL_TRANSPARENT ) return COL_TRANSPARENT; return maBLTRColor; } return aColor; } SvxFrameWindow_Impl::SvxFrameWindow_Impl ( svt::ToolboxController& rController, vcl::Window* pParentWindow ) : ToolbarPopup( rController.getFrameInterface(), pParentWindow, WB_STDPOPUP | WB_MOVEABLE | WB_CLOSEABLE ), aFrameSet ( VclPtr::Create(this, WinBits( WB_ITEMBORDER | WB_DOUBLEBORDER | WB_3DLOOK | WB_NO_DIRECTSELECT )) ), mrController( rController ), bParagraphMode(false) { AddStatusListener(".uno:BorderReducedMode"); InitImageList(); /* * 1 2 3 4 * ------------------------------------- * NONE LEFT RIGHT LEFTRIGHT * TOP BOTTOM TOPBOTTOM OUTER * ------------------------------------- * HOR HORINNER VERINNER ALL <- can be switched of via bParagraphMode */ sal_uInt16 i = 0; for ( i=1; i<9; i++ ) aFrameSet->InsertItem(i, Image(aImgVec[i-1])); //bParagraphMode should have been set in StateChanged if ( !bParagraphMode ) for ( i = 9; i < 13; i++ ) aFrameSet->InsertItem(i, Image(aImgVec[i-1])); aFrameSet->SetColCount( 4 ); aFrameSet->SetSelectHdl( LINK( this, SvxFrameWindow_Impl, SelectHdl ) ); CalcSizeValueSet(); SetHelpId( HID_POPUP_FRAME ); SetText( SvxResId(RID_SVXSTR_FRAME) ); aFrameSet->SetAccessibleName( SvxResId(RID_SVXSTR_FRAME) ); aFrameSet->Show(); } SvxFrameWindow_Impl::~SvxFrameWindow_Impl() { disposeOnce(); } void SvxFrameWindow_Impl::dispose() { aFrameSet.disposeAndClear(); ToolbarPopup::dispose(); } void SvxFrameWindow_Impl::GetFocus() { if (aFrameSet) aFrameSet->StartSelection(); } void SvxFrameWindow_Impl::KeyInput( const KeyEvent& rKEvt ) { aFrameSet->GrabFocus(); aFrameSet->KeyInput( rKEvt ); } void SvxFrameWindow_Impl::DataChanged( const DataChangedEvent& rDCEvt ) { ToolbarPopup::DataChanged( rDCEvt ); if ( ( rDCEvt.GetType() == DataChangedEventType::SETTINGS ) && ( rDCEvt.GetFlags() & AllSettingsFlags::STYLE ) ) { InitImageList(); sal_uInt16 nNumOfItems = aFrameSet->GetItemCount(); for ( sal_uInt16 i = 1 ; i <= nNumOfItems ; ++i ) aFrameSet->SetItemImage( i, Image(aImgVec[i-1]) ); } } namespace { enum class FrmValidFlags { NONE = 0x00, Left = 0x01, Right = 0x02, Top = 0x04, Bottom = 0x08, HInner = 0x10, VInner = 0x20, AllMask = 0x3f, }; } namespace o3tl { template<> struct typed_flags : is_typed_flags {}; } // By default unset lines remain unchanged. // Via Shift unset lines are reset IMPL_LINK_NOARG(SvxFrameWindow_Impl, SelectHdl, ValueSet*, void) { VclPtr xThis(this); SvxBoxItem aBorderOuter( SID_ATTR_BORDER_OUTER ); SvxBoxInfoItem aBorderInner( SID_ATTR_BORDER_INNER ); SvxBorderLine theDefLine; SvxBorderLine *pLeft = nullptr, *pRight = nullptr, *pTop = nullptr, *pBottom = nullptr; sal_uInt16 nSel = aFrameSet->GetSelectedItemId(); sal_uInt16 nModifier = aFrameSet->GetModifier(); FrmValidFlags nValidFlags = FrmValidFlags::NONE; theDefLine.GuessLinesWidths(theDefLine.GetBorderLineStyle(), DEF_LINE_WIDTH_0); switch ( nSel ) { case 1: nValidFlags |= FrmValidFlags::AllMask; break; // NONE case 2: pLeft = &theDefLine; nValidFlags |= FrmValidFlags::Left; break; // LEFT case 3: pRight = &theDefLine; nValidFlags |= FrmValidFlags::Right; break; // RIGHT case 4: pLeft = pRight = &theDefLine; nValidFlags |= FrmValidFlags::Right|FrmValidFlags::Left; break; // LEFTRIGHT case 5: pTop = &theDefLine; nValidFlags |= FrmValidFlags::Top; break; // TOP case 6: pBottom = &theDefLine; nValidFlags |= FrmValidFlags::Bottom; break; // BOTTOM case 7: pTop = pBottom = &theDefLine; nValidFlags |= FrmValidFlags::Bottom|FrmValidFlags::Top; break; // TOPBOTTOM case 8: pLeft = pRight = pTop = pBottom = &theDefLine; nValidFlags |= FrmValidFlags::Left | FrmValidFlags::Right | FrmValidFlags::Top | FrmValidFlags::Bottom; break; // OUTER // Inner Table: case 9: // HOR pTop = pBottom = &theDefLine; aBorderInner.SetLine( &theDefLine, SvxBoxInfoItemLine::HORI ); aBorderInner.SetLine( nullptr, SvxBoxInfoItemLine::VERT ); nValidFlags |= FrmValidFlags::HInner|FrmValidFlags::Top|FrmValidFlags::Bottom; break; case 10: // HORINNER pLeft = pRight = pTop = pBottom = &theDefLine; aBorderInner.SetLine( &theDefLine, SvxBoxInfoItemLine::HORI ); aBorderInner.SetLine( nullptr, SvxBoxInfoItemLine::VERT ); nValidFlags |= FrmValidFlags::Right|FrmValidFlags::Left|FrmValidFlags::HInner|FrmValidFlags::Top|FrmValidFlags::Bottom; break; case 11: // VERINNER pLeft = pRight = pTop = pBottom = &theDefLine; aBorderInner.SetLine( nullptr, SvxBoxInfoItemLine::HORI ); aBorderInner.SetLine( &theDefLine, SvxBoxInfoItemLine::VERT ); nValidFlags |= FrmValidFlags::Right|FrmValidFlags::Left|FrmValidFlags::VInner|FrmValidFlags::Top|FrmValidFlags::Bottom; break; case 12: // ALL pLeft = pRight = pTop = pBottom = &theDefLine; aBorderInner.SetLine( &theDefLine, SvxBoxInfoItemLine::HORI ); aBorderInner.SetLine( &theDefLine, SvxBoxInfoItemLine::VERT ); nValidFlags |= FrmValidFlags::AllMask; break; default: break; } aBorderOuter.SetLine( pLeft, SvxBoxItemLine::LEFT ); aBorderOuter.SetLine( pRight, SvxBoxItemLine::RIGHT ); aBorderOuter.SetLine( pTop, SvxBoxItemLine::TOP ); aBorderOuter.SetLine( pBottom, SvxBoxItemLine::BOTTOM ); if(nModifier == KEY_SHIFT) nValidFlags |= FrmValidFlags::AllMask; aBorderInner.SetValid( SvxBoxInfoItemValidFlags::TOP, bool(nValidFlags&FrmValidFlags::Top )); aBorderInner.SetValid( SvxBoxInfoItemValidFlags::BOTTOM, bool(nValidFlags&FrmValidFlags::Bottom )); aBorderInner.SetValid( SvxBoxInfoItemValidFlags::LEFT, bool(nValidFlags&FrmValidFlags::Left)); aBorderInner.SetValid( SvxBoxInfoItemValidFlags::RIGHT, bool(nValidFlags&FrmValidFlags::Right )); aBorderInner.SetValid( SvxBoxInfoItemValidFlags::HORI, bool(nValidFlags&FrmValidFlags::HInner )); aBorderInner.SetValid( SvxBoxInfoItemValidFlags::VERT, bool(nValidFlags&FrmValidFlags::VInner)); aBorderInner.SetValid( SvxBoxInfoItemValidFlags::DISTANCE ); aBorderInner.SetValid( SvxBoxInfoItemValidFlags::DISABLE, false ); if ( IsInPopupMode() ) EndPopupMode(); Any a; Sequence< PropertyValue > aArgs( 2 ); aArgs[0].Name = "OuterBorder"; aBorderOuter.QueryValue( a ); aArgs[0].Value = a; aArgs[1].Name = "InnerBorder"; aBorderInner.QueryValue( a ); aArgs[1].Value = a; if (aFrameSet) { /* #i33380# Moved the following line above the Dispatch() call. This instance may be deleted in the meantime (i.e. when a dialog is opened while in Dispatch()), accessing members will crash in this case. */ aFrameSet->SetNoSelection(); } mrController.dispatchCommand( ".uno:SetBorderStyle", aArgs ); } void SvxFrameWindow_Impl::statusChanged( const css::frame::FeatureStateEvent& rEvent ) { if ( rEvent.FeatureURL.Complete == ".uno:BorderReducedMode" ) { bool bValue; if ( rEvent.State >>= bValue ) { bParagraphMode = bValue; //initial calls mustn't insert or remove elements if(aFrameSet->GetItemCount()) { bool bTableMode = ( aFrameSet->GetItemCount() == 12 ); bool bResize = false; if ( bTableMode && bParagraphMode ) { for ( sal_uInt16 i = 9; i < 13; i++ ) aFrameSet->RemoveItem(i); bResize = true; } else if ( !bTableMode && !bParagraphMode ) { for ( sal_uInt16 i = 9; i < 13; i++ ) aFrameSet->InsertItem(i, Image(aImgVec[i-1])); bResize = true; } if ( bResize ) { CalcSizeValueSet(); } } } } } void SvxFrameWindow_Impl::CalcSizeValueSet() { Size aItemSize( 20 * GetParent()->GetDPIScaleFactor(), 20 * GetParent()->GetDPIScaleFactor() ); Size aSize = aFrameSet->CalcWindowSizePixel( aItemSize ); aFrameSet->SetPosSizePixel( Point( 2, 2 ), aSize ); aSize.AdjustWidth(4 ); aSize.AdjustHeight(4 ); SetOutputSizePixel( aSize ); } void SvxFrameWindow_Impl::InitImageList() { aImgVec.clear(); aImgVec.emplace_back(RID_SVXBMP_FRAME1); aImgVec.emplace_back(RID_SVXBMP_FRAME2); aImgVec.emplace_back(RID_SVXBMP_FRAME3); aImgVec.emplace_back(RID_SVXBMP_FRAME4); aImgVec.emplace_back(RID_SVXBMP_FRAME5); aImgVec.emplace_back(RID_SVXBMP_FRAME6); aImgVec.emplace_back(RID_SVXBMP_FRAME7); aImgVec.emplace_back(RID_SVXBMP_FRAME8); aImgVec.emplace_back(RID_SVXBMP_FRAME9); aImgVec.emplace_back(RID_SVXBMP_FRAME10); aImgVec.emplace_back(RID_SVXBMP_FRAME11); aImgVec.emplace_back(RID_SVXBMP_FRAME12); } static Color lcl_mediumColor( Color aMain, Color /*aDefault*/ ) { return SvxBorderLine::threeDMediumColor( aMain ); } SvxCurrencyList_Impl::SvxCurrencyList_Impl( SvxCurrencyToolBoxControl* pControl, vcl::Window* pParentWindow, OUString& rSelectedFormat, LanguageType& eSelectedLanguage ) : ToolbarPopup( pControl->getFrameInterface(), pParentWindow, WB_STDPOPUP | WB_MOVEABLE | WB_CLOSEABLE ), m_pCurrencyLb( VclPtr::Create(this) ), m_xControl( pControl ), m_rSelectedFormat( rSelectedFormat ), m_eSelectedLanguage( eSelectedLanguage ) { m_pCurrencyLb->setPosSizePixel( 2, 2, 300, 140 ); SetOutputSizePixel( Size( 304, 144 ) ); std::vector< OUString > aList; std::vector< sal_uInt16 > aCurrencyList; const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable(); sal_uInt16 nLen = rCurrencyTable.size(); SvNumberFormatter aFormatter( m_xControl->getContext(), LANGUAGE_SYSTEM ); m_eFormatLanguage = aFormatter.GetLanguage(); SvxCurrencyToolBoxControl::GetCurrencySymbols( aList, true, aCurrencyList ); sal_uInt16 nPos = 0, nCount = 0; sal_Int32 nSelectedPos = -1; bool bIsSymbol; NfWSStringsDtor aStringsDtor; for( const auto& rItem : aList ) { sal_uInt16& rCurrencyIndex = aCurrencyList[ nCount ]; if ( rCurrencyIndex < nLen ) { m_pCurrencyLb->InsertEntry( rItem ); const NfCurrencyEntry& aCurrencyEntry = rCurrencyTable[ rCurrencyIndex ]; bIsSymbol = nPos >= nLen; sal_uInt16 nDefaultFormat = aFormatter.GetCurrencyFormatStrings( aStringsDtor, aCurrencyEntry, bIsSymbol ); const OUString& rFormatStr = aStringsDtor[ nDefaultFormat ]; m_aFormatEntries.push_back( rFormatStr ); if( rFormatStr == m_rSelectedFormat ) nSelectedPos = nPos; ++nPos; } ++nCount; } m_pCurrencyLb->SetSelectHdl( LINK( this, SvxCurrencyList_Impl, SelectHdl ) ); SetText( SvxResId( RID_SVXSTR_TBLAFMT_CURRENCY ) ); if ( nSelectedPos >= 0 ) m_pCurrencyLb->SelectEntryPos( nSelectedPos ); m_pCurrencyLb->Show(); } void SvxCurrencyList_Impl::dispose() { m_xControl.clear(); m_pCurrencyLb.disposeAndClear(); ToolbarPopup::dispose(); } SvxLineWindow_Impl::SvxLineWindow_Impl( svt::ToolboxController& rController, vcl::Window* pParentWindow ) : ToolbarPopup( rController.getFrameInterface(), pParentWindow, WB_STDPOPUP | WB_MOVEABLE | WB_CLOSEABLE ), m_aLineStyleLb( VclPtr::Create(this) ), m_rController( rController ) { try { Reference< lang::XServiceInfo > xServices( rController.getFrameInterface()->getController()->getModel(), UNO_QUERY_THROW ); m_bIsWriter = xServices->supportsService("com.sun.star.text.TextDocument"); } catch(const uno::Exception& ) { } m_aLineStyleLb->setPosSizePixel( 2, 2, 110, 140 ); SetOutputSizePixel( Size( 114, 144 ) ); m_aLineStyleLb->SetSourceUnit( FieldUnit::TWIP ); m_aLineStyleLb->SetNone( SvxResId(RID_SVXSTR_NONE) ); m_aLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::SOLID ), SvxBorderLineStyle::SOLID ); m_aLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::DOTTED ), SvxBorderLineStyle::DOTTED ); m_aLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::DASHED ), SvxBorderLineStyle::DASHED ); // Double lines m_aLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::DOUBLE ), SvxBorderLineStyle::DOUBLE ); m_aLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::THINTHICK_SMALLGAP ), SvxBorderLineStyle::THINTHICK_SMALLGAP, 20 ); m_aLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::THINTHICK_MEDIUMGAP ), SvxBorderLineStyle::THINTHICK_MEDIUMGAP ); m_aLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::THINTHICK_LARGEGAP ), SvxBorderLineStyle::THINTHICK_LARGEGAP ); m_aLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::THICKTHIN_SMALLGAP ), SvxBorderLineStyle::THICKTHIN_SMALLGAP, 20 ); m_aLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::THICKTHIN_MEDIUMGAP ), SvxBorderLineStyle::THICKTHIN_MEDIUMGAP ); m_aLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::THICKTHIN_LARGEGAP ), SvxBorderLineStyle::THICKTHIN_LARGEGAP ); // Engraved / Embossed m_aLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::EMBOSSED ), SvxBorderLineStyle::EMBOSSED, 15, &SvxBorderLine::threeDLightColor, &SvxBorderLine::threeDDarkColor, &lcl_mediumColor ); m_aLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::ENGRAVED ), SvxBorderLineStyle::ENGRAVED, 15, &SvxBorderLine::threeDDarkColor, &SvxBorderLine::threeDLightColor, &lcl_mediumColor ); // Inset / Outset m_aLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::OUTSET ), SvxBorderLineStyle::OUTSET, 10, &SvxBorderLine::lightColor, &SvxBorderLine::darkColor ); m_aLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::INSET ), SvxBorderLineStyle::INSET, 10, &SvxBorderLine::darkColor, &SvxBorderLine::lightColor ); m_aLineStyleLb->SetWidth( 20 ); // 1pt by default m_aLineStyleLb->SetSelectHdl( LINK( this, SvxLineWindow_Impl, SelectHdl ) ); SetHelpId( HID_POPUP_LINE ); SetText( SvxResId(RID_SVXSTR_FRAME_STYLE) ); m_aLineStyleLb->Show(); } IMPL_LINK_NOARG(SvxCurrencyList_Impl, SelectHdl, ListBox&, void) { VclPtr xThis(this); if ( IsInPopupMode() ) EndPopupMode(); if (!m_xControl.is()) return; m_rSelectedFormat = m_aFormatEntries[ m_pCurrencyLb->GetSelectedEntryPos() ]; m_eSelectedLanguage = m_eFormatLanguage; m_xControl->execute( m_pCurrencyLb->GetSelectedEntryPos() + 1 ); } IMPL_LINK_NOARG(SvxLineWindow_Impl, SelectHdl, ListBox&, void) { VclPtr xThis(this); SvxLineItem aLineItem( SID_FRAME_LINESTYLE ); SvxBorderLineStyle nStyle = m_aLineStyleLb->GetSelectEntryStyle(); if ( m_aLineStyleLb->GetSelectedEntryPos( ) > 0 ) { SvxBorderLine aTmp; aTmp.SetBorderLineStyle( nStyle ); aTmp.SetWidth( 20 ); // TODO Make it depend on a width field aLineItem.SetLine( &aTmp ); } else aLineItem.SetLine( nullptr ); if ( IsInPopupMode() ) EndPopupMode(); Any a; Sequence< PropertyValue > aArgs( 1 ); aArgs[0].Name = "LineStyle"; aLineItem.QueryValue( a, m_bIsWriter ? CONVERT_TWIPS : 0 ); aArgs[0].Value = a; m_rController.dispatchCommand( ".uno:LineStyle", aArgs ); } void SvxLineWindow_Impl::Resize() { m_aLineStyleLb->Resize(); } void SvxLineWindow_Impl::GetFocus() { if ( m_aLineStyleLb ) m_aLineStyleLb->GrabFocus(); } SfxStyleControllerItem_Impl::SfxStyleControllerItem_Impl( const Reference< XDispatchProvider >& rDispatchProvider, sal_uInt16 nSlotId, // Family-ID const OUString& rCommand, // .uno: command bound to this item SvxStyleToolBoxControl& rTbxCtl ) // controller instance, which the item is assigned to. : SfxStatusListener( rDispatchProvider, nSlotId, rCommand ), rControl( rTbxCtl ) { } void SfxStyleControllerItem_Impl::StateChanged( SfxItemState eState, const SfxPoolItem* pState ) { switch ( GetId() ) { case SID_STYLE_FAMILY1: case SID_STYLE_FAMILY2: case SID_STYLE_FAMILY3: case SID_STYLE_FAMILY4: case SID_STYLE_FAMILY5: { const sal_uInt16 nIdx = GetId() - SID_STYLE_FAMILY_START; if ( SfxItemState::DEFAULT == eState ) { const SfxTemplateItem* pStateItem = dynamic_cast( pState ); DBG_ASSERT( pStateItem != nullptr, "SfxTemplateItem expected" ); rControl.SetFamilyState( nIdx, pStateItem ); } else rControl.SetFamilyState( nIdx, nullptr ); break; } } } struct SvxStyleToolBoxControl::Impl { OUString aClearForm; OUString aMore; ::std::vector< OUString > aDefaultStyles; bool bSpecModeWriter; bool bSpecModeCalc; Impl() :aClearForm ( SvxResId( RID_SVXSTR_CLEARFORM ) ) ,aMore ( SvxResId( RID_SVXSTR_MORE_STYLES ) ) ,bSpecModeWriter ( false ) ,bSpecModeCalc ( false ) { } void InitializeStyles(const Reference < frame::XModel >& xModel) { //now convert the default style names to the localized names try { Reference< style::XStyleFamiliesSupplier > xStylesSupplier( xModel, UNO_QUERY_THROW ); Reference< lang::XServiceInfo > xServices( xModel, UNO_QUERY_THROW ); bSpecModeWriter = xServices->supportsService("com.sun.star.text.TextDocument"); if(bSpecModeWriter) { Reference xParaStyles; xStylesSupplier->getStyleFamilies()->getByName("ParagraphStyles") >>= xParaStyles; static const std::vector aWriterStyles = { "Standard", "Text body", "Title", "Subtitle", "Heading 1", "Heading 2", "Heading 3", "Quotations" }; for( const OUString& aStyle: aWriterStyles ) { try { Reference< beans::XPropertySet > xStyle; xParaStyles->getByName( aStyle ) >>= xStyle; OUString sName; xStyle->getPropertyValue("DisplayName") >>= sName; if( !sName.isEmpty() ) aDefaultStyles.push_back(sName); } catch( const uno::Exception& ) {} } } else if( ( bSpecModeCalc = xServices->supportsService( "com.sun.star.sheet.SpreadsheetDocument"))) { static const sal_Char* aCalcStyles[] = { "Default", "Heading1", "Result", "Result2" }; Reference xCellStyles; xStylesSupplier->getStyleFamilies()->getByName("CellStyles") >>= xCellStyles; for(const char* pCalcStyle : aCalcStyles) { try { const OUString sStyleName( OUString::createFromAscii( pCalcStyle ) ); if( xCellStyles->hasByName( sStyleName ) ) { Reference< beans::XPropertySet > xStyle( xCellStyles->getByName( sStyleName), UNO_QUERY_THROW ); OUString sName; xStyle->getPropertyValue("DisplayName") >>= sName; if( !sName.isEmpty() ) aDefaultStyles.push_back(sName); } } catch( const uno::Exception& ) {} } } } catch(const uno::Exception& ) { OSL_FAIL("error while initializing style names"); } } }; // mapping table from bound items. BE CAREFUL this table must be in the // same order as the uno commands bound to the slots SID_STYLE_FAMILY1..n // MAX_FAMILIES must also be correctly set! static const char* StyleSlotToStyleCommand[MAX_FAMILIES] = { ".uno:CharStyle", ".uno:ParaStyle", ".uno:FrameStyle", ".uno:PageStyle", ".uno:TemplateFamily5" }; SvxStyleToolBoxControl::SvxStyleToolBoxControl( sal_uInt16 nSlotId, sal_uInt16 nId, ToolBox& rTbx ) : SfxToolBoxControl ( nSlotId, nId, rTbx ), pImpl ( new Impl ), pStyleSheetPool ( nullptr ), nActFamily ( 0xffff ) { for ( sal_uInt16 i=0; i& aArguments ) { SfxToolBoxControl::initialize( aArguments ); // After initialize we should have a valid frame member where we can retrieve our // dispatch provider. if ( m_xFrame.is() ) { pImpl->InitializeStyles(m_xFrame->getController()->getModel()); Reference< XDispatchProvider > xDispatchProvider( m_xFrame->getController(), UNO_QUERY ); for ( sal_uInt16 i=0; i( pBoundItems[i] ), UNO_QUERY ); pFamilyState[i] = nullptr; } } } // XComponent void SAL_CALL SvxStyleToolBoxControl::dispose() { SfxToolBoxControl::dispose(); for( sal_uInt16 i=0; idispose(); } catch ( Exception& ) { } m_xBoundItems[i].clear(); pBoundItems[i] = nullptr; } pFamilyState[i].reset(); } pStyleSheetPool = nullptr; pImpl.reset(); } void SAL_CALL SvxStyleToolBoxControl::update() { // Do nothing, we will start binding our listener when we are visible. // See link SvxStyleToolBoxControl::VisibilityNotification. SvxStyleBox_Impl* pBox = static_cast(GetToolBox().GetItemWindow( GetId() )); if ( pBox->IsVisible() ) { for (SfxStyleControllerItem_Impl* pBoundItem : pBoundItems) pBoundItem->ReBind(); bindListener(); } } SfxStyleFamily SvxStyleToolBoxControl::GetActFamily() const { switch ( nActFamily-1 + SID_STYLE_FAMILY_START ) { case SID_STYLE_FAMILY1: return SfxStyleFamily::Char; case SID_STYLE_FAMILY2: return SfxStyleFamily::Para; case SID_STYLE_FAMILY3: return SfxStyleFamily::Frame; case SID_STYLE_FAMILY4: return SfxStyleFamily::Page; case SID_STYLE_FAMILY5: return SfxStyleFamily::Pseudo; default: OSL_FAIL( "unknown style family" ); break; } return SfxStyleFamily::Para; } void SvxStyleToolBoxControl::FillStyleBox() { SvxStyleBox_Impl* pBox = static_cast(GetToolBox().GetItemWindow( GetId() )); DBG_ASSERT( pStyleSheetPool, "StyleSheetPool not found!" ); DBG_ASSERT( pBox, "Control not found!" ); if ( pStyleSheetPool && pBox && nActFamily!=0xffff ) { const SfxStyleFamily eFamily = GetActFamily(); sal_uInt16 nCount = pStyleSheetPool->Count(); SfxStyleSheetBase* pStyle = nullptr; bool bDoFill = false; pStyleSheetPool->SetSearchMask( eFamily, SfxStyleSearchBits::Used ); // Check whether fill is necessary pStyle = pStyleSheetPool->First(); //!!! TODO: This condition isn't right any longer, because we always show some default entries //!!! so the list doesn't show the count if ( nCount != pBox->GetEntryCount() ) { bDoFill = true; } else { sal_uInt16 i= 0; while ( pStyle && !bDoFill ) { bDoFill = ( pBox->GetEntry(i) != pStyle->GetName() ); pStyle = pStyleSheetPool->Next(); i++; } } if ( bDoFill ) { pBox->SetUpdateMode( false ); pBox->Clear(); { pStyle = pStyleSheetPool->Next(); if( pImpl->bSpecModeWriter || pImpl->bSpecModeCalc ) { while ( pStyle ) { // sort out default styles bool bInsert = true; OUString aName( pStyle->GetName() ); for( auto const & _i: pImpl->aDefaultStyles ) { if( _i == aName ) { bInsert = false; break; } } if( bInsert ) pBox->InsertEntry( aName ); pStyle = pStyleSheetPool->Next(); } } else { while ( pStyle ) { pBox->InsertEntry( pStyle->GetName() ); pStyle = pStyleSheetPool->Next(); } } } if( pImpl->bSpecModeWriter || pImpl->bSpecModeCalc ) { // disable sort to preserve special order WinBits nWinBits = pBox->GetStyle(); nWinBits &= ~WB_SORT; pBox->SetStyle( nWinBits ); // insert default styles sal_uInt16 nPos = 1; for( auto const & _i: pImpl->aDefaultStyles ) { pBox->InsertEntry( _i, nPos ); ++nPos; } pBox->InsertEntry( pImpl->aClearForm, 0 ); pBox->SetSeparatorPos( 0 ); pBox->InsertEntry( pImpl->aMore ); // enable sort again nWinBits |= WB_SORT; pBox->SetStyle( nWinBits ); } pBox->SetUpdateMode( true ); pBox->SetFamily( eFamily ); sal_uInt16 nLines = static_cast( std::min( pBox->GetEntryCount(), static_cast(MAX_STYLES_ENTRIES))); pBox->SetDropDownLineCount( nLines ); } } } void SvxStyleToolBoxControl::SelectStyle( const OUString& rStyleName ) { SvxStyleBox_Impl* pBox = static_cast(GetToolBox().GetItemWindow( GetId() )); DBG_ASSERT( pBox, "Control not found!" ); if ( pBox ) { OUString aStrSel( pBox->GetText() ); if ( !rStyleName.isEmpty() ) { if ( rStyleName != aStrSel ) pBox->SetText( rStyleName ); } else pBox->SetNoSelection(); pBox->SaveValue(); } } void SvxStyleToolBoxControl::Update() { SfxStyleSheetBasePool* pPool = nullptr; SfxObjectShell* pDocShell = SfxObjectShell::Current(); if ( pDocShell ) pPool = pDocShell->GetStyleSheetPool(); sal_uInt16 i; for ( i=0; iGetStyleName() ); } void SvxStyleToolBoxControl::SetFamilyState( sal_uInt16 nIdx, const SfxTemplateItem* pItem ) { pFamilyState[nIdx].reset( pItem == nullptr ? nullptr : new SfxTemplateItem( *pItem ) ); Update(); } IMPL_LINK_NOARG(SvxStyleToolBoxControl, VisibilityNotification, SvxStyleBox_Impl&, void) { // Call ReBind() && UnBind() according to visibility SvxStyleBox_Impl* pBox = static_cast( GetToolBox().GetItemWindow( GetId() )); if ( pBox && pBox->IsVisible() && !isBound() ) { for (SfxStyleControllerItem_Impl* pBoundItem : pBoundItems) pBoundItem->ReBind(); bindListener(); } else if ( (!pBox || !pBox->IsVisible()) && isBound() ) { for (SfxStyleControllerItem_Impl* pBoundItem : pBoundItems) pBoundItem->UnBind(); unbindListener(); } } void SvxStyleToolBoxControl::StateChanged( sal_uInt16 , SfxItemState eState, const SfxPoolItem* pState ) { sal_uInt16 nId = GetId(); ToolBox& rTbx = GetToolBox(); SvxStyleBox_Impl* pBox = static_cast(rTbx.GetItemWindow( nId )); TriState eTri = TRISTATE_FALSE; DBG_ASSERT( pBox, "Control not found!" ); if ( SfxItemState::DISABLED == eState ) pBox->Disable(); else pBox->Enable(); rTbx.EnableItem( nId, SfxItemState::DISABLED != eState ); switch ( eState ) { case SfxItemState::DEFAULT: eTri = static_cast(pState)->GetValue() != SfxStyleSearchBits::Auto ? TRISTATE_TRUE : TRISTATE_FALSE; break; case SfxItemState::DONTCARE: eTri = TRISTATE_INDET; break; default: break; } rTbx.SetItemState( nId, eTri ); if ( SfxItemState::DISABLED != eState ) Update(); } VclPtr SvxStyleToolBoxControl::CreateItemWindow( vcl::Window *pParent ) { VclPtrInstance pBox( pParent, OUString( ".uno:StyleApply" ), SfxStyleFamily::Para, Reference< XDispatchProvider >( m_xFrame->getController(), UNO_QUERY ), m_xFrame, pImpl->aClearForm, pImpl->aMore, pImpl->bSpecModeWriter || pImpl->bSpecModeCalc ); if( !pImpl->aDefaultStyles.empty()) pBox->SetDefaultStyle( pImpl->aDefaultStyles[0] ); // Set visibility listener to bind/unbind controller pBox->SetVisibilityListener( LINK( this, SvxStyleToolBoxControl, VisibilityNotification )); return pBox.get(); } class SvxFontNameToolBoxControl : public cppu::ImplInheritanceHelper< svt::ToolboxController, css::lang::XServiceInfo > { public: SvxFontNameToolBoxControl(); // XStatusListener virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& rEvent ) override; // XToolbarController virtual css::uno::Reference< css::awt::XWindow > SAL_CALL createItemWindow( const css::uno::Reference< css::awt::XWindow >& rParent ) override; // XComponent virtual void SAL_CALL dispose() override; // XServiceInfo virtual OUString SAL_CALL getImplementationName() override; virtual sal_Bool SAL_CALL supportsService( const OUString& rServiceName ) override; virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; private: VclPtr m_pBox; }; SvxFontNameToolBoxControl::SvxFontNameToolBoxControl() { } void SvxFontNameToolBoxControl::statusChanged( const css::frame::FeatureStateEvent& rEvent ) { SolarMutexGuard aGuard; ToolBox* pToolBox = nullptr; sal_uInt16 nId = 0; if ( !getToolboxId( nId, &pToolBox ) ) return; if ( !rEvent.IsEnabled ) { m_pBox->Disable(); m_pBox->Update( nullptr ); } else { m_pBox->Enable(); css::awt::FontDescriptor aFontDesc; if ( rEvent.State >>= aFontDesc ) m_pBox->Update( &aFontDesc ); else m_pBox->SetText( "" ); m_pBox->SaveValue(); } pToolBox->EnableItem( nId, rEvent.IsEnabled ); } css::uno::Reference< css::awt::XWindow > SvxFontNameToolBoxControl::createItemWindow( const css::uno::Reference< css::awt::XWindow >& rParent ) { SolarMutexGuard aGuard; m_pBox = VclPtr::Create( VCLUnoHelper::GetWindow( rParent ), Reference< XDispatchProvider >( m_xFrame->getController(), UNO_QUERY ), m_xFrame, 0); return VCLUnoHelper::GetInterface( m_pBox ); } void SvxFontNameToolBoxControl::dispose() { m_pBox.disposeAndClear(); ToolboxController::dispose(); } OUString SvxFontNameToolBoxControl::getImplementationName() { return "com.sun.star.comp.svx.FontNameToolBoxControl"; } sal_Bool SvxFontNameToolBoxControl::supportsService( const OUString& rServiceName ) { return cppu::supportsService( this, rServiceName ); } css::uno::Sequence< OUString > SvxFontNameToolBoxControl::getSupportedServiceNames() { return { "com.sun.star.frame.ToolbarController" }; } extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_svx_FontNameToolBoxControl_get_implementation( css::uno::XComponentContext*, css::uno::Sequence const & ) { return cppu::acquire( new SvxFontNameToolBoxControl() ); } SvxColorToolBoxControl::SvxColorToolBoxControl( const css::uno::Reference& rContext ) : ImplInheritanceHelper( rContext, nullptr, OUString() ), m_bSplitButton(true), m_nSlotId(0), m_aColorSelectFunction(PaletteManager::DispatchColorCommand) { } namespace { sal_uInt16 MapCommandToSlotId(const OUString& rCommand) { if (rCommand == ".uno:Color") return SID_ATTR_CHAR_COLOR; else if (rCommand == ".uno:FontColor") return SID_ATTR_CHAR_COLOR2; else if (rCommand == ".uno:BackColor") return SID_ATTR_CHAR_COLOR_BACKGROUND; else if (rCommand == ".uno:CharBackColor") return SID_ATTR_CHAR_BACK_COLOR; else if (rCommand == ".uno:BackgroundColor") return SID_BACKGROUND_COLOR; else if (rCommand == ".uno:TableCellBackgroundColor") return SID_TABLE_CELL_BACKGROUND_COLOR; else if (rCommand == ".uno:Extrusion3DColor") return SID_EXTRUSION_3D_COLOR; else if (rCommand == ".uno:XLineColor") return SID_ATTR_LINE_COLOR; else if (rCommand == ".uno:FillColor") return SID_ATTR_FILL_COLOR; else if (rCommand == ".uno:FrameLineColor") return SID_FRAME_LINECOLOR; SAL_WARN("svx.tbxcrtls", "Unknown color command: " << rCommand); return 0; } } void SvxColorToolBoxControl::initialize( const css::uno::Sequence& rArguments ) { PopupWindowController::initialize( rArguments ); ToolBox* pToolBox = nullptr; sal_uInt16 nId = 0; if ( !getToolboxId( nId, &pToolBox ) ) { SAL_WARN("svx.tbxcrtls", "ToolBox not found!"); return; } m_nSlotId = MapCommandToSlotId( m_aCommandURL ); if ( m_nSlotId == SID_ATTR_LINE_COLOR || m_nSlotId == SID_ATTR_FILL_COLOR || m_nSlotId == SID_FRAME_LINECOLOR || m_nSlotId == SID_BACKGROUND_COLOR ) // Sidebar uses wide buttons for those. m_bSplitButton = typeid( *pToolBox ) != typeid( sfx2::sidebar::SidebarToolBox ); OUString aCommandLabel = vcl::CommandInfoProvider::GetLabelForCommand( getCommandURL(), getModuleName() ); m_xBtnUpdater.reset( new svx::ToolboxButtonColorUpdater( m_nSlotId, nId, pToolBox, !m_bSplitButton, aCommandLabel ) ); pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | ( m_bSplitButton ? ToolBoxItemBits::DROPDOWN : ToolBoxItemBits::DROPDOWNONLY ) ); } void SvxColorToolBoxControl::update() { PopupWindowController::update(); switch( m_nSlotId ) { case SID_ATTR_CHAR_COLOR2: addStatusListener( ".uno:CharColorExt"); break; case SID_ATTR_CHAR_COLOR_BACKGROUND: addStatusListener( ".uno:CharBackgroundExt"); break; case SID_FRAME_LINECOLOR: addStatusListener( ".uno:BorderTLBR"); addStatusListener( ".uno:BorderBLTR"); break; } } void SvxColorToolBoxControl::EnsurePaletteManager() { if (!m_xPaletteManager) { m_xPaletteManager.reset(new PaletteManager); m_xPaletteManager->SetBtnUpdater(m_xBtnUpdater.get()); } } SvxColorToolBoxControl::~SvxColorToolBoxControl() { if (m_xPaletteManager) m_xPaletteManager->SetBtnUpdater(nullptr); } void SvxColorToolBoxControl::setColorSelectFunction(const ColorSelectFunction& aColorSelectFunction) { m_aColorSelectFunction = aColorSelectFunction; if (m_xPaletteManager) m_xPaletteManager->SetColorSelectFunction(aColorSelectFunction); } VclPtr SvxColorToolBoxControl::createPopupWindow( vcl::Window* pParent ) { EnsurePaletteManager(); VclPtrInstance pColorWin( m_aCommandURL, m_xPaletteManager, m_aColorStatus, m_nSlotId, m_xFrame, pParent, false, m_aColorSelectFunction); OUString aWindowTitle = vcl::CommandInfoProvider::GetLabelForCommand( m_aCommandURL, m_sModuleName ); pColorWin->SetText( aWindowTitle ); pColorWin->StartSelection(); if ( m_bSplitButton ) pColorWin->SetSelectedHdl( LINK( this, SvxColorToolBoxControl, SelectedHdl ) ); return pColorWin; } IMPL_LINK(SvxColorToolBoxControl, SelectedHdl, const NamedColor&, rColor, void) { m_xBtnUpdater->Update(rColor); } void SvxColorToolBoxControl::statusChanged( const css::frame::FeatureStateEvent& rEvent ) { ToolBox* pToolBox = nullptr; sal_uInt16 nId = 0; if ( !getToolboxId( nId, &pToolBox ) ) return; if ( rEvent.FeatureURL.Complete == m_aCommandURL ) pToolBox->EnableItem( nId, rEvent.IsEnabled ); bool bValue; if ( !m_bSplitButton ) { m_aColorStatus.statusChanged( rEvent ); m_xBtnUpdater->Update( m_aColorStatus.GetColor() ); } else if ( rEvent.State >>= bValue ) pToolBox->CheckItem( nId, bValue ); } void SvxColorToolBoxControl::execute(sal_Int16 /*nSelectModifier*/) { if ( !m_bSplitButton ) { // Open the popup also when Enter key is pressed. createPopupWindow(); return; } OUString aCommand = m_aCommandURL; Color aColor = m_xBtnUpdater->GetCurrentColor(); switch( m_nSlotId ) { case SID_ATTR_CHAR_COLOR2 : aCommand = ".uno:CharColorExt"; break; case SID_ATTR_CHAR_COLOR_BACKGROUND : aCommand = ".uno:CharBackgroundExt"; break; } auto aArgs( comphelper::InitPropertySequence( { { m_aCommandURL.copy(5), css::uno::makeAny(aColor) } } ) ); dispatchCommand( aCommand, aArgs ); EnsurePaletteManager(); OUString sColorName = m_xBtnUpdater->GetCurrentColorName(); m_xPaletteManager->AddRecentColor(aColor, sColorName); } sal_Bool SvxColorToolBoxControl::opensSubToolbar() { // For a split button, we mark this controller as a sub-toolbar controller, // so we get notified (through updateImage method) on button image changes, // and could redraw the last used color on top of it. return m_bSplitButton; } void SvxColorToolBoxControl::updateImage() { ToolBox* pToolBox = nullptr; sal_uInt16 nId = 0; if ( !getToolboxId( nId, &pToolBox ) ) return; Image aImage = vcl::CommandInfoProvider::GetImageForCommand(m_aCommandURL, m_xFrame, pToolBox->GetImageSize()); if ( !!aImage ) { pToolBox->SetItemImage( nId, aImage ); m_xBtnUpdater->Update(m_xBtnUpdater->GetCurrentColor(), true); } } OUString SvxColorToolBoxControl::getSubToolbarName() { return OUString(); } void SvxColorToolBoxControl::functionSelected( const OUString& /*rCommand*/ ) { } OUString SvxColorToolBoxControl::getImplementationName() { return "com.sun.star.comp.svx.ColorToolBoxControl"; } css::uno::Sequence SvxColorToolBoxControl::getSupportedServiceNames() { return { "com.sun.star.frame.ToolbarController" }; } extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_svx_ColorToolBoxControl_get_implementation( css::uno::XComponentContext* rContext, css::uno::Sequence const & ) { return cppu::acquire( new SvxColorToolBoxControl( rContext ) ); } // class SvxFrameToolBoxControl -------------------------------------------- class SvxFrameToolBoxControl : public svt::PopupWindowController { public: explicit SvxFrameToolBoxControl( const css::uno::Reference< css::uno::XComponentContext >& rContext ); // XInitialization virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& rArguments ) override; // XServiceInfo virtual OUString SAL_CALL getImplementationName() override; virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; private: virtual VclPtr createPopupWindow( vcl::Window* pParent ) override; using svt::ToolboxController::createPopupWindow; }; SvxFrameToolBoxControl::SvxFrameToolBoxControl( const css::uno::Reference< css::uno::XComponentContext >& rContext ) : svt::PopupWindowController( rContext, nullptr, OUString() ) { } void SvxFrameToolBoxControl::initialize( const css::uno::Sequence< css::uno::Any >& rArguments ) { svt::PopupWindowController::initialize( rArguments ); ToolBox* pToolBox = nullptr; sal_uInt16 nId = 0; if ( getToolboxId( nId, &pToolBox ) ) pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | ToolBoxItemBits::DROPDOWNONLY ); } VclPtr SvxFrameToolBoxControl::createPopupWindow( vcl::Window* pParent ) { if ( m_aCommandURL == ".uno:LineStyle" ) return VclPtr::Create( *this, pParent ); return VclPtr::Create( *this, pParent ); } OUString SvxFrameToolBoxControl::getImplementationName() { return "com.sun.star.comp.svx.FrameToolBoxControl"; } css::uno::Sequence< OUString > SvxFrameToolBoxControl::getSupportedServiceNames() { return { "com.sun.star.frame.ToolbarController" }; } extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_svx_FrameToolBoxControl_get_implementation( css::uno::XComponentContext* rContext, css::uno::Sequence const & ) { return cppu::acquire( new SvxFrameToolBoxControl( rContext ) ); } SvxSimpleUndoRedoController::SvxSimpleUndoRedoController( sal_uInt16 nSlotId, sal_uInt16 nId, ToolBox& rTbx ) :SfxToolBoxControl( nSlotId, nId, rTbx ) { aDefaultText = rTbx.GetItemText( nId ); } SvxSimpleUndoRedoController::~SvxSimpleUndoRedoController() { } void SvxSimpleUndoRedoController::StateChanged( sal_uInt16, SfxItemState eState, const SfxPoolItem* pState ) { const SfxStringItem* pItem = dynamic_cast( pState ); ToolBox& rBox = GetToolBox(); if ( pItem && eState != SfxItemState::DISABLED ) { OUString aNewText( MnemonicGenerator::EraseAllMnemonicChars( pItem->GetValue() ) ); rBox.SetQuickHelpText( GetId(), aNewText ); } if ( eState == SfxItemState::DISABLED ) rBox.SetQuickHelpText( GetId(), aDefaultText ); rBox.EnableItem( GetId(), eState != SfxItemState::DISABLED ); } SvxCurrencyToolBoxControl::SvxCurrencyToolBoxControl( const css::uno::Reference& rContext ) : PopupWindowController( rContext, nullptr, OUString() ), m_eLanguage( Application::GetSettings().GetLanguageTag().getLanguageType() ), m_nFormatKey( NUMBERFORMAT_ENTRY_NOT_FOUND ) { } SvxCurrencyToolBoxControl::~SvxCurrencyToolBoxControl() {} void SvxCurrencyToolBoxControl::initialize( const css::uno::Sequence< css::uno::Any >& rArguments ) { PopupWindowController::initialize(rArguments); ToolBox* pToolBox = nullptr; sal_uInt16 nId = 0; if (getToolboxId(nId, &pToolBox) && pToolBox->GetItemCommand(nId) == m_aCommandURL) pToolBox->SetItemBits(nId, ToolBoxItemBits::DROPDOWN | pToolBox->GetItemBits(nId)); } VclPtr SvxCurrencyToolBoxControl::createPopupWindow( vcl::Window* pParent ) { return VclPtr::Create(this, pParent, m_aFormatString, m_eLanguage); } void SvxCurrencyToolBoxControl::execute( sal_Int16 nSelectModifier ) { sal_uInt32 nFormatKey; if (m_aFormatString.isEmpty()) nFormatKey = NUMBERFORMAT_ENTRY_NOT_FOUND; else { if ( nSelectModifier > 0 ) { try { uno::Reference< util::XNumberFormatsSupplier > xRef( m_xFrame->getController()->getModel(), uno::UNO_QUERY ); uno::Reference< util::XNumberFormats > rxNumberFormats( xRef->getNumberFormats(), uno::UNO_SET_THROW ); css::lang::Locale aLocale = LanguageTag::convertToLocale( m_eLanguage ); nFormatKey = rxNumberFormats->queryKey( m_aFormatString, aLocale, false ); if ( nFormatKey == NUMBERFORMAT_ENTRY_NOT_FOUND ) nFormatKey = rxNumberFormats->addNew( m_aFormatString, aLocale ); } catch( const uno::Exception& ) { nFormatKey = m_nFormatKey; } } else nFormatKey = m_nFormatKey; } if( nFormatKey != NUMBERFORMAT_ENTRY_NOT_FOUND ) { Sequence< PropertyValue > aArgs( 1 ); aArgs[0].Name = "NumberFormatCurrency"; aArgs[0].Value <<= nFormatKey; dispatchCommand( m_aCommandURL, aArgs ); m_nFormatKey = nFormatKey; } else PopupWindowController::execute( nSelectModifier ); } OUString SvxCurrencyToolBoxControl::getImplementationName() { return "com.sun.star.comp.svx.CurrencyToolBoxControl"; } css::uno::Sequence SvxCurrencyToolBoxControl::getSupportedServiceNames() { return { "com.sun.star.frame.ToolbarController" }; } extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_svx_CurrencyToolBoxControl_get_implementation( css::uno::XComponentContext* rContext, css::uno::Sequence const & ) { return cppu::acquire( new SvxCurrencyToolBoxControl( rContext ) ); } Reference< css::accessibility::XAccessible > SvxFontNameBox_Impl::CreateAccessible() { FillList(); return FontNameBox::CreateAccessible(); } //static void SvxCurrencyToolBoxControl::GetCurrencySymbols( std::vector& rList, bool bFlag, std::vector& rCurrencyList ) { rCurrencyList.clear(); const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable(); sal_uInt16 nCount = rCurrencyTable.size(); sal_uInt16 nStart = 1; OUString aString( ApplyLreOrRleEmbedding( rCurrencyTable[0].GetSymbol() ) + " " ); aString += ApplyLreOrRleEmbedding( SvtLanguageTable::GetLanguageString( rCurrencyTable[0].GetLanguage() ) ); rList.push_back( aString ); rCurrencyList.push_back( sal_uInt16(-1) ); // nAuto if( bFlag ) { rList.push_back( aString ); rCurrencyList.push_back( 0 ); ++nStart; } CollatorWrapper aCollator( ::comphelper::getProcessComponentContext() ); aCollator.loadDefaultCollator( Application::GetSettings().GetLanguageTag().getLocale(), 0 ); const OUString aTwoSpace(" "); for( sal_uInt16 i = 1; i < nCount; ++i ) { OUString aStr( ApplyLreOrRleEmbedding( rCurrencyTable[i].GetBankSymbol() ) ); aStr += aTwoSpace; aStr += ApplyLreOrRleEmbedding( rCurrencyTable[i].GetSymbol() ); aStr += aTwoSpace; aStr += ApplyLreOrRleEmbedding( SvtLanguageTable::GetLanguageString( rCurrencyTable[i].GetLanguage() ) ); std::vector::size_type j = nStart; for( ; j < rList.size(); ++j ) if ( aCollator.compareString( aStr, rList[j] ) < 0 ) break; // insert before first greater than rList.insert( rList.begin() + j, aStr ); rCurrencyList.insert( rCurrencyList.begin() + j, i ); } // Append ISO codes to symbol list. // XXX If this is to be changed, various other places would had to be // adapted that assume this order! std::vector::size_type nCont = rList.size(); for ( sal_uInt16 i = 1; i < nCount; ++i ) { bool bInsert = true; OUString aStr( ApplyLreOrRleEmbedding( rCurrencyTable[i].GetBankSymbol() ) ); std::vector::size_type j = nCont; for ( ; j < rList.size() && bInsert; ++j ) { if( rList[j] == aStr ) bInsert = false; else if ( aCollator.compareString( aStr, rList[j] ) < 0 ) break; // insert before first greater than } if ( bInsert ) { rList.insert( rList.begin() + j, aStr ); rCurrencyList.insert( rCurrencyList.begin() + j, i ); } } } SvxListBoxColorWrapper::SvxListBoxColorWrapper(SvxColorListBox* pControl) : mxControl(pControl) { } void SvxListBoxColorWrapper::operator()(const OUString& /*rCommand*/, const NamedColor& rColor) { if (!mxControl) return; mxControl->Selected(rColor); } void SvxListBoxColorWrapper::dispose() { mxControl.clear(); } ListBoxColorWrapper::ListBoxColorWrapper(ColorListBox* pControl) : mpControl(pControl) { } void ListBoxColorWrapper::operator()(const OUString& /*rCommand*/, const NamedColor& rColor) { mpControl->Selected(rColor); } SvxColorListBox::SvxColorListBox(vcl::Window* pParent, WinBits nStyle) : MenuButton(pParent, nStyle) , m_aColorWrapper(this) , m_aAutoDisplayColor(Application::GetSettings().GetStyleSettings().GetDialogColor()) , m_nSlotId(0) { m_aSelectedColor = GetAutoColor(m_nSlotId); LockWidthRequest(); ShowPreview(m_aSelectedColor); SetActivateHdl(LINK(this, SvxColorListBox, MenuActivateHdl)); } void SvxColorListBox::EnsurePaletteManager() { if (!m_xPaletteManager) { m_xPaletteManager.reset(new PaletteManager); m_xPaletteManager->SetColorSelectFunction(std::ref(m_aColorWrapper)); } } void ColorListBox::EnsurePaletteManager() { if (!m_xPaletteManager) { m_xPaletteManager.reset(new PaletteManager); m_xPaletteManager->SetColorSelectFunction(std::ref(m_aColorWrapper)); } } void SvxColorListBox::SetSlotId(sal_uInt16 nSlotId) { m_nSlotId = nSlotId; m_xColorWindow.disposeAndClear(); m_aSelectedColor = GetAutoColor(m_nSlotId); ShowPreview(m_aSelectedColor); createColorWindow(); } void ColorListBox::SetSlotId(sal_uInt16 nSlotId, bool bShowNoneButton) { m_nSlotId = nSlotId; m_bShowNoneButton = bShowNoneButton; m_xButton->set_popover(nullptr); m_xColorWindow.reset(); m_aSelectedColor = bShowNoneButton ? GetNoneColor() : GetAutoColor(m_nSlotId); ShowPreview(m_aSelectedColor); createColorWindow(); } //to avoid the box resizing every time the color is changed to //the optimal size of the individual color, get the longest //standard color and stick with that as the size for all void SvxColorListBox::LockWidthRequest() { if (get_width_request() != -1) return; NamedColor aLongestColor; long nMaxStandardColorTextWidth = 0; XColorListRef const xColorTable = XColorList::CreateStdColorList(); for (long i = 0; i != xColorTable->Count(); ++i) { XColorEntry& rEntry = *xColorTable->GetColor(i); long nColorTextWidth = GetTextWidth(rEntry.GetName()); if (nColorTextWidth > nMaxStandardColorTextWidth) { nMaxStandardColorTextWidth = nColorTextWidth; aLongestColor.second = rEntry.GetName(); } } ShowPreview(aLongestColor); set_width_request(get_preferred_size().Width()); } void SvxColorListBox::ShowPreview(const NamedColor &rColor) { const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); Size aImageSize(rStyleSettings.GetListBoxPreviewDefaultPixelSize()); ScopedVclPtrInstance xDevice; xDevice->SetOutputSize(aImageSize); const tools::Rectangle aRect(Point(0, 0), aImageSize); if (rColor.first == COL_AUTO) xDevice->SetFillColor(m_aAutoDisplayColor); else xDevice->SetFillColor(rColor.first); xDevice->SetLineColor(rStyleSettings.GetDisableColor()); xDevice->DrawRect(aRect); BitmapEx aBitmap(xDevice->GetBitmapEx(Point(0, 0), xDevice->GetOutputSize())); SetImageAlign(ImageAlign::Left); SetModeImage(Image(aBitmap)); SetText(rColor.second); } IMPL_LINK(SvxColorListBox, WindowEventListener, VclWindowEvent&, rWindowEvent, void) { if (rWindowEvent.GetId() == VclEventId::WindowEndPopupMode) { m_xColorWindow.disposeAndClear(); SetPopover(nullptr); } } IMPL_LINK_NOARG(SvxColorListBox, MenuActivateHdl, MenuButton *, void) { if (!m_xColorWindow || m_xColorWindow->isDisposed()) createColorWindow(); } void SvxColorListBox::createColorWindow() { const SfxViewFrame* pViewFrame = SfxViewFrame::Current(); const SfxFrame* pFrame = pViewFrame ? &pViewFrame->GetFrame() : nullptr; css::uno::Reference xFrame(pFrame ? pFrame->GetFrameInterface() : uno::Reference()); EnsurePaletteManager(); m_xColorWindow = VclPtr::Create( OUString() /*m_aCommandURL*/, m_xPaletteManager, m_aColorStatus, m_nSlotId, xFrame, this, true, m_aColorWrapper); m_xColorWindow->AddEventListener(LINK(this, SvxColorListBox, WindowEventListener)); SetNoSelection(); m_xColorWindow->SelectEntry(m_aSelectedColor); SetPopover(m_xColorWindow); } void SvxColorListBox::Selected(const NamedColor& rColor) { ShowPreview(rColor); m_aSelectedColor = rColor; if (m_aSelectedLink.IsSet()) m_aSelectedLink.Call(*this); } VCL_BUILDER_FACTORY(SvxColorListBox) SvxColorListBox::~SvxColorListBox() { disposeOnce(); } void SvxColorListBox::dispose() { m_xColorWindow.disposeAndClear(); m_aColorWrapper.dispose(); MenuButton::dispose(); } VclPtr const & SvxColorListBox::getColorWindow() const { if (!m_xColorWindow || m_xColorWindow->isDisposed()) const_cast(this)->createColorWindow(); return m_xColorWindow; } void SvxColorListBox::SelectEntry(const NamedColor& rColor) { if (rColor.second.trim().isEmpty()) { SelectEntry(rColor.first); return; } VclPtr xColorWindow = getColorWindow(); xColorWindow->SelectEntry(rColor); m_aSelectedColor = xColorWindow->GetSelectEntryColor(); ShowPreview(m_aSelectedColor); } void SvxColorListBox::SelectEntry(const Color& rColor) { VclPtr xColorWindow = getColorWindow(); xColorWindow->SelectEntry(rColor); m_aSelectedColor = xColorWindow->GetSelectEntryColor(); ShowPreview(m_aSelectedColor); } ColorListBox::ColorListBox(std::unique_ptr pControl, weld::Window* pTopLevel) : m_xButton(std::move(pControl)) , m_pTopLevel(pTopLevel) , m_aColorWrapper(this) , m_aAutoDisplayColor(Application::GetSettings().GetStyleSettings().GetDialogColor()) , m_nSlotId(0) , m_bShowNoneButton(false) { m_aSelectedColor = GetAutoColor(m_nSlotId); LockWidthRequest(); ShowPreview(m_aSelectedColor); } ColorListBox::~ColorListBox() { } ColorWindow* ColorListBox::getColorWindow() const { if (!m_xColorWindow) const_cast(this)->createColorWindow(); return m_xColorWindow.get(); } void ColorListBox::createColorWindow() { const SfxViewFrame* pViewFrame = SfxViewFrame::Current(); const SfxFrame* pFrame = pViewFrame ? &pViewFrame->GetFrame() : nullptr; css::uno::Reference xFrame(pFrame ? pFrame->GetFrameInterface() : uno::Reference()); EnsurePaletteManager(); m_xColorWindow.reset(new ColorWindow( m_xPaletteManager, m_aColorStatus, m_nSlotId, xFrame, m_pTopLevel, m_xButton.get(), m_aColorWrapper)); SetNoSelection(); m_xButton->set_popover(m_xColorWindow->GetWidget()); if (m_bShowNoneButton) m_xColorWindow->ShowNoneButton(); m_xColorWindow->SelectEntry(m_aSelectedColor); } void ColorListBox::SelectEntry(const NamedColor& rColor) { if (rColor.second.trim().isEmpty()) { SelectEntry(rColor.first); return; } ColorWindow* pColorWindow = getColorWindow(); pColorWindow->SelectEntry(rColor); m_aSelectedColor = pColorWindow->GetSelectEntryColor(); ShowPreview(m_aSelectedColor); } void ColorListBox::SelectEntry(const Color& rColor) { ColorWindow* pColorWindow = getColorWindow(); pColorWindow->SelectEntry(rColor); m_aSelectedColor = pColorWindow->GetSelectEntryColor(); ShowPreview(m_aSelectedColor); } void ColorListBox::Selected(const NamedColor& rColor) { ShowPreview(rColor); m_aSelectedColor = rColor; if (m_aSelectedLink.IsSet()) m_aSelectedLink.Call(*this); } //to avoid the box resizing every time the color is changed to //the optimal size of the individual color, get the longest //standard color and stick with that as the size for all void ColorListBox::LockWidthRequest() { NamedColor aLongestColor; long nMaxStandardColorTextWidth = 0; XColorListRef const xColorTable = XColorList::CreateStdColorList(); for (long i = 0; i != xColorTable->Count(); ++i) { XColorEntry& rEntry = *xColorTable->GetColor(i); auto nColorTextWidth = m_xButton->get_pixel_size(rEntry.GetName()).Width(); if (nColorTextWidth > nMaxStandardColorTextWidth) { nMaxStandardColorTextWidth = nColorTextWidth; aLongestColor.second = rEntry.GetName(); } } ShowPreview(aLongestColor); m_xButton->set_size_request(m_xButton->get_preferred_size().Width(), -1); } void ColorListBox::ShowPreview(const NamedColor &rColor) { const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); Size aImageSize(rStyleSettings.GetListBoxPreviewDefaultPixelSize()); ScopedVclPtrInstance xDevice; xDevice->SetOutputSize(aImageSize); const tools::Rectangle aRect(Point(0, 0), aImageSize); if (m_bShowNoneButton && rColor.first == COL_NONE_COLOR) { const Color aW(COL_WHITE); const Color aG(0xef, 0xef, 0xef); xDevice->DrawCheckered(aRect.TopLeft(), aRect.GetSize(), 8, aW, aG); xDevice->SetFillColor(); } else { if (rColor.first == COL_AUTO) xDevice->SetFillColor(m_aAutoDisplayColor); else xDevice->SetFillColor(rColor.first); } xDevice->SetLineColor(rStyleSettings.GetDisableColor()); xDevice->DrawRect(aRect); m_xButton->set_image(xDevice.get()); m_xButton->set_label(rColor.second); } MenuOrToolMenuButton::MenuOrToolMenuButton(weld::MenuButton* pMenuButton) : m_pMenuButton(pMenuButton) , m_pToolbar(nullptr) { } MenuOrToolMenuButton::MenuOrToolMenuButton(weld::Toolbar* pToolbar, const OString& rIdent) : m_pMenuButton(nullptr) , m_pToolbar(pToolbar) , m_aIdent(rIdent) { } bool MenuOrToolMenuButton::get_active() const { if (m_pMenuButton) return m_pMenuButton->get_active(); return m_pToolbar->get_item_active(m_aIdent); } void MenuOrToolMenuButton::set_active(bool bActive) const { if (m_pMenuButton) { m_pMenuButton->set_active(bActive); return; } m_pToolbar->set_item_active(m_aIdent, bActive); } weld::Widget* MenuOrToolMenuButton::get_widget() const { if (m_pMenuButton) return m_pMenuButton; return m_pToolbar; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */