/* -*- 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 "sal/config.h" #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 "svtools/treelistentry.hxx" #include "svtools/viewdataentry.hxx" #include #include #include #include "helpids.h" #include "strings.hrc" #include "acccfg.hxx" #include "cfg.hxx" #include "SvxToolbarConfigPage.hxx" #include "SvxConfigPageHelper.hxx" #include "eventdlg.hxx" #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 "com/sun/star/ui/dialogs/TemplateDescription.hpp" #include #include #include "dlgname.hxx" SvxToolbarConfigPage::SvxToolbarConfigPage(vcl::Window *pParent, const SfxItemSet& rSet) : SvxConfigPage(pParent, rSet) { SetHelpId( HID_SVX_CONFIG_TOOLBAR ); m_pContentsListBox = VclPtr::Create(m_pEntries, this); m_pContentsListBox->set_grid_left_attach(0); m_pContentsListBox->set_grid_top_attach(0); m_pContentsListBox->set_hexpand(true); m_pContentsListBox->set_vexpand(true); m_pContentsListBox->Show(); m_pTopLevelListBox->SetHelpId ( HID_SVX_TOPLEVELLISTBOX ); m_pContentsListBox->SetHelpId( HID_SVX_CONFIG_TOOLBAR_CONTENTS ); m_pSaveInListBox->SetHelpId( HID_SVX_SAVE_IN ); m_pMoveUpButton->SetHelpId( HID_SVX_UP_TOOLBAR_ITEM ); m_pMoveDownButton->SetHelpId( HID_SVX_DOWN_TOOLBAR_ITEM ); m_pDescriptionField->SetHelpId ( HID_SVX_DESCFIELD ); m_pTopLevelListBox->SetSelectHdl( LINK( this, SvxToolbarConfigPage, SelectToolbar ) ); m_pContentsListBox->SetSelectHdl( LINK( this, SvxToolbarConfigPage, SelectToolbarEntry ) ); m_pCommandCategoryListBox->SetSelectHdl( LINK( this, SvxToolbarConfigPage, SelectCategory ) ); m_pPlusBtn->SetClickHdl( LINK( this, SvxToolbarConfigPage, AddToolbarHdl ) ); m_pMinusBtn->SetClickHdl( LINK( this, SvxToolbarConfigPage, RemoveToolbarHdl ) ); m_pMoveUpButton->SetClickHdl ( LINK( this, SvxToolbarConfigPage, MoveHdl) ); m_pMoveDownButton->SetClickHdl ( LINK( this, SvxToolbarConfigPage, MoveHdl) ); // Always enable Up and Down buttons // added for issue i53677 by shizhoubo m_pMoveDownButton->Enable(); m_pMoveUpButton->Enable(); m_pAddCommandButton->SetClickHdl( LINK( this, SvxToolbarConfigPage, AddCommandHdl ) ); m_pRemoveCommandButton->SetClickHdl( LINK( this, SvxToolbarConfigPage, RemoveCommandHdl ) ); m_pInsertBtn->SetSelectHdl( LINK( this, SvxToolbarConfigPage, InsertHdl ) ); m_pModifyBtn->SetSelectHdl( LINK( this, SvxToolbarConfigPage, ModifyItemHdl ) ); m_pResetBtn->SetClickHdl( LINK( this, SvxToolbarConfigPage, ResetToolbarHdl ) ); // "Insert Submenu" is irrelevant to the toolbars PopupMenu* pPopup = m_pInsertBtn->GetPopupMenu(); pPopup->EnableItem(OString( "insertsubmenu"), false ); pPopup->RemoveDisabledEntries(); // default toolbar to select is standardbar unless a different one // has been passed in m_aURLToSelect = ITEM_TOOLBAR_URL; m_aURLToSelect += "standardbar"; const SfxPoolItem* pItem = rSet.GetItem( rSet.GetPool()->GetWhich( SID_CONFIG ) ); if ( pItem ) { OUString text = static_cast(pItem)->GetValue(); if (text.startsWith( ITEM_TOOLBAR_URL )) { m_aURLToSelect = text.copy( 0 ); } } } SvxToolbarConfigPage::~SvxToolbarConfigPage() { disposeOnce(); } void SvxToolbarConfigPage::dispose() { for ( sal_Int32 i = 0 ; i < m_pSaveInListBox->GetEntryCount(); ++i ) { ToolbarSaveInData* pData = static_cast(m_pSaveInListBox->GetEntryData( i )); delete pData; } m_pSaveInListBox->Clear(); SvxConfigPage::dispose(); } void SvxToolbarConfigPage::DeleteSelectedTopLevel() { const sal_Int32 nSelectionPos = m_pTopLevelListBox->GetSelectedEntryPos(); ToolbarSaveInData* pSaveInData = static_cast( GetSaveInData() ); pSaveInData->RemoveToolbar( GetTopLevelSelection() ); if ( m_pTopLevelListBox->GetEntryCount() > 1 ) { // select next entry after the one being deleted // selection position is indexed from 0 so need to // subtract one from the entry count if ( nSelectionPos != m_pTopLevelListBox->GetEntryCount() - 1 ) { m_pTopLevelListBox->SelectEntryPos( nSelectionPos + 1 ); } else { m_pTopLevelListBox->SelectEntryPos( nSelectionPos - 1 ); } m_pTopLevelListBox->GetSelectHdl().Call( *m_pTopLevelListBox ); // and now remove the entry m_pTopLevelListBox->RemoveEntry( nSelectionPos ); } else { ReloadTopLevelListBox(); } } void SvxToolbarConfigPage::DeleteSelectedContent() { SvTreeListEntry *pActEntry = m_pContentsListBox->FirstSelected(); if ( pActEntry != nullptr ) { // get currently selected entry SvxConfigEntry* pEntry = static_cast(pActEntry->GetUserData()); SvxConfigEntry* pToolbar = GetTopLevelSelection(); // remove entry from the list for this toolbar SvxConfigPageHelper::RemoveEntry( pToolbar->GetEntries(), pEntry ); // remove toolbar entry from UI m_pContentsListBox->GetModel()->Remove( pActEntry ); // delete data for toolbar entry delete pEntry; static_cast(GetSaveInData())->ApplyToolbar( pToolbar ); UpdateButtonStates(); // if this is the last entry in the toolbar and it is a user // defined toolbar pop up a dialog asking the user if they // want to delete the toolbar if ( m_pContentsListBox->GetEntryCount() == 0 && GetTopLevelSelection()->IsDeletable() ) { ScopedVclPtrInstance qbox(this, CuiResId(RID_SXVSTR_CONFIRM_DELETE_TOOLBAR), VclMessageType::Question, VclButtonsType::YesNo); if ( qbox->Execute() == RET_YES ) { DeleteSelectedTopLevel(); } } } } IMPL_LINK( SvxToolbarConfigPage, MoveHdl, Button *, pButton, void ) { MoveEntry(pButton == m_pMoveUpButton); } void SvxToolbarConfigPage::MoveEntry( bool bMoveUp ) { SvxConfigPage::MoveEntry( bMoveUp ); // Apply change to currently selected toolbar SvxConfigEntry* pToolbar = GetTopLevelSelection(); if ( pToolbar ) static_cast(GetSaveInData())->ApplyToolbar( pToolbar ); else { SAL_WARN( "cui.customize", "SvxToolbarConfigPage::MoveEntry(): no entry" ); UpdateButtonStates(); } } void SvxToolbarConfigPage::Init() { // ensure that the UI is cleared before populating it m_pTopLevelListBox->Clear(); m_pContentsListBox->Clear(); ReloadTopLevelListBox(); sal_Int32 nPos = 0; if ( !m_aURLToSelect.isEmpty() ) { for ( sal_Int32 i = 0 ; i < m_pTopLevelListBox->GetEntryCount(); ++i ) { SvxConfigEntry* pData = static_cast(m_pTopLevelListBox->GetEntryData( i )); if ( pData->GetCommand().equals( m_aURLToSelect ) ) { nPos = i; break; } } // in future select the default toolbar: Standard m_aURLToSelect = ITEM_TOOLBAR_URL; m_aURLToSelect += "standardbar"; } m_pTopLevelListBox->SelectEntryPos(nPos); m_pTopLevelListBox->GetSelectHdl().Call(*m_pTopLevelListBox); m_pCommandCategoryListBox->Init( comphelper::getProcessComponentContext(), m_xFrame, vcl::CommandInfoProvider::GetModuleIdentifier(m_xFrame)); m_pCommandCategoryListBox->categorySelected( m_pFunctions ); } SaveInData* SvxToolbarConfigPage::CreateSaveInData( const css::uno::Reference< css::ui::XUIConfigurationManager >& xCfgMgr, const css::uno::Reference< css::ui::XUIConfigurationManager >& xParentCfgMgr, const OUString& aModuleId, bool bDocConfig ) { return static_cast< SaveInData* >( new ToolbarSaveInData( xCfgMgr, xParentCfgMgr, aModuleId, bDocConfig )); } IMPL_LINK_NOARG( SvxToolbarConfigPage, SelectToolbarEntry, SvTreeListBox *, void ) { UpdateButtonStates(); } IMPL_LINK_NOARG( SvxToolbarConfigPage, AddToolbarHdl, Button *, void ) { OUString prefix = CuiResId( RID_SVXSTR_NEW_TOOLBAR ); OUString aNewName = SvxConfigPageHelper::generateCustomName( prefix, GetSaveInData()->GetEntries() ); OUString aNewURL = SvxConfigPageHelper::generateCustomURL( GetSaveInData()->GetEntries() ); VclPtrInstance< SvxNewToolbarDialog > pNameDialog( nullptr, aNewName ); // Reflect the actual m_pSaveInListBox into the new toolbar dialog for ( sal_Int32 i = 0; i < m_pSaveInListBox->GetEntryCount(); ++i ) { SaveInData* pData = static_cast(m_pSaveInListBox->GetEntryData( i )); const sal_Int32 nInsertPos = pNameDialog->m_pSaveInListBox->InsertEntry( m_pSaveInListBox->GetEntry( i ) ); pNameDialog->m_pSaveInListBox->SetEntryData( nInsertPos, pData ); } pNameDialog->m_pSaveInListBox->SelectEntryPos( m_pSaveInListBox->GetSelectedEntryPos() ); if ( pNameDialog->Execute() == RET_OK ) { aNewName = pNameDialog->GetName(); // Where to save the new toolbar? (i.e. Modulewise or documentwise) sal_Int32 nInsertPos = pNameDialog->m_pSaveInListBox->GetSelectedEntryPos(); ToolbarSaveInData* pData = static_cast( pNameDialog->m_pSaveInListBox->GetEntryData( nInsertPos ) ); if ( GetSaveInData() != pData ) { m_pSaveInListBox->SelectEntryPos( nInsertPos ); m_pSaveInListBox->GetSelectHdl().Call(*m_pSaveInListBox); } SvxConfigEntry* pToolbar = new SvxConfigEntry( aNewName, aNewURL, true ); pToolbar->SetUserDefined(); pToolbar->SetMain(); pData->CreateToolbar( pToolbar ); nInsertPos = m_pTopLevelListBox->InsertEntry( pToolbar->GetName() ); m_pTopLevelListBox->SetEntryData( nInsertPos, pToolbar ); m_pTopLevelListBox->SelectEntryPos( nInsertPos ); m_pTopLevelListBox->GetSelectHdl().Call(*m_pTopLevelListBox); pData->SetModified(); } } IMPL_LINK_NOARG( SvxToolbarConfigPage, RemoveToolbarHdl, Button *, void ) { SvxConfigEntry* pToolbar = GetTopLevelSelection(); if ( pToolbar && pToolbar->IsDeletable() ) { DeleteSelectedTopLevel(); UpdateButtonStates(); } } IMPL_LINK_NOARG( SvxToolbarConfigPage, SelectCategory, ListBox&, void ) { OUString aSearchTerm( m_pSearchEdit->GetText() ); m_pCommandCategoryListBox->categorySelected( m_pFunctions, aSearchTerm ); } IMPL_LINK_NOARG( SvxToolbarConfigPage, AddCommandHdl, Button *, void ) { AddFunction(); } IMPL_LINK_NOARG( SvxToolbarConfigPage, RemoveCommandHdl, Button *, void ) { DeleteSelectedContent(); } IMPL_LINK( SvxToolbarConfigPage, InsertHdl, MenuButton *, pButton, void ) { OString sIdent = pButton->GetCurItemIdent(); if (sIdent == "insertseparator") { // Get the currently selected toolbar SvxConfigEntry* pToolbar = GetTopLevelSelection(); SvxConfigEntry* pNewEntryData = new SvxConfigEntry; pNewEntryData->SetUserDefined(); SvTreeListEntry* pNewLBEntry = InsertEntry( pNewEntryData ); m_pContentsListBox->SetCheckButtonInvisible( pNewLBEntry ); m_pContentsListBox->SetCheckButtonState( pNewLBEntry, SvButtonState::Tristate ); static_cast( GetSaveInData())->ApplyToolbar( pToolbar ); UpdateButtonStates(); } else { //This block should never be reached SAL_WARN("cui.customize", "Unknown insert option: " << sIdent); return; } } IMPL_LINK( SvxToolbarConfigPage, ModifyItemHdl, MenuButton *, pButton, void ) { bool bNeedsApply = false; // get currently selected toolbar SvxConfigEntry* pToolbar = GetTopLevelSelection(); OString sIdent = pButton->GetCurItemIdent(); if (sIdent == "renameItem") { SvTreeListEntry* pActEntry = m_pContentsListBox->GetCurEntry(); SvxConfigEntry* pEntry = static_cast(pActEntry->GetUserData()); OUString aNewName( SvxConfigPageHelper::stripHotKey( pEntry->GetName() ) ); OUString aDesc = CuiResId( RID_SVXSTR_LABEL_NEW_NAME ); VclPtrInstance< SvxNameDialog > pNameDialog( this, aNewName, aDesc ); pNameDialog->SetHelpId( HID_SVX_CONFIG_RENAME_TOOLBAR_ITEM ); pNameDialog->SetText( CuiResId( RID_SVXSTR_RENAME_TOOLBAR ) ); if ( pNameDialog->Execute() == RET_OK ) { pNameDialog->GetName(aNewName); if( aNewName.isEmpty() ) // tdf#80758 - Accelerator character ("~") is passed as pEntry->SetName( "~" ); // the button name in case of empty values. else pEntry->SetName( aNewName ); m_pContentsListBox->SetEntryText( pActEntry, aNewName ); bNeedsApply = true; } } else if (sIdent == "changeIcon") { SvTreeListEntry* pActEntry = m_pContentsListBox->GetCurEntry(); SvxConfigEntry* pEntry = static_cast(pActEntry->GetUserData()); // Position of entry within the list // TODO: Add a GetSelectionPos() method to the SvTreeListBox class sal_uInt16 nSelectionPos = m_pContentsListBox->GetModel()->GetAbsPos( pActEntry ); ScopedVclPtr pIconDialog( VclPtr::Create( nullptr, GetSaveInData()->GetImageManager(), GetSaveInData()->GetParentImageManager() )); if ( pIconDialog->Execute() == RET_OK ) { css::uno::Reference< css::graphic::XGraphic > newgraphic = pIconDialog->GetSelectedIcon(); if ( newgraphic.is() ) { css::uno::Sequence< css::uno::Reference< css::graphic::XGraphic > > aGraphicSeq( 1 ); css::uno::Sequence aURLSeq { pEntry->GetCommand() }; if ( !pEntry->GetBackupGraphic().is() ) { css::uno::Reference< css::graphic::XGraphic > backup; backup = SvxConfigPageHelper::GetGraphic( GetSaveInData()->GetImageManager(), aURLSeq[ 0 ] ); if ( backup.is() ) { pEntry->SetBackupGraphic( backup ); } } aGraphicSeq[ 0 ] = newgraphic; try { GetSaveInData()->GetImageManager()->replaceImages( SvxConfigPageHelper::GetImageType(), aURLSeq, aGraphicSeq ); m_pContentsListBox->GetModel()->Remove( pActEntry ); SvTreeListEntry* pNewLBEntry = InsertEntryIntoUI( pEntry, nSelectionPos ); m_pContentsListBox->SetCheckButtonState( pNewLBEntry, pEntry->IsVisible() ? SvButtonState::Checked : SvButtonState::Unchecked ); m_pContentsListBox->Select( pNewLBEntry ); m_pContentsListBox->MakeVisible( pNewLBEntry ); GetSaveInData()->PersistChanges( GetSaveInData()->GetImageManager() ); } catch ( css::uno::Exception& e) { SAL_WARN("cui.customize", "Error replacing image: " << e); } } } } else if (sIdent == "resetIcon") { SvTreeListEntry* pActEntry = m_pContentsListBox->GetCurEntry(); SvxConfigEntry* pEntry = static_cast(pActEntry->GetUserData()); // Position of entry within the list // TODO: Add a GetSelectionPos() method to the SvTreeListBox class sal_uInt16 nSelectionPos = m_pContentsListBox->GetModel()->GetAbsPos( pActEntry ); css::uno::Reference< css::graphic::XGraphic > backup = pEntry->GetBackupGraphic(); css::uno::Sequence< css::uno::Reference< css::graphic::XGraphic > > aGraphicSeq( 1 ); aGraphicSeq[ 0 ] = backup; css::uno::Sequence aURLSeq { pEntry->GetCommand() }; try { GetSaveInData()->GetImageManager()->replaceImages( SvxConfigPageHelper::GetImageType(), aURLSeq, aGraphicSeq ); m_pContentsListBox->GetModel()->Remove( pActEntry ); SvTreeListEntry* pNewLBEntry = InsertEntryIntoUI( pEntry, nSelectionPos ); m_pContentsListBox->SetCheckButtonState( pNewLBEntry, pEntry->IsVisible() ? SvButtonState::Checked : SvButtonState::Unchecked ); m_pContentsListBox->Select( pNewLBEntry ); m_pContentsListBox->MakeVisible( pNewLBEntry ); // reset backup in entry pEntry->SetBackupGraphic( css::uno::Reference< css::graphic::XGraphic >() ); GetSaveInData()->PersistChanges( GetSaveInData()->GetImageManager() ); } catch ( css::uno::Exception& e ) { SAL_WARN("cui.customize", "Error resetting image: " << e); } } else if (sIdent == "restoreItem") { SvTreeListEntry* pActEntry = m_pContentsListBox->GetCurEntry(); SvxConfigEntry* pEntry = static_cast(pActEntry->GetUserData()); // Position of entry within the list // TODO: Add a GetSelectionPos() method to the SvTreeListBox class sal_uInt16 nSelectionPos = m_pContentsListBox->GetModel()->GetAbsPos( pActEntry ); ToolbarSaveInData* pSaveInData = static_cast( GetSaveInData() ); OUString aSystemName = pSaveInData->GetSystemUIName( pEntry->GetCommand() ); if ( !pEntry->GetName().equals( aSystemName ) ) { pEntry->SetName( aSystemName ); m_pContentsListBox->SetEntryText( pActEntry, SvxConfigPageHelper::stripHotKey( aSystemName ) ); bNeedsApply = true; } css::uno::Sequence aURLSeq { pEntry->GetCommand() }; try { GetSaveInData()->GetImageManager()->removeImages( SvxConfigPageHelper::GetImageType(), aURLSeq ); // reset backup in entry pEntry->SetBackupGraphic( css::uno::Reference< css::graphic::XGraphic >() ); GetSaveInData()->PersistChanges( GetSaveInData()->GetImageManager() ); m_pContentsListBox->RemoveEntry( pActEntry ); SvTreeListEntry* pNewLBEntry = InsertEntryIntoUI( pEntry, nSelectionPos ); m_pContentsListBox->SetCheckButtonState( pNewLBEntry, pEntry->IsVisible() ? SvButtonState::Checked : SvButtonState::Unchecked ); m_pContentsListBox->Select( pNewLBEntry ); m_pContentsListBox->MakeVisible( pNewLBEntry ); bNeedsApply = true; } catch ( css::uno::Exception& e ) { SAL_WARN("cui.customize", "Error restoring image: " << e); } } else { //This block should never be reached SAL_WARN("cui.customize", "Unknown insert option: " << sIdent); return; } if ( bNeedsApply ) { static_cast( GetSaveInData())->ApplyToolbar( pToolbar ); UpdateButtonStates(); } } IMPL_LINK_NOARG( SvxToolbarConfigPage, ResetToolbarHdl, Button *, void ) { sal_Int32 nSelectionPos = m_pTopLevelListBox->GetSelectedEntryPos(); SvxConfigEntry* pToolbar = static_cast(m_pTopLevelListBox->GetEntryData( nSelectionPos )); ScopedVclPtrInstance qbox(this, CuiResId(RID_SVXSTR_CONFIRM_RESTORE_DEFAULT), VclMessageType::Question, VclButtonsType::YesNo); if ( qbox->Execute() == RET_YES ) { ToolbarSaveInData* pSaveInData = static_cast(GetSaveInData()); pSaveInData->RestoreToolbar( pToolbar ); m_pTopLevelListBox->GetSelectHdl().Call( *m_pTopLevelListBox ); } } void SvxToolbarConfigPage::UpdateButtonStates() { SvTreeListEntry* selection = m_pContentsListBox->GetCurEntry(); bool bIsSeparator = selection && static_cast(selection->GetUserData())->IsSeparator(); bool bIsValidSelection = !(m_pContentsListBox->GetEntryCount() == 0 || selection == nullptr); m_pMoveUpButton->Enable( bIsValidSelection ); m_pMoveDownButton->Enable( bIsValidSelection ); m_pRemoveCommandButton->Enable( bIsValidSelection ); m_pModifyBtn->Enable( bIsValidSelection && !bIsSeparator ); } short SvxToolbarConfigPage::QueryReset() { OUString msg = CuiResId( RID_SVXSTR_CONFIRM_TOOLBAR_RESET ); OUString saveInName = m_pSaveInListBox->GetEntry( m_pSaveInListBox->GetSelectedEntryPos() ); OUString label = SvxConfigPageHelper::replaceSaveInName( msg, saveInName ); ScopedVclPtrInstance< QueryBox > qbox( this, MessBoxStyle::YesNo, label ); return qbox->Execute(); } IMPL_LINK_NOARG( SvxToolbarConfigPage, SelectToolbar, ListBox&, void ) { m_pContentsListBox->Clear(); SvxConfigEntry* pToolbar = GetTopLevelSelection(); if ( pToolbar == nullptr ) { //TODO: Disable related buttons m_pPlusBtn->Enable( false ); m_pMinusBtn->Enable( false ); m_pInsertBtn->Enable( false ); m_pResetBtn->Enable( false ); return; } else { m_pPlusBtn->Enable(); m_pMinusBtn->Enable( pToolbar->IsDeletable() ); m_pInsertBtn->Enable(); m_pResetBtn->Enable(); } SvxEntries* pEntries = pToolbar->GetEntries(); SvxEntries::const_iterator iter = pEntries->begin(); for ( ; iter != pEntries->end(); ++iter ) { SvxConfigEntry* pEntry = *iter; SvTreeListEntry* pNewLBEntry = InsertEntryIntoUI( pEntry ); if(pEntry->IsSeparator()) m_pContentsListBox->SetCheckButtonInvisible( pNewLBEntry ); if (pEntry->IsBinding()) { m_pContentsListBox->SetCheckButtonState( pNewLBEntry, pEntry->IsVisible() ? SvButtonState::Checked : SvButtonState::Unchecked ); } else { m_pContentsListBox->SetCheckButtonState( pNewLBEntry, SvButtonState::Tristate ); } } UpdateButtonStates(); } void SvxToolbarConfigPage::AddFunction( SvTreeListEntry* pTarget, bool bFront ) { // Add the command to the contents listbox of the selected toolbar SvTreeListEntry* pNewLBEntry = SvxConfigPage::AddFunction( pTarget, bFront, true/*bAllowDuplicates*/ ); SvxConfigEntry* pEntry = static_cast(pNewLBEntry->GetUserData()); if ( pEntry->IsBinding() ) { pEntry->SetVisible( true ); m_pContentsListBox->SetCheckButtonState( pNewLBEntry, SvButtonState::Checked ); } else { m_pContentsListBox->SetCheckButtonState( pNewLBEntry, SvButtonState::Tristate ); } // Changes are not visible on the toolbar until this point // TODO: Figure out a way to show the changes on the toolbar, but revert if // the dialog is closed by pressing "Cancel" // get currently selected toolbar and apply change SvxConfigEntry* pToolbar = GetTopLevelSelection(); if ( pToolbar != nullptr ) { static_cast( GetSaveInData() )->ApplyToolbar( pToolbar ); } } SvxToolbarEntriesListBox::SvxToolbarEntriesListBox(vcl::Window* pParent, SvxToolbarConfigPage* pPg) : SvxMenuEntriesListBox(pParent, pPg) , pPage(pPg) { m_pButtonData = new SvLBoxButtonData( this ); BuildCheckBoxButtonImages( m_pButtonData ); EnableCheckButton( m_pButtonData ); } SvxToolbarEntriesListBox::~SvxToolbarEntriesListBox() { disposeOnce(); } void SvxToolbarEntriesListBox::dispose() { delete m_pButtonData; m_pButtonData = nullptr; pPage.clear(); SvxMenuEntriesListBox::dispose(); } void SvxToolbarEntriesListBox::BuildCheckBoxButtonImages( SvLBoxButtonData* pData ) { // Build checkbox images according to the current application // settings. This is necessary to be able to have correct colors // in all color modes, like high contrast. const AllSettings& rSettings = Application::GetSettings(); ScopedVclPtrInstance< VirtualDevice > pVDev; Size aSize( 26, 20 ); pVDev->SetOutputSizePixel( aSize ); Image aImage = GetSizedImage( *pVDev.get(), aSize, CheckBox::GetCheckImage( rSettings, DrawButtonFlags::Default )); // Fill button data struct with new images pData->SetImage(SvBmp::UNCHECKED, aImage); pData->SetImage(SvBmp::CHECKED, GetSizedImage( *pVDev.get(), aSize, CheckBox::GetCheckImage( rSettings, DrawButtonFlags::Checked )) ); pData->SetImage(SvBmp::HICHECKED, GetSizedImage( *pVDev.get(), aSize, CheckBox::GetCheckImage( rSettings, DrawButtonFlags::Checked | DrawButtonFlags::Pressed )) ); pData->SetImage(SvBmp::HIUNCHECKED, GetSizedImage( *pVDev.get(), aSize, CheckBox::GetCheckImage( rSettings, DrawButtonFlags::Default | DrawButtonFlags::Pressed)) ); pData->SetImage(SvBmp::TRISTATE, GetSizedImage( *pVDev.get(), aSize, Image() ) ); // Use tristate bitmaps to have no checkbox for separator entries pData->SetImage(SvBmp::HITRISTATE, GetSizedImage( *pVDev.get(), aSize, Image() ) ); // Get image size m_aCheckBoxImageSizePixel = aImage.GetSizePixel(); } Image SvxToolbarEntriesListBox::GetSizedImage( VirtualDevice& rVDev, const Size& aNewSize, const Image& aImage ) { // Create new checkbox images for treelistbox. They must have a // decent width to have a clear column for the visibility checkbox. // Standard transparent color is light magenta as is won't be // used for other things Color aFillColor( COL_LIGHTMAGENTA ); // Position image at the center of (width-2),(height) rectangle. // We need 2 pixels to have a bigger border to the next button image sal_uInt16 nPosX = std::max( (sal_uInt16) (((( aNewSize.Width() - 2 ) - aImage.GetSizePixel().Width() ) / 2 ) - 1), (sal_uInt16) 0 ); sal_uInt16 nPosY = std::max( (sal_uInt16) (((( aNewSize.Height() - 2 ) - aImage.GetSizePixel().Height() ) / 2 ) + 1), (sal_uInt16) 0 ); Point aPos( nPosX > 0 ? nPosX : 0, nPosY > 0 ? nPosY : 0 ); rVDev.SetFillColor( aFillColor ); rVDev.SetLineColor( aFillColor ); rVDev.DrawRect( ::tools::Rectangle( Point(), aNewSize )); rVDev.DrawImage( aPos, aImage ); // Draw separator line 2 pixels left from the right border Color aLineColor = GetDisplayBackground().GetColor().IsDark() ? Color( COL_WHITE ) : Color( COL_BLACK ); rVDev.SetLineColor( aLineColor ); rVDev.DrawLine( Point( aNewSize.Width()-3, 0 ), Point( aNewSize.Width()-3, aNewSize.Height()-1 )); // Create new image that uses the fillcolor as transparent return Image(BitmapEx(rVDev.GetBitmap(Point(), aNewSize), aFillColor)); } void SvxToolbarEntriesListBox::DataChanged( const DataChangedEvent& rDCEvt ) { SvTreeListBox::DataChanged( rDCEvt ); if (( rDCEvt.GetType() == DataChangedEventType::SETTINGS ) && ( rDCEvt.GetFlags() & AllSettingsFlags::STYLE )) { BuildCheckBoxButtonImages( m_pButtonData ); Invalidate(); } } void SvxToolbarEntriesListBox::ChangeVisibility( SvTreeListEntry* pEntry ) { if ( pEntry != nullptr ) { SvxConfigEntry* pEntryData = static_cast(pEntry->GetUserData()); if ( pEntryData->IsBinding() ) { pEntryData->SetVisible( !pEntryData->IsVisible() ); SvxConfigEntry* pToolbar = pPage->GetTopLevelSelection(); ToolbarSaveInData* pToolbarSaveInData = static_cast( pPage->GetSaveInData() ); pToolbarSaveInData->ApplyToolbar( pToolbar ); SetCheckButtonState( pEntry, pEntryData->IsVisible() ? SvButtonState::Checked : SvButtonState::Unchecked ); } } } void SvxToolbarEntriesListBox::CheckButtonHdl() { ChangeVisibility( GetHdlEntry() ); } void SvxToolbarEntriesListBox::KeyInput( const KeyEvent& rKeyEvent ) { // space key will change visibility of toolbar items if ( rKeyEvent.GetKeyCode() == KEY_SPACE ) { ChangeVisibility( GetCurEntry() ); } else { // pass on to superclass SvxMenuEntriesListBox::KeyInput( rKeyEvent ); } } TriState SvxToolbarEntriesListBox::NotifyMoving( SvTreeListEntry* pTarget, SvTreeListEntry* pSource, SvTreeListEntry*& rpNewParent, sal_uLong& rNewChildPos) { TriState result = SvxMenuEntriesListBox::NotifyMoving( pTarget, pSource, rpNewParent, rNewChildPos ); if ( result ) { // Instant Apply changes to UI SvxConfigEntry* pToolbar = pPage->GetTopLevelSelection(); if ( pToolbar != nullptr ) { ToolbarSaveInData* pSaveInData = static_cast( pPage->GetSaveInData() ); pSaveInData->ApplyToolbar( pToolbar ); } } return result; } TriState SvxToolbarEntriesListBox::NotifyCopying( SvTreeListEntry* pTarget, SvTreeListEntry*, SvTreeListEntry*&, sal_uLong&) { if ( !m_bIsInternalDrag ) { // if the target is NULL then add function to the start of the list static_cast(pPage.get())->AddFunction( pTarget, pTarget == nullptr ); // Instant Apply changes to UI SvxConfigEntry* pToolbar = pPage->GetTopLevelSelection(); if ( pToolbar != nullptr ) { ToolbarSaveInData* pSaveInData = static_cast( pPage->GetSaveInData() ); pSaveInData->ApplyToolbar( pToolbar ); } // AddFunction already adds the listbox entry so return TRISTATE_FALSE // to stop another listbox entry being added return TRISTATE_FALSE; } // Copying is only allowed from external controls, not within the listbox return TRISTATE_FALSE; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */