Files
odfstudio/svx/source/tbxctrls/colrctrl.cxx
T
Michael Weghorn a81cc28ba6 sfx2: Pass SfxDockingWindow's SfxBindings param by ref
With the refactoring from previous commits in place, it's
clear that all callers pass a non-null SfxBindings*
param.
Switch the param to a reference, to make that clear
and prepare for further refactoring.

Change-Id: Id9f1487dba4b84860f9afa52ff9ffb4dd7b1d2c6
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/208387
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2026-07-23 23:21:34 +02:00

428 lines
14 KiB
C++

/* -*- 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 <sot/exchange.hxx>
#include <svx/strings.hrc>
#include <svx/svxids.hrc>
#include <sfx2/viewsh.hxx>
#include <sfx2/objsh.hxx>
#include <sfx2/dispatch.hxx>
#include <sfx2/viewfrm.hxx>
#include <vcl/image.hxx>
#include <vcl/transfer.hxx>
#include <vcl/weld/Builder.hxx>
#include <vcl/weld/ScrolledWindow.hxx>
#include <colrctrl.hxx>
#include <svx/svdview.hxx>
#include <svx/drawitem.hxx>
#include <svx/xfillit0.hxx>
#include <svx/xflclit.hxx>
#include <editeng/colritem.hxx>
#include <svx/xlineit0.hxx>
#include <svx/xlnclit.hxx>
#include <svx/dialmgr.hxx>
#include <helpids.h>
#include <vcl/virdev.hxx>
#include <com/sun/star/beans/NamedValue.hpp>
using namespace com::sun::star;
class SvxColorValueSetData final : public TransferDataContainer
{
private:
uno::Sequence<beans::NamedValue> m_Data;
virtual void AddSupportedFormats() override;
virtual bool GetData(const css::datatransfer::DataFlavor& rFlavor, const OUString& rDestDoc) override;
public:
SvxColorValueSetData()
{
}
void SetData(const uno::Sequence<beans::NamedValue>& rData)
{
m_Data = rData;
ClearFormats(); // invalidate m_aAny so new data will take effect
}
};
void SvxColorValueSetData::AddSupportedFormats()
{
AddFormat( SotClipboardFormatId::XFA );
}
bool SvxColorValueSetData::GetData( const css::datatransfer::DataFlavor& rFlavor, const OUString& /*rDestDoc*/ )
{
bool bRet = false;
if( SotExchange::GetFormat( rFlavor ) == SotClipboardFormatId::XFA )
{
SetAny(uno::Any(m_Data));
bRet = true;
}
return bRet;
}
void SvxColorValueSet_docking::SetDrawingArea(weld::DrawingArea* pDrawingArea)
{
SvxColorValueSet::SetDrawingArea(pDrawingArea);
SetStyle(GetStyle() | WB_ITEMBORDER);
m_xHelper.set(new SvxColorValueSetData);
rtl::Reference<TransferDataContainer> xHelper(m_xHelper);
SetDragDataTransferable(xHelper, DND_ACTION_COPY);
}
SvxColorValueSet_docking::SvxColorValueSet_docking(std::unique_ptr<weld::ScrolledWindow> xWindow)
: SvxColorValueSet(std::move(xWindow))
, mbLeftButton(true)
{
}
bool SvxColorValueSet_docking::MouseButtonDown( const MouseEvent& rMEvt )
{
bool bRet;
// For Mac still handle differently!
if( rMEvt.IsLeft() )
{
mbLeftButton = true;
bRet = SvxColorValueSet::MouseButtonDown( rMEvt );
}
else
{
mbLeftButton = false;
MouseEvent aMEvt( rMEvt.GetPosPixel(),
rMEvt.GetClicks(),
rMEvt.GetMode(),
MOUSE_LEFT,
rMEvt.GetModifier() );
bRet = SvxColorValueSet::MouseButtonDown( aMEvt );
}
return bRet;
}
bool SvxColorValueSet_docking::MouseButtonUp( const MouseEvent& rMEvt )
{
bool bRet;
// For Mac still handle differently!
if( rMEvt.IsLeft() )
{
mbLeftButton = true;
bRet = SvxColorValueSet::MouseButtonUp( rMEvt );
}
else
{
mbLeftButton = false;
MouseEvent aMEvt( rMEvt.GetPosPixel(),
rMEvt.GetClicks(),
rMEvt.GetMode(),
MOUSE_LEFT,
rMEvt.GetModifier() );
bRet = SvxColorValueSet::MouseButtonUp( aMEvt );
}
SetNoSelection();
return bRet;
}
bool SvxColorValueSet_docking::StartDrag()
{
sal_uInt16 nPos = GetSelectedItemId();
Color aItemColor( GetItemColor( nPos ) );
OUString sItemText( GetItemText( nPos ) );
drawing::FillStyle eStyle = (nPos == GetItemCount())
? drawing::FillStyle_NONE
: drawing::FillStyle_SOLID;
XFillColorItem const color(sItemText, aItemColor);
XFillStyleItem const style(eStyle);
uno::Any c, s;
color.QueryValue(c, 0);
style.QueryValue(s, 0);
uno::Sequence<beans::NamedValue> props{ { u"FillColor"_ustr, std::move(c) },
{ u"FillStyle"_ustr, std::move(s) } };
m_xHelper->SetData(props);
return false;
}
constexpr sal_uInt16 gnLeftSlot = SID_ATTR_FILL_COLOR;
constexpr sal_uInt16 gnRightSlot = SID_ATTR_LINE_COLOR;
SvxColorDockingWindow::SvxColorDockingWindow(SfxBindings& rBindings, SfxChildWindow* pCW,
vcl::Window* _pParent)
: SfxDockingWindow(rBindings, pCW, _pParent, u"DockingColorWindow"_ustr,
u"svx/ui/dockingcolorwindow.ui"_ustr)
, m_pColorSet(
new SvxColorValueSet_docking(m_xBuilder->weld_scrolled_window(u"valuesetwin"_ustr, true)))
, m_pColorSetWin(new weld::CustomWeld(*m_xBuilder, u"valueset"_ustr, *m_pColorSet))
{
SetText(SvxResId(STR_COLORTABLE));
SetQuickHelpText(SvxResId(RID_SVXSTR_COLORBAR));
SetSizePixel(LogicToPixel(Size(150, 22), MapMode(MapUnit::MapAppFont)));
SetHelpId(HID_CTRL_COLOR);
m_pColorSet->SetSelectHdl(LINK(this, SvxColorDockingWindow, SelectHdl));
m_pColorSet->SetAccessibleName(SvxResId(STR_COLORTABLE));
m_pColorSet->SetHelpId(HID_COLOR_CTL_COLORS);
// Get the model from the view shell. Using SfxObjectShell::Current()
// is unreliable when called at the wrong times.
SfxObjectShell* pDocSh = nullptr;
SfxDispatcher* pDispatcher = rBindings.GetDispatcher();
if (pDispatcher != nullptr)
{
SfxViewFrame* pFrame = pDispatcher->GetFrame();
if (pFrame != nullptr)
{
SfxViewShell* pViewShell = pFrame->GetViewShell();
if (pViewShell != nullptr)
pDocSh = pViewShell->GetObjectShell();
}
}
if ( pDocSh )
{
if (const SvxColorListItem* pItem = pDocSh->GetItem( SID_COLOR_TABLE ))
{
m_pColorList = pItem->GetColorList();
FillValueSet();
}
}
Size aItemSize = m_pColorSet->CalcItemSizePixel(
Size(SvxColorValueSet::getEntryEdgeLength(), SvxColorValueSet::getEntryEdgeLength()));
aItemSize.setWidth( aItemSize.Width() + SvxColorValueSet::getEntryEdgeLength() );
aItemSize.setWidth( aItemSize.Width() / 2 );
aItemSize.setHeight( aItemSize.Height() + SvxColorValueSet::getEntryEdgeLength() );
aItemSize.setHeight( aItemSize.Height() / 2 );
StartListening(rBindings, DuplicateHandling::Prevent);
}
SvxColorDockingWindow::~SvxColorDockingWindow()
{
disposeOnce();
}
void SvxColorDockingWindow::dispose()
{
EndListening( GetBindings() );
m_pColorSetWin.reset();
m_pColorSet.reset();
SfxDockingWindow::dispose();
}
void SvxColorDockingWindow::Notify( SfxBroadcaster& , const SfxHint& rHint )
{
if (rHint.GetId() == SfxHintId::PoolItem)
{
const SfxPoolItemHint* pPoolItemHint = static_cast<const SfxPoolItemHint*>(&rHint);
if (auto pColorListItem = dynamic_cast<const SvxColorListItem*>(pPoolItemHint->GetObject()))
{
// The list of colors has changed
m_pColorList = pColorListItem->GetColorList();
FillValueSet();
}
}
}
void SvxColorDockingWindow::FillValueSet()
{
if (!m_pColorList.is())
return;
m_pColorSet->Clear();
m_pColorSet->addEntriesForXColorList(*m_pColorList);
// create the last entry for 'invisible/none'
const Size aColorSize(SvxColorValueSet::getEntryEdgeLength(), SvxColorValueSet::getEntryEdgeLength());
tools::Long nPtX = aColorSize.Width() - 1;
tools::Long nPtY = aColorSize.Height() - 1;
ScopedVclPtrInstance< VirtualDevice > pVD;
pVD->SetOutputSizePixel( aColorSize );
pVD->SetLineColor( COL_BLACK );
pVD->SetBackground( Wallpaper( COL_WHITE ) );
pVD->DrawLine( Point(), Point( nPtX, nPtY ) );
pVD->DrawLine( Point( 0, nPtY ), Point( nPtX, 0 ) );
Bitmap aBmp( pVD->GetBitmap( Point(), aColorSize ) );
m_pColorSet->InsertItem(m_pColorSet->GetItemCount() + 1, Image(aBmp),
SvxResId(RID_SVXSTR_INVISIBLE));
}
bool SvxColorDockingWindow::Close()
{
SfxBoolItem aItem( SID_COLOR_CONTROL, false );
GetBindings().GetDispatcher()->ExecuteList(SID_COLOR_CONTROL,
SfxCallMode::ASYNCHRON | SfxCallMode::RECORD, { &aItem });
SfxDockingWindow::Close();
return true;
}
IMPL_LINK_NOARG(SvxColorDockingWindow, SelectHdl, ValueSet*, void)
{
SfxDispatcher* pDispatcher = GetBindings().GetDispatcher();
sal_uInt16 nPos = m_pColorSet->GetSelectedItemId();
Color aColor(m_pColorSet->GetItemColor(nPos));
OUString aStr(m_pColorSet->GetItemText(nPos));
// ID of 'invisible/none' entry, see SvxColorDockingWindow::FillValueSet
const sal_uInt16 nIdNone = m_pColorSet->GetItemCount();
if (m_pColorSet->IsLeftButton())
{
if ( gnLeftSlot == SID_ATTR_FILL_COLOR )
{
if (nPos == nIdNone)
{
XFillStyleItem aXFillStyleItem( drawing::FillStyle_NONE );
pDispatcher->ExecuteList(gnLeftSlot, SfxCallMode::RECORD,
{ &aXFillStyleItem });
}
else
{
bool bDone = false;
// If we have a DrawView and we are in TextEdit mode, then
// not the area color but the text color is assigned
SfxViewShell* pViewSh = SfxViewShell::Current();
if ( pViewSh )
{
SdrView* pView = pViewSh->GetDrawView();
if ( pView && pView->IsTextEdit() )
{
SvxColorItem aTextColorItem( aColor, SID_ATTR_CHAR_COLOR );
pDispatcher->ExecuteList(SID_ATTR_CHAR_COLOR,
SfxCallMode::RECORD, { &aTextColorItem });
bDone = true;
}
}
if ( !bDone )
{
XFillStyleItem aXFillStyleItem( drawing::FillStyle_SOLID );
XFillColorItem aXFillColorItem( aStr, aColor );
pDispatcher->ExecuteList(gnLeftSlot, SfxCallMode::RECORD,
{ &aXFillColorItem, &aXFillStyleItem });
}
}
}
else if (nPos != nIdNone)
{
SvxColorItem aLeftColorItem( aColor, gnLeftSlot );
pDispatcher->ExecuteList(gnLeftSlot, SfxCallMode::RECORD,
{ &aLeftColorItem });
}
}
else
{
if ( gnRightSlot == SID_ATTR_LINE_COLOR )
{
if (nPos == nIdNone)
{
XLineStyleItem aXLineStyleItem( drawing::LineStyle_NONE );
pDispatcher->ExecuteList(gnRightSlot, SfxCallMode::RECORD,
{ &aXLineStyleItem });
}
else
{
// If the LineStyle is invisible, it is set to SOLID
SfxViewShell* pViewSh = SfxViewShell::Current();
if ( pViewSh )
{
SdrView* pView = pViewSh->GetDrawView();
if ( pView )
{
SfxItemSet aAttrSet(pView->GetModel().GetItemPool());
pView->GetAttributes( aAttrSet );
if ( aAttrSet.GetItemState( XATTR_LINESTYLE ) != SfxItemState::INVALID )
{
drawing::LineStyle eXLS =
aAttrSet.Get( XATTR_LINESTYLE ).GetValue();
if ( eXLS == drawing::LineStyle_NONE )
{
XLineStyleItem aXLineStyleItem( drawing::LineStyle_SOLID );
pDispatcher->ExecuteList(gnRightSlot,
SfxCallMode::RECORD, { &aXLineStyleItem });
}
}
}
}
XLineColorItem aXLineColorItem( aStr, aColor );
pDispatcher->ExecuteList(gnRightSlot, SfxCallMode::RECORD,
{ &aXLineColorItem });
}
}
else if (nPos != nIdNone)
{
SvxColorItem aRightColorItem( aColor, gnRightSlot );
pDispatcher->ExecuteList(gnRightSlot, SfxCallMode::RECORD,
{ &aRightColorItem });
}
}
}
void SvxColorDockingWindow::GetFocus()
{
SfxDockingWindow::GetFocus();
if (m_pColorSet)
{
// Grab the focus to the color value set so that it can be controlled
// with the keyboard.
m_pColorSet->GrabFocus();
}
}
bool SvxColorDockingWindow::EventNotify( NotifyEvent& rNEvt )
{
bool bRet = false;
if( rNEvt.GetType() == NotifyEventType::KEYINPUT )
{
KeyEvent aKeyEvt = *rNEvt.GetKeyEvent();
sal_uInt16 nKeyCode = aKeyEvt.GetKeyCode().GetCode();
switch( nKeyCode )
{
case KEY_ESCAPE:
GrabFocusToDocument();
bRet = true;
break;
}
}
return bRet || SfxDockingWindow::EventNotify(rNEvt);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */