1
0
Fork 0
libreoffice/svx/source/tbxctrls/colrctrl.cxx
Daniel Baumann 8e63e14cf6
Adding upstream version 4:25.2.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-22 16:20:04 +02:00

424 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 <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);
SetAccessibleName(SvxResId(STR_COLORTABLE));
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 = ((1 == nPos)
? 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* _pBindings, SfxChildWindow* pCW, vcl::Window* _pParent)
: SfxDockingWindow(_pBindings, pCW, _pParent,
u"DockingColorWindow"_ustr, u"svx/ui/dockingcolorwindow.ui"_ustr)
, xColorSet(new SvxColorValueSet_docking(m_xBuilder->weld_scrolled_window(u"valuesetwin"_ustr, true)))
, xColorSetWin(new weld::CustomWeld(*m_xBuilder, u"valueset"_ustr, *xColorSet))
{
SetText(SvxResId(STR_COLORTABLE));
SetQuickHelpText(SvxResId(RID_SVXSTR_COLORBAR));
SetSizePixel(LogicToPixel(Size(150, 22), MapMode(MapUnit::MapAppFont)));
SetHelpId(HID_CTRL_COLOR);
xColorSet->SetSelectHdl( LINK( this, SvxColorDockingWindow, SelectHdl ) );
xColorSet->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;
if (_pBindings != nullptr)
{
SfxDispatcher* pDispatcher = _pBindings->GetDispatcher();
if (pDispatcher != nullptr)
{
SfxViewFrame* pFrame = pDispatcher->GetFrame();
if (pFrame != nullptr)
{
SfxViewShell* pViewShell = pFrame->GetViewShell();
if (pViewShell != nullptr)
pDocSh = pViewShell->GetObjectShell();
}
}
}
if ( pDocSh )
{
const SfxPoolItem* pItem = pDocSh->GetItem( SID_COLOR_TABLE );
if( pItem )
{
pColorList = static_cast<const SvxColorListItem*>(pItem)->GetColorList();
FillValueSet();
}
}
Size aItemSize = xColorSet->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 );
if (_pBindings != nullptr)
StartListening(*_pBindings, DuplicateHandling::Prevent);
}
SvxColorDockingWindow::~SvxColorDockingWindow()
{
disposeOnce();
}
void SvxColorDockingWindow::dispose()
{
EndListening( GetBindings() );
xColorSetWin.reset();
xColorSet.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
pColorList = pColorListItem->GetColorList();
FillValueSet();
}
}
}
void SvxColorDockingWindow::FillValueSet()
{
if( !pColorList.is() )
return;
xColorSet->Clear();
xColorSet->addEntriesForXColorList(*pColorList, 2);
// 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 ) );
BitmapEx aBmp( pVD->GetBitmapEx( Point(), aColorSize ) );
xColorSet->InsertItem( sal_uInt16(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 = xColorSet->GetSelectedItemId();
Color aColor( xColorSet->GetItemColor( nPos ) );
OUString aStr( xColorSet->GetItemText( nPos ) );
if (xColorSet->IsLeftButton())
{
if ( gnLeftSlot == SID_ATTR_FILL_COLOR )
{
if ( nPos == 1 ) // invisible
{
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 != 1 ) // invisible
{
SvxColorItem aLeftColorItem( aColor, gnLeftSlot );
pDispatcher->ExecuteList(gnLeftSlot, SfxCallMode::RECORD,
{ &aLeftColorItem });
}
}
else
{
if ( gnRightSlot == SID_ATTR_LINE_COLOR )
{
if( nPos == 1 ) // invisible
{
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 != 1 ) // invisible
{
SvxColorItem aRightColorItem( aColor, gnRightSlot );
pDispatcher->ExecuteList(gnRightSlot, SfxCallMode::RECORD,
{ &aRightColorItem });
}
}
}
void SvxColorDockingWindow::GetFocus()
{
SfxDockingWindow::GetFocus();
if (xColorSet)
{
// Grab the focus to the color value set so that it can be controlled
// with the keyboard.
xColorSet->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: */