diff options
author | Caolán McNamara <caolanm@redhat.com> | 2020-01-21 15:43:46 +0000 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2020-01-22 17:55:28 +0100 |
commit | eae55d7397f953ca8a4be1a2665e8ca887adfe81 (patch) | |
tree | 47d84a1b81c3a4d7b4719b328cb1241ae80f1a2f /svx/source/tbxctrls/linectrl.cxx | |
parent | 2399373778cf0778ad15b1fec9a1bf289b4089de (diff) |
rework line style to be a wide toolbar button
involves converting SvxLineStyleToolBoxControl to a PopupWindowController
because chart is doing interesting things in its panel there needs to be
a non-standard way to report/detect the selected line style, which is
then reused to disable/enable the arrows when none is selected/deselected
in non-chart sidebars
SvxLineBox becomes a toolbar dropdown instead of a combobox itemwindow
linectrl.cxx split into linewidthctrl.cxx and linewidthctrl because
SvxLineBox is now needed in svxcore
Change-Id: Icf0ef5e612b894a43d389af8a2908138c2e9c580
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/87164
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'svx/source/tbxctrls/linectrl.cxx')
-rw-r--r-- | svx/source/tbxctrls/linectrl.cxx | 390 |
1 files changed, 249 insertions, 141 deletions
diff --git a/svx/source/tbxctrls/linectrl.cxx b/svx/source/tbxctrls/linectrl.cxx index 80c36beb55d5..31233a13e5ea 100644 --- a/svx/source/tbxctrls/linectrl.cxx +++ b/svx/source/tbxctrls/linectrl.cxx @@ -19,6 +19,8 @@ #include <string> +#include <vcl/settings.hxx> +#include <vcl/svapp.hxx> #include <vcl/toolbox.hxx> #include <sfx2/app.hxx> #include <sfx2/dispatch.hxx> @@ -42,6 +44,7 @@ #include <svx/linectrl.hxx> #include <svx/itemwin.hxx> #include <svx/dialmgr.hxx> +#include <svx/tbxcolorupdate.hxx> #include <svx/unoapi.hxx> #include <memory> @@ -55,198 +58,171 @@ using namespace ::com::sun::star; // For End Line Controller #define MAX_LINES 12 -SFX_IMPL_TOOLBOX_CONTROL( SvxLineStyleToolBoxControl, XLineStyleItem ); -SFX_IMPL_TOOLBOX_CONTROL( SvxLineWidthToolBoxControl, XLineWidthItem ); - -SvxLineStyleToolBoxControl::SvxLineStyleToolBoxControl( sal_uInt16 nSlotId, - sal_uInt16 nId, - ToolBox& rTbx ) : - SfxToolBoxControl( nSlotId, nId, rTbx ), - bUpdate ( false ) +SvxLineStyleToolBoxControl::SvxLineStyleToolBoxControl( const css::uno::Reference<css::uno::XComponentContext>& rContext ) + : svt::PopupWindowController( rContext, nullptr, OUString() ) { - addStatusListener( ".uno:LineDash"); - addStatusListener( ".uno:DashListState"); + addStatusListener(".uno:LineDash"); } - SvxLineStyleToolBoxControl::~SvxLineStyleToolBoxControl() { } - -void SvxLineStyleToolBoxControl::StateChanged ( - - sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState ) - +void SAL_CALL SvxLineStyleToolBoxControl::statusChanged( const frame::FeatureStateEvent& rEvent ) { - SvxLineBox* pBox = static_cast<SvxLineBox*>( GetToolBox().GetItemWindow( GetId() ) ); - DBG_ASSERT( pBox, "Window not found!" ); + ToolBox* pToolBox = nullptr; + sal_uInt16 nId = 0; + if (!getToolboxId(nId, &pToolBox) && !m_pToolbar) + return; + + OString sId(m_aCommandURL.toUtf8()); - if( eState == SfxItemState::DISABLED ) + if ( rEvent.FeatureURL.Complete == m_aCommandURL ) { - pBox->Disable(); - pBox->SetNoSelection(); + if (m_pToolbar) + m_pToolbar->set_item_sensitive(sId, rEvent.IsEnabled); + else + pToolBox->EnableItem( nId, rEvent.IsEnabled ); } - else - { - pBox->Enable(); - if ( eState == SfxItemState::DEFAULT ) + m_xBtnUpdater->Update(rEvent); + + SfxObjectShell* pSh = SfxObjectShell::Current(); + if (pSh) + { + const SvxDashListItem* pItem = pSh->GetItem( SID_DASH_LIST ); + if (pItem) { - if( nSID == SID_ATTR_LINE_STYLE ) + XDashListRef xList = pItem->GetDashList(); + int nIndex = m_xBtnUpdater->GetStyleIndex(); + switch (nIndex) { - pStyleItem.reset( static_cast<XLineStyleItem*>(pState->Clone()) ); - } - else if( nSID == SID_ATTR_LINE_DASH ) - { - pDashItem.reset( static_cast<XLineDashItem*>(pState->Clone()) ); + case -1: + case 0: + { + BitmapEx aEmpty(xList->GetBitmapForUISolidLine()); + aEmpty.Erase(Application::GetSettings().GetStyleSettings().GetFieldColor()); + if (m_pToolbar) + { + Graphic aGraf(aEmpty); + m_pToolbar->set_item_image(sId, aGraf.GetXGraphic()); + } + else + pToolBox->SetItemImage(nId, Image(aEmpty)); + break; + } + case 1: + if (m_pToolbar) + { + Graphic aGraf(xList->GetBitmapForUISolidLine()); + m_pToolbar->set_item_image(sId, aGraf.GetXGraphic()); + } + else + pToolBox->SetItemImage(nId, Image(xList->GetBitmapForUISolidLine())); + break; + default: + if (m_pToolbar) + { + Graphic aGraf(xList->GetUiBitmap(nIndex - 2)); + m_pToolbar->set_item_image(sId, aGraf.GetXGraphic()); + } + else + pToolBox->SetItemImage(nId, Image(xList->GetUiBitmap(nIndex - 2))); + break; } - - bUpdate = true; - Update( pState ); - } - else if ( nSID != SID_DASH_LIST ) - { - // no or ambiguous status - pBox->SetNoSelection(); } } } - -void SvxLineStyleToolBoxControl::Update( const SfxPoolItem* pState ) +void SAL_CALL SvxLineStyleToolBoxControl::execute(sal_Int16 /*KeyModifier*/) { - if ( pState && bUpdate ) + if (m_pToolbar) { - bUpdate = false; - - SvxLineBox* pBox = static_cast<SvxLineBox*>(GetToolBox().GetItemWindow( GetId() )); - DBG_ASSERT( pBox, "Window not found!" ); - - // Since the timer can strike unexpectedly, it may happen that - // the LB is not yet filled. A ClearCache() on the control - // in DelayHdl () was unsuccessful. - if( pBox->GetEntryCount() == 0 ) - pBox->FillControl(); - - drawing::LineStyle eXLS; - - if ( pStyleItem ) - eXLS = pStyleItem->GetValue(); - else - eXLS = drawing::LineStyle_NONE; - - switch( eXLS ) - { - case drawing::LineStyle_NONE: - pBox->SelectEntryPos( 0 ); - break; - - case drawing::LineStyle_SOLID: - pBox->SelectEntryPos( 1 ); - break; + // Toggle the popup also when toolbutton is activated + const OString aId(m_aCommandURL.toUtf8()); + m_pToolbar->set_menu_item_active(aId, !m_pToolbar->get_menu_item_active(aId)); + } + else + { + // Open the popup also when Enter key is pressed. + createPopupWindow(); + } +} - case drawing::LineStyle_DASH: - { - if( pDashItem ) - { - OUString aString = SvxUnogetInternalNameForItem( - XATTR_LINEDASH, pDashItem->GetName()); - pBox->SelectEntry( aString ); - } - else - pBox->SetNoSelection(); - } - break; +void SvxLineStyleToolBoxControl::initialize( const css::uno::Sequence<css::uno::Any>& rArguments ) +{ + svt::PopupWindowController::initialize( rArguments ); - default: - OSL_FAIL( "Unsupported type of line" ); - break; - } + if (m_pToolbar) + { + mxPopoverContainer.reset(new ToolbarPopupContainer(m_pToolbar)); + m_pToolbar->set_item_popover(m_aCommandURL.toUtf8(), mxPopoverContainer->getTopLevel()); } - if ( auto pDashListItem = dynamic_cast<const SvxDashListItem*>( pState) ) + ToolBox* pToolBox = nullptr; + sal_uInt16 nId = 0; + if ( getToolboxId( nId, &pToolBox ) ) { - // The list of line styles has changed - SvxLineBox* pBox = static_cast<SvxLineBox*>(GetToolBox().GetItemWindow( GetId() )); - DBG_ASSERT( pBox, "Window not found!" ); - - OUString aString( pBox->GetSelectedEntry() ); - pBox->Clear(); - pBox->InsertEntry( SvxResId(RID_SVXSTR_INVISIBLE) ); - pBox->InsertEntry( SvxResId(RID_SVXSTR_SOLID) ); - pBox->Fill( pDashListItem->GetDashList() ); - pBox->SelectEntry( aString ); + pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | ToolBoxItemBits::DROPDOWNONLY ); } -} + m_xBtnUpdater.reset(new svx::ToolboxButtonLineStyleUpdater); +} -VclPtr<vcl::Window> SvxLineStyleToolBoxControl::CreateItemWindow( vcl::Window *pParent ) +void SvxLineStyleToolBoxControl::setLineStyleSelectFunction(const LineStyleSelectFunction& rLineStyleSelectFunction) { - return VclPtr<SvxLineBox>::Create( pParent, m_xFrame ).get(); + m_aLineStyleSelectFunction = rLineStyleSelectFunction; } -SvxLineWidthToolBoxControl::SvxLineWidthToolBoxControl( - sal_uInt16 nSlotId, sal_uInt16 nId, ToolBox& rTbx ) : - SfxToolBoxControl( nSlotId, nId, rTbx ) +void SvxLineStyleToolBoxControl::dispatchLineStyleCommand(const OUString& rCommand, const Sequence<PropertyValue>& rArgs) { - addStatusListener( ".uno:MetricUnit"); -} + if (m_aLineStyleSelectFunction && m_aLineStyleSelectFunction(rCommand, rArgs[0].Value)) + return; + dispatchCommand(rCommand, rArgs); +} -SvxLineWidthToolBoxControl::~SvxLineWidthToolBoxControl() +int SvxLineStyleToolBoxControl::GetStyleIndex() const { + return m_xBtnUpdater->GetStyleIndex(); } - -void SvxLineWidthToolBoxControl::StateChanged( - sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState ) +std::unique_ptr<WeldToolbarPopup> SvxLineStyleToolBoxControl::weldPopupWindow() { - SvxMetricField* pFld = static_cast<SvxMetricField*>( - GetToolBox().GetItemWindow( GetId() )); - DBG_ASSERT( pFld, "Window not found" ); + return std::make_unique<SvxLineBox>(this, m_pToolbar, m_xBtnUpdater->GetStyleIndex()); +} - if ( nSID == SID_ATTR_METRIC ) - { - pFld->RefreshDlgUnit(); - } - else - { - if ( eState == SfxItemState::DISABLED ) - { - pFld->Disable(); - pFld->SetText( "" ); - } - else - { - pFld->Enable(); +VclPtr<vcl::Window> SvxLineStyleToolBoxControl::createVclPopupWindow( vcl::Window* pParent ) +{ + mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, + std::make_unique<SvxLineBox>(this, pParent->GetFrameWeld(), m_xBtnUpdater->GetStyleIndex())); - if ( eState == SfxItemState::DEFAULT ) - { - DBG_ASSERT( dynamic_cast<const XLineWidthItem*>( pState) != nullptr, "wrong ItemType" ); + mxInterimPopover->Show(); - // Core-Unit handed over to MetricField - // Should not happen in CreateItemWin ()! - // CD!!! GetCoreMetric(); - pFld->SetCoreUnit( MapUnit::Map100thMM ); + return mxInterimPopover; +} - pFld->Update( static_cast<const XLineWidthItem*>(pState) ); - } - else - pFld->Update( nullptr ); - } - } +OUString SvxLineStyleToolBoxControl::getImplementationName() +{ + return "com.sun.star.comp.svx.LineStyleToolBoxControl"; } +css::uno::Sequence<OUString> SvxLineStyleToolBoxControl::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} -VclPtr<vcl::Window> SvxLineWidthToolBoxControl::CreateItemWindow( vcl::Window *pParent ) +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_svx_LineStyleToolBoxControl_get_implementation( + css::uno::XComponentContext* rContext, + css::uno::Sequence<css::uno::Any> const & ) { - return VclPtr<SvxMetricField>::Create( pParent, m_xFrame ).get(); + return cppu::acquire( new SvxLineStyleToolBoxControl( rContext ) ); } namespace { -class SvxLineEndToolBoxControl : public svt::PopupWindowController +class SvxLineEndToolBoxControl final : public svt::PopupWindowController { public: explicit SvxLineEndToolBoxControl( const css::uno::Reference<css::uno::XComponentContext>& rContext ); @@ -529,4 +505,136 @@ com_sun_star_comp_svx_LineEndToolBoxControl_get_implementation( return cppu::acquire( new SvxLineEndToolBoxControl( rContext ) ); } +SvxLineBox::SvxLineBox(SvxLineStyleToolBoxControl* pControl, weld::Widget* pParent, int nInitialIndex) + : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "svx/ui/floatinglinestyle.ui", "FloatingLineStyle") + , mxControl(pControl) + , mxLineStyleSet(new SvtValueSet(m_xBuilder->weld_scrolled_window("valuesetwin"))) + , mxLineStyleSetWin(new weld::CustomWeld(*m_xBuilder, "valueset", *mxLineStyleSet)) +{ + mxLineStyleSet->SetStyle(WB_FLATVALUESET | WB_ITEMBORDER | WB_3DLOOK | WB_NO_DIRECTSELECT); + + FillControl(); + + mxLineStyleSet->SelectItem(nInitialIndex + 1); + + mxLineStyleSet->SetSelectHdl( LINK( this, SvxLineBox, SelectHdl ) ); +} + +void SvxLineBox::GrabFocus() +{ + mxLineStyleSet->GrabFocus(); +} + +SvxLineBox::~SvxLineBox() +{ +} + +// Fills the listbox (provisional) with strings + +void SvxLineBox::Fill( const XDashListRef &pList ) +{ + mxLineStyleSet->Clear(); + + if( !pList.is() ) + return; + + // entry for 'none' + mxLineStyleSet->InsertItem(1, Image(), pList->GetStringForUiNoLine()); + + // entry for solid line + auto aBmp = pList->GetBitmapForUISolidLine(); + Size aBmpSize = aBmp.GetSizePixel(); + mxLineStyleSet->InsertItem(2, Image(aBmp), pList->GetStringForUiSolidLine()); + + // entries for dashed lines + long nCount = pList->Count(); + for( long i = 0; i < nCount; i++ ) + { + const XDashEntry* pEntry = pList->GetDash(i); + const BitmapEx aBitmap = pList->GetUiBitmap(i); + + mxLineStyleSet->InsertItem(i + 3, Image(aBitmap), pEntry->GetName()); + } + + sal_uInt16 nLines = std::min( static_cast<sal_uInt16>(nCount + 2), sal_uInt16(MAX_LINES) ); + mxLineStyleSet->SetLineCount(nLines); + + WinBits nBits = mxLineStyleSet->GetStyle(); + if ( nLines == mxLineStyleSet->GetItemCount() ) + nBits &= ~WB_VSCROLL; + else + nBits |= WB_VSCROLL; + mxLineStyleSet->SetStyle( nBits ); + + Size aSize(aBmpSize); + aSize.AdjustWidth(6); + aSize.AdjustHeight(6); + aSize = mxLineStyleSet->CalcWindowSizePixel(aSize); + mxLineStyleSet->GetDrawingArea()->set_size_request(aSize.Width(), aSize.Height()); + mxLineStyleSet->SetOutputSizePixel(aSize); +} + +IMPL_LINK_NOARG(SvxLineBox, SelectHdl, SvtValueSet*, void) +{ + drawing::LineStyle eXLS; + sal_Int32 nPos = mxLineStyleSet->GetSelectedItemId(); + --nPos; // ids start at 1, get the pos of the id + + switch ( nPos ) + { + case 0: + eXLS = drawing::LineStyle_NONE; + break; + + case 1: + eXLS = drawing::LineStyle_SOLID; + break; + + default: + { + eXLS = drawing::LineStyle_DASH; + + if ( nPos != -1 && + SfxObjectShell::Current() && + SfxObjectShell::Current()->GetItem( SID_DASH_LIST ) ) + { + // LineDashItem will only be sent if it also has a dash. + // Notify cares! + SvxDashListItem const * pItem = SfxObjectShell::Current()->GetItem( SID_DASH_LIST ); + const XDashEntry* pEntry = pItem->GetDashList()->GetDash(nPos - 2); + XLineDashItem aLineDashItem(pEntry->GetName(), pEntry->GetDash()); + + Any a; + Sequence< PropertyValue > aArgs( 1 ); + aArgs[0].Name = "LineDash"; + aLineDashItem.QueryValue ( a ); + aArgs[0].Value = a; + mxControl->dispatchLineStyleCommand(".uno:LineDash", aArgs); + } + } + break; + } + + XLineStyleItem aLineStyleItem( eXLS ); + Any a; + Sequence< PropertyValue > aArgs( 1 ); + aArgs[0].Name = "XLineStyle"; + aLineStyleItem.QueryValue ( a ); + aArgs[0].Value = a; + mxControl->dispatchLineStyleCommand(".uno:XLineStyle", aArgs); + + mxControl->EndPopupMode(); +} + +void SvxLineBox::FillControl() +{ + SfxObjectShell* pSh = SfxObjectShell::Current(); + if (pSh) + { + const SvxDashListItem* pItem = pSh->GetItem( SID_DASH_LIST ); + if (pItem) + Fill(pItem->GetDashList()); + } +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |