1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/uno/XComponentContext.hpp>
21 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
22 #include <com/sun/star/ui/dialogs/XAsynchronousExecutableDialog.hpp>
23 #include <com/sun/star/beans/XPropertyAccess.hpp>
24 #include <com/sun/star/lang/XInitialization.hpp>
25 #include <com/sun/star/lang/XServiceInfo.hpp>
26 #include <com/sun/star/awt/XWindow.hpp>
28 #include <comphelper/propertyvalue.hxx>
29 #include <comphelper/compbase.hxx>
30 #include <cppuhelper/supportsservice.hxx>
31 #include <vcl/customweld.hxx>
32 #include <vcl/event.hxx>
33 #include <vcl/svapp.hxx>
34 #include <vcl/virdev.hxx>
35 #include <vcl/weld.hxx>
36 #include <sfx2/basedlgs.hxx>
37 #include <svx/hexcolorcontrol.hxx>
38 #include <basegfx/color/bcolortools.hxx>
40 #include <o3tl/typed_flags_set.hxx>
42 using namespace ::com::sun::star::uno
;
43 using namespace ::com::sun::star::lang
;
44 using namespace ::com::sun::star::ui::dialogs
;
45 using namespace ::com::sun::star::beans
;
46 using namespace ::basegfx
;
50 enum class UpdateFlags
65 template<> struct typed_flags
<UpdateFlags
> : is_typed_flags
<UpdateFlags
, 0x3f> {};
74 enum class ColorComponent
{
89 // color space conversion helpers
91 static void RGBtoHSV( double dR
, double dG
, double dB
, double& dH
, double& dS
, double& dV
)
93 BColor result
= basegfx::utils::rgb2hsv( BColor( dR
, dG
, dB
) );
100 static void HSVtoRGB(double dH
, double dS
, double dV
, double& dR
, double& dG
, double& dB
)
102 BColor result
= basegfx::utils::hsv2rgb( BColor( dH
, dS
, dV
) );
104 dR
= result
.getRed();
105 dG
= result
.getGreen();
106 dB
= result
.getBlue();
109 // CMYK values from 0 to 1
110 static void CMYKtoRGB( double fCyan
, double fMagenta
, double fYellow
, double fKey
, double& dR
, double& dG
, double& dB
)
112 fCyan
= (fCyan
* ( 1.0 - fKey
)) + fKey
;
113 fMagenta
= (fMagenta
* ( 1.0 - fKey
)) + fKey
;
114 fYellow
= (fYellow
* ( 1.0 - fKey
)) + fKey
;
116 dR
= std::clamp( 1.0 - fCyan
, 0.0, 1.0 );
117 dG
= std::clamp( 1.0 - fMagenta
, 0.0, 1.0 );
118 dB
= std::clamp( 1.0 - fYellow
, 0.0, 1.0 );
121 // CMY results from 0 to 1
122 static void RGBtoCMYK( double dR
, double dG
, double dB
, double& fCyan
, double& fMagenta
, double& fYellow
, double& fKey
)
128 //CMYK and CMY values from 0 to 1
130 if( fCyan
< fKey
) fKey
= fCyan
;
131 if( fMagenta
< fKey
) fKey
= fMagenta
;
132 if( fYellow
< fKey
) fKey
= fYellow
;
143 fCyan
= ( fCyan
- fKey
) / ( 1.0 - fKey
);
144 fMagenta
= ( fMagenta
- fKey
) / ( 1.0 - fKey
);
145 fYellow
= ( fYellow
- fKey
) / ( 1.0 - fKey
);
151 class ColorPreviewControl
: public weld::CustomWidgetController
156 virtual void Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&) override
;
158 ColorPreviewControl()
162 virtual void SetDrawingArea(weld::DrawingArea
* pDrawingArea
) override
164 CustomWidgetController::SetDrawingArea(pDrawingArea
);
165 pDrawingArea
->set_size_request(pDrawingArea
->get_approximate_digit_width() * 10,
166 pDrawingArea
->get_text_height() * 2);
169 void SetColor(const Color
& rCol
)
171 if (rCol
!= m_aColor
)
181 void ColorPreviewControl::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&)
183 rRenderContext
.SetFillColor(m_aColor
);
184 rRenderContext
.SetLineColor(m_aColor
);
185 rRenderContext
.DrawRect(tools::Rectangle(Point(0, 0), GetOutputSizePixel()));
190 enum ColorMode
{ HUE
, SATURATION
, BRIGHTNESS
, RED
, GREEN
, BLUE
};
194 const ColorMode DefaultMode
= HUE
;
198 class ColorFieldControl
: public weld::CustomWidgetController
202 : meMode( DefaultMode
)
203 , mnBaseValue(USHRT_MAX
)
206 , mbMouseCaptured(false)
210 virtual void SetDrawingArea(weld::DrawingArea
* pDrawingArea
) override
212 CustomWidgetController::SetDrawingArea(pDrawingArea
);
213 pDrawingArea
->set_size_request(pDrawingArea
->get_approximate_digit_width() * 40,
214 pDrawingArea
->get_text_height() * 10);
217 virtual ~ColorFieldControl() override
219 mxBitmap
.disposeAndClear();
222 virtual void Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& rRect
) override
;
223 virtual void Resize() override
;
224 virtual bool MouseButtonDown(const MouseEvent
& rMEvt
) override
;
225 virtual bool MouseMove(const MouseEvent
& rMEvt
) override
;
226 virtual bool MouseButtonUp(const MouseEvent
& rMEvt
) override
;
229 void ShowPosition( const Point
& rPos
, bool bUpdate
);
230 void UpdatePosition();
233 void SetValues(sal_uInt16 nBaseValue
, ColorMode eMode
, double x
, double y
);
234 double GetX() const { return mdX
;}
235 double GetY() const { return mdY
;}
237 void SetModifyHdl(const Link
<ColorFieldControl
&,void>& rLink
) { maModifyHdl
= rLink
; }
241 sal_uInt16 mnBaseValue
;
244 bool mbMouseCaptured
;
246 VclPtr
<VirtualDevice
> mxBitmap
;
247 Link
<ColorFieldControl
&,void> maModifyHdl
;
248 std::vector
<sal_uInt8
> maRGB_Horiz
;
249 std::vector
<sal_uInt16
> maGrad_Horiz
;
250 std::vector
<sal_uInt16
> maPercent_Horiz
;
251 std::vector
<sal_uInt8
> maRGB_Vert
;
252 std::vector
<sal_uInt16
> maPercent_Vert
;
257 void ColorFieldControl::UpdateBitmap()
259 const Size
aSize(GetOutputSizePixel());
261 if (mxBitmap
&& mxBitmap
->GetOutputSizePixel() != aSize
)
262 mxBitmap
.disposeAndClear();
264 const sal_Int32 nWidth
= aSize
.Width();
265 const sal_Int32 nHeight
= aSize
.Height();
267 if (nWidth
== 0 || nHeight
== 0)
272 mxBitmap
= VclPtr
<VirtualDevice
>::Create();
273 mxBitmap
->SetOutputSizePixel(aSize
);
275 maRGB_Horiz
.resize( nWidth
);
276 maGrad_Horiz
.resize( nWidth
);
277 maPercent_Horiz
.resize( nWidth
);
279 sal_uInt8
* pRGB
= maRGB_Horiz
.data();
280 sal_uInt16
* pGrad
= maGrad_Horiz
.data();
281 sal_uInt16
* pPercent
= maPercent_Horiz
.data();
283 for( sal_Int32 x
= 0; x
< nWidth
; x
++ )
285 *pRGB
++ = static_cast<sal_uInt8
>((x
* 256) / nWidth
);
286 *pGrad
++ = static_cast<sal_uInt16
>((x
* 359) / nWidth
);
287 *pPercent
++ = static_cast<sal_uInt16
>((x
* 100) / nWidth
);
290 maRGB_Vert
.resize(nHeight
);
291 maPercent_Vert
.resize(nHeight
);
293 pRGB
= maRGB_Vert
.data();
294 pPercent
= maPercent_Vert
.data();
296 sal_Int32 y
= nHeight
;
299 *pRGB
++ = static_cast<sal_uInt8
>((y
* 256) / nHeight
);
300 *pPercent
++ = static_cast<sal_uInt16
>((y
* 100) / nHeight
);
304 sal_uInt8
* pRGB_Horiz
= maRGB_Horiz
.data();
305 sal_uInt16
* pGrad_Horiz
= maGrad_Horiz
.data();
306 sal_uInt16
* pPercent_Horiz
= maPercent_Horiz
.data();
307 sal_uInt8
* pRGB_Vert
= maRGB_Vert
.data();
308 sal_uInt16
* pPercent_Vert
= maPercent_Vert
.data();
310 // this has been unlooped for performance reason, please do not merge back!
312 sal_uInt16 y
= nHeight
,x
;
319 sal_uInt16 nBri
= pPercent_Vert
[y
];
323 sal_uInt16 nSat
= pPercent_Horiz
[x
];
324 mxBitmap
->DrawPixel(Point(x
,y
), Color::HSBtoRGB(mnBaseValue
, nSat
, nBri
));
331 sal_uInt16 nBri
= pPercent_Vert
[y
];
335 sal_uInt16 nHue
= pGrad_Horiz
[x
];
336 mxBitmap
->DrawPixel(Point(x
,y
), Color::HSBtoRGB(nHue
, mnBaseValue
, nBri
));
343 sal_uInt16 nSat
= pPercent_Vert
[y
];
347 sal_uInt16 nHue
= pGrad_Horiz
[x
];
348 mxBitmap
->DrawPixel(Point(x
,y
), Color::HSBtoRGB(nHue
, nSat
, mnBaseValue
));
355 aBitmapColor
.SetRed(mnBaseValue
);
358 aBitmapColor
.SetGreen(pRGB_Vert
[y
]);
362 aBitmapColor
.SetBlue(pRGB_Horiz
[x
]);
363 mxBitmap
->DrawPixel(Point(x
,y
), aBitmapColor
);
371 aBitmapColor
.SetGreen(mnBaseValue
);
374 aBitmapColor
.SetRed(pRGB_Vert
[y
]);
378 aBitmapColor
.SetBlue(pRGB_Horiz
[x
]);
379 mxBitmap
->DrawPixel(Point(x
,y
), aBitmapColor
);
387 aBitmapColor
.SetBlue(mnBaseValue
);
390 aBitmapColor
.SetGreen(pRGB_Vert
[y
]);
394 aBitmapColor
.SetRed(pRGB_Horiz
[x
]);
395 mxBitmap
->DrawPixel(Point(x
,y
), aBitmapColor
);
403 constexpr int nCenterOffset
= 5;
405 void ColorFieldControl::ShowPosition( const Point
& rPos
, bool bUpdate
)
416 const Size
aSize(mxBitmap
->GetOutputSizePixel());
418 tools::Long nX
= rPos
.X();
419 tools::Long nY
= rPos
.Y();
422 else if (nX
>= aSize
.Width())
423 nX
= aSize
.Width() - 1;
427 else if (nY
>= aSize
.Height())
428 nY
= aSize
.Height() - 1;
430 Point aPos
= maPosition
;
431 maPosition
.setX( nX
- nCenterOffset
);
432 maPosition
.setY( nY
- nCenterOffset
);
433 Invalidate(tools::Rectangle(aPos
, Size(11, 11)));
434 Invalidate(tools::Rectangle(maPosition
, Size(11, 11)));
438 mdX
= double(nX
) / double(aSize
.Width() - 1.0);
439 mdY
= double(aSize
.Height() - 1.0 - nY
) / double(aSize
.Height() - 1.0);
443 bool ColorFieldControl::MouseButtonDown(const MouseEvent
& rMEvt
)
446 mbMouseCaptured
= true;
447 ShowPosition(rMEvt
.GetPosPixel(), true);
452 bool ColorFieldControl::MouseMove(const MouseEvent
& rMEvt
)
456 ShowPosition(rMEvt
.GetPosPixel(), true);
462 bool ColorFieldControl::MouseButtonUp(const MouseEvent
&)
465 mbMouseCaptured
= false;
469 void ColorFieldControl::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&)
477 Size
aSize(GetOutputSizePixel());
478 rRenderContext
.DrawOutDev(Point(0, 0), aSize
, Point(0, 0), aSize
, *mxBitmap
);
480 // draw circle around current color
481 Point
aPos(maPosition
.X() + nCenterOffset
, maPosition
.Y() + nCenterOffset
);
482 Color aColor
= mxBitmap
->GetPixel(aPos
);
484 rRenderContext
.SetLineColor(COL_WHITE
);
486 rRenderContext
.SetLineColor(COL_BLACK
);
488 rRenderContext
.SetFillColor();
489 rRenderContext
.DrawEllipse(::tools::Rectangle(maPosition
, Size(11, 11)));
492 void ColorFieldControl::Resize()
494 CustomWidgetController::Resize();
499 void ColorFieldControl::Modify()
501 maModifyHdl
.Call( *this );
504 void ColorFieldControl::SetValues(sal_uInt16 nBaseValue
, ColorMode eMode
, double x
, double y
)
506 bool bUpdateBitmap
= (mnBaseValue
!= nBaseValue
) || (meMode
!= eMode
);
507 if (!bUpdateBitmap
&& mdX
== x
&& mdY
== y
)
510 mnBaseValue
= nBaseValue
;
522 void ColorFieldControl::UpdatePosition()
524 Size
aSize(GetOutputSizePixel());
525 ShowPosition(Point(static_cast<tools::Long
>(mdX
* aSize
.Width()), static_cast<tools::Long
>((1.0 - mdY
) * aSize
.Height())), false);
530 class ColorSliderControl
: public weld::CustomWidgetController
533 ColorSliderControl();
534 virtual ~ColorSliderControl() override
;
536 virtual void SetDrawingArea(weld::DrawingArea
* pDrawingArea
) override
;
538 virtual bool MouseButtonDown(const MouseEvent
& rMEvt
) override
;
539 virtual bool MouseMove(const MouseEvent
& rMEvt
) override
;
540 virtual bool MouseButtonUp(const MouseEvent
& rMEvt
) override
;
541 virtual void Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&) override
;
542 virtual void Resize() override
;
545 void ChangePosition( tools::Long nY
);
548 void SetValue( const Color
& rColor
, ColorMode eMode
, double dValue
);
549 double GetValue() const { return mdValue
; }
551 void SetModifyHdl( const Link
<ColorSliderControl
&,void>& rLink
) { maModifyHdl
= rLink
; }
553 sal_Int16
GetLevel() const { return mnLevel
; }
556 Link
<ColorSliderControl
&,void> maModifyHdl
;
559 VclPtr
<VirtualDevice
> mxBitmap
;
566 ColorSliderControl::ColorSliderControl()
567 : meMode( DefaultMode
)
573 void ColorSliderControl::SetDrawingArea(weld::DrawingArea
* pDrawingArea
)
575 CustomWidgetController::SetDrawingArea(pDrawingArea
);
576 pDrawingArea
->set_size_request(pDrawingArea
->get_approximate_digit_width() * 3, -1);
579 ColorSliderControl::~ColorSliderControl()
581 mxBitmap
.disposeAndClear();
584 void ColorSliderControl::UpdateBitmap()
586 Size
aSize(1, GetOutputSizePixel().Height());
588 if (mxBitmap
&& mxBitmap
->GetOutputSizePixel() != aSize
)
589 mxBitmap
.disposeAndClear();
593 mxBitmap
= VclPtr
<VirtualDevice
>::Create();
594 mxBitmap
->SetOutputSizePixel(aSize
);
597 const tools::Long nY
= aSize
.Height() - 1;
599 Color
aBitmapColor(maColor
);
601 sal_uInt16 nHue
, nSat
, nBri
;
602 maColor
.RGBtoHSB(nHue
, nSat
, nBri
);
604 // this has been unlooped for performance reason, please do not merge back!
611 for (tools::Long y
= 0; y
<= nY
; y
++)
613 nHue
= static_cast<sal_uInt16
>((359 * y
) / nY
);
614 mxBitmap
->DrawPixel(Point(0, nY
- y
), Color::HSBtoRGB(nHue
, nSat
, nBri
));
619 nBri
= std::max(sal_uInt16(32), nBri
);
620 for (tools::Long y
= 0; y
<= nY
; y
++)
622 nSat
= static_cast<sal_uInt16
>((100 * y
) / nY
);
623 mxBitmap
->DrawPixel(Point(0, nY
- y
), Color::HSBtoRGB(nHue
, nSat
, nBri
));
628 for (tools::Long y
= 0; y
<= nY
; y
++)
630 nBri
= static_cast<sal_uInt16
>((100 * y
) / nY
);
631 mxBitmap
->DrawPixel(Point(0, nY
- y
), Color::HSBtoRGB(nHue
, nSat
, nBri
));
636 for (tools::Long y
= 0; y
<= nY
; y
++)
638 aBitmapColor
.SetRed(sal_uInt8((tools::Long(255) * y
) / nY
));
639 mxBitmap
->DrawPixel(Point(0, nY
- y
), aBitmapColor
);
644 for (tools::Long y
= 0; y
<= nY
; y
++)
646 aBitmapColor
.SetGreen(sal_uInt8((tools::Long(255) * y
) / nY
));
647 mxBitmap
->DrawPixel(Point(0, nY
- y
), aBitmapColor
);
652 for (tools::Long y
= 0; y
<= nY
; y
++)
654 aBitmapColor
.SetBlue(sal_uInt8((tools::Long(255) * y
) / nY
));
655 mxBitmap
->DrawPixel(Point(0, nY
- y
), aBitmapColor
);
661 void ColorSliderControl::ChangePosition(tools::Long nY
)
663 const tools::Long nHeight
= GetOutputSizePixel().Height() - 1;
667 else if (nY
> nHeight
)
671 mdValue
= double(nHeight
- nY
) / double(nHeight
);
674 bool ColorSliderControl::MouseButtonDown(const MouseEvent
& rMEvt
)
677 ChangePosition(rMEvt
.GetPosPixel().Y());
682 bool ColorSliderControl::MouseMove(const MouseEvent
& rMEvt
)
684 if (IsMouseCaptured())
686 ChangePosition(rMEvt
.GetPosPixel().Y());
692 bool ColorSliderControl::MouseButtonUp(const MouseEvent
&)
698 void ColorSliderControl::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&)
703 const Size
aSize(GetOutputSizePixel());
706 int x
= aSize
.Width();
709 rRenderContext
.DrawOutDev(aPos
, aSize
, Point(0,0), aSize
, *mxBitmap
);
714 void ColorSliderControl::Resize()
716 CustomWidgetController::Resize();
720 void ColorSliderControl::Modify()
722 maModifyHdl
.Call(*this);
725 void ColorSliderControl::SetValue(const Color
& rColor
, ColorMode eMode
, double dValue
)
727 bool bUpdateBitmap
= (rColor
!= maColor
) || (eMode
!= meMode
);
728 if( bUpdateBitmap
|| (mdValue
!= dValue
))
732 mnLevel
= static_cast<sal_Int16
>((1.0-dValue
) * GetOutputSizePixel().Height());
742 class ColorPickerDialog
: public SfxDialogController
745 ColorFieldControl m_aColorField
;
746 ColorSliderControl m_aColorSlider
;
747 ColorPreviewControl m_aColorPreview
;
748 ColorPreviewControl m_aColorPrevious
;
750 std::unique_ptr
<weld::CustomWeld
> m_xColorField
;
751 std::unique_ptr
<weld::CustomWeld
> m_xColorSlider
;
752 std::unique_ptr
<weld::CustomWeld
> m_xColorPreview
;
753 std::unique_ptr
<weld::CustomWeld
> m_xColorPrevious
;
755 std::unique_ptr
<weld::Widget
> m_xFISliderLeft
;
756 std::unique_ptr
<weld::Widget
> m_xFISliderRight
;
757 std::unique_ptr
<weld::RadioButton
> m_xRBRed
;
758 std::unique_ptr
<weld::RadioButton
> m_xRBGreen
;
759 std::unique_ptr
<weld::RadioButton
> m_xRBBlue
;
760 std::unique_ptr
<weld::RadioButton
> m_xRBHue
;
761 std::unique_ptr
<weld::RadioButton
> m_xRBSaturation
;
762 std::unique_ptr
<weld::RadioButton
> m_xRBBrightness
;
764 std::unique_ptr
<weld::SpinButton
> m_xMFRed
;
765 std::unique_ptr
<weld::SpinButton
> m_xMFGreen
;
766 std::unique_ptr
<weld::SpinButton
> m_xMFBlue
;
767 std::unique_ptr
<weld::HexColorControl
> m_xEDHex
;
769 std::unique_ptr
<weld::MetricSpinButton
> m_xMFHue
;
770 std::unique_ptr
<weld::MetricSpinButton
> m_xMFSaturation
;
771 std::unique_ptr
<weld::MetricSpinButton
> m_xMFBrightness
;
773 std::unique_ptr
<weld::MetricSpinButton
> m_xMFCyan
;
774 std::unique_ptr
<weld::MetricSpinButton
> m_xMFMagenta
;
775 std::unique_ptr
<weld::MetricSpinButton
> m_xMFYellow
;
776 std::unique_ptr
<weld::MetricSpinButton
> m_xMFKey
;
779 ColorPickerDialog(weld::Window
* pParent
, Color nColor
, sal_Int16 nMode
);
781 void update_color(UpdateFlags n
= UpdateFlags::All
);
783 DECL_LINK(ColorFieldControlModifydl
, ColorFieldControl
&, void);
784 DECL_LINK(ColorSliderControlModifyHdl
, ColorSliderControl
&, void);
785 DECL_LINK(ColorModifyMetricHdl
, weld::MetricSpinButton
&, void);
786 DECL_LINK(ColorModifySpinHdl
, weld::SpinButton
&, void);
787 DECL_LINK(ColorModifyEditHdl
, weld::Entry
&, void);
788 DECL_LINK(ModeModifyHdl
, weld::Toggleable
&, void);
790 Color
GetColor() const;
792 void setColorComponent(ColorComponent nComp
, double dValue
);
797 double mdRed
, mdGreen
, mdBlue
;
798 double mdHue
, mdSat
, mdBri
;
799 double mdCyan
, mdMagenta
, mdYellow
, mdKey
;
804 ColorPickerDialog::ColorPickerDialog(weld::Window
* pParent
, Color nColor
, sal_Int16 nDialogMode
)
805 : SfxDialogController(pParent
, u
"cui/ui/colorpickerdialog.ui"_ustr
, u
"ColorPicker"_ustr
)
806 , m_xColorField(new weld::CustomWeld(*m_xBuilder
, u
"colorField"_ustr
, m_aColorField
))
807 , m_xColorSlider(new weld::CustomWeld(*m_xBuilder
, u
"colorSlider"_ustr
, m_aColorSlider
))
808 , m_xColorPreview(new weld::CustomWeld(*m_xBuilder
, u
"preview"_ustr
, m_aColorPreview
))
809 , m_xColorPrevious(new weld::CustomWeld(*m_xBuilder
, u
"previous"_ustr
, m_aColorPrevious
))
810 , m_xFISliderLeft(m_xBuilder
->weld_widget(u
"leftImage"_ustr
))
811 , m_xFISliderRight(m_xBuilder
->weld_widget(u
"rightImage"_ustr
))
812 , m_xRBRed(m_xBuilder
->weld_radio_button(u
"redRadiobutton"_ustr
))
813 , m_xRBGreen(m_xBuilder
->weld_radio_button(u
"greenRadiobutton"_ustr
))
814 , m_xRBBlue(m_xBuilder
->weld_radio_button(u
"blueRadiobutton"_ustr
))
815 , m_xRBHue(m_xBuilder
->weld_radio_button(u
"hueRadiobutton"_ustr
))
816 , m_xRBSaturation(m_xBuilder
->weld_radio_button(u
"satRadiobutton"_ustr
))
817 , m_xRBBrightness(m_xBuilder
->weld_radio_button(u
"brightRadiobutton"_ustr
))
818 , m_xMFRed(m_xBuilder
->weld_spin_button(u
"redSpinbutton"_ustr
))
819 , m_xMFGreen(m_xBuilder
->weld_spin_button(u
"greenSpinbutton"_ustr
))
820 , m_xMFBlue(m_xBuilder
->weld_spin_button(u
"blueSpinbutton"_ustr
))
821 , m_xEDHex(new weld::HexColorControl(m_xBuilder
->weld_entry(u
"hexEntry"_ustr
)))
822 , m_xMFHue(m_xBuilder
->weld_metric_spin_button(u
"hueSpinbutton"_ustr
, FieldUnit::DEGREE
))
823 , m_xMFSaturation(m_xBuilder
->weld_metric_spin_button(u
"satSpinbutton"_ustr
, FieldUnit::PERCENT
))
824 , m_xMFBrightness(m_xBuilder
->weld_metric_spin_button(u
"brightSpinbutton"_ustr
, FieldUnit::PERCENT
))
825 , m_xMFCyan(m_xBuilder
->weld_metric_spin_button(u
"cyanSpinbutton"_ustr
, FieldUnit::PERCENT
))
826 , m_xMFMagenta(m_xBuilder
->weld_metric_spin_button(u
"magSpinbutton"_ustr
, FieldUnit::PERCENT
))
827 , m_xMFYellow(m_xBuilder
->weld_metric_spin_button(u
"yellowSpinbutton"_ustr
, FieldUnit::PERCENT
))
828 , m_xMFKey(m_xBuilder
->weld_metric_spin_button(u
"keySpinbutton"_ustr
, FieldUnit::PERCENT
))
829 , meMode( DefaultMode
)
831 m_aColorField
.SetModifyHdl( LINK( this, ColorPickerDialog
, ColorFieldControlModifydl
) );
832 m_aColorSlider
.SetModifyHdl( LINK( this, ColorPickerDialog
, ColorSliderControlModifyHdl
) );
834 int nMargin
= (m_xFISliderLeft
->get_preferred_size().Height() + 1) / 2;
835 m_xColorSlider
->set_margin_top(nMargin
);
836 m_xColorSlider
->set_margin_bottom(nMargin
);
838 Link
<weld::MetricSpinButton
&,void> aLink3( LINK( this, ColorPickerDialog
, ColorModifyMetricHdl
) );
839 m_xMFCyan
->connect_value_changed( aLink3
);
840 m_xMFMagenta
->connect_value_changed( aLink3
);
841 m_xMFYellow
->connect_value_changed( aLink3
);
842 m_xMFKey
->connect_value_changed( aLink3
);
844 m_xMFHue
->connect_value_changed( aLink3
);
845 m_xMFSaturation
->connect_value_changed( aLink3
);
846 m_xMFBrightness
->connect_value_changed( aLink3
);
848 Link
<weld::SpinButton
&,void> aLink4(LINK(this, ColorPickerDialog
, ColorModifySpinHdl
));
849 m_xMFRed
->connect_value_changed(aLink4
);
850 m_xMFGreen
->connect_value_changed(aLink4
);
851 m_xMFBlue
->connect_value_changed(aLink4
);
853 m_xEDHex
->connect_changed(LINK(this, ColorPickerDialog
, ColorModifyEditHdl
));
855 Link
<weld::Toggleable
&,void> aLink2
= LINK( this, ColorPickerDialog
, ModeModifyHdl
);
856 m_xRBRed
->connect_toggled( aLink2
);
857 m_xRBGreen
->connect_toggled( aLink2
);
858 m_xRBBlue
->connect_toggled( aLink2
);
859 m_xRBHue
->connect_toggled( aLink2
);
860 m_xRBSaturation
->connect_toggled( aLink2
);
861 m_xRBBrightness
->connect_toggled( aLink2
);
863 Color
aColor(nColor
);
866 if (nDialogMode
== 2)
868 m_aColorPrevious
.SetColor(aColor
);
869 m_xColorPrevious
->show();
872 mdRed
= static_cast<double>(aColor
.GetRed()) / 255.0;
873 mdGreen
= static_cast<double>(aColor
.GetGreen()) / 255.0;
874 mdBlue
= static_cast<double>(aColor
.GetBlue()) / 255.0;
876 RGBtoHSV( mdRed
, mdGreen
, mdBlue
, mdHue
, mdSat
, mdBri
);
877 RGBtoCMYK( mdRed
, mdGreen
, mdBlue
, mdCyan
, mdMagenta
, mdYellow
, mdKey
);
882 static int toInt( double dValue
, double dRange
)
884 return static_cast< int >( std::floor((dValue
* dRange
) + 0.5 ) );
887 Color
ColorPickerDialog::GetColor() const
889 return Color( toInt(mdRed
,255.0), toInt(mdGreen
,255.0), toInt(mdBlue
,255.0) );
892 void ColorPickerDialog::update_color( UpdateFlags n
)
894 sal_uInt8 nRed
= toInt(mdRed
,255.0);
895 sal_uInt8 nGreen
= toInt(mdGreen
,255.0);
896 sal_uInt8 nBlue
= toInt(mdBlue
,255.0);
898 sal_uInt16 nHue
= toInt(mdHue
, 1.0);
899 sal_uInt16 nSat
= toInt(mdSat
, 100.0);
900 sal_uInt16 nBri
= toInt(mdBri
, 100.0);
902 if (n
& UpdateFlags::RGB
) // update RGB
904 m_xMFRed
->set_value(nRed
);
905 m_xMFGreen
->set_value(nGreen
);
906 m_xMFBlue
->set_value(nBlue
);
909 if (n
& UpdateFlags::CMYK
) // update CMYK
911 m_xMFCyan
->set_value(toInt(mdCyan
, 100.0), FieldUnit::PERCENT
);
912 m_xMFMagenta
->set_value(toInt(mdMagenta
, 100.0), FieldUnit::PERCENT
);
913 m_xMFYellow
->set_value(toInt(mdYellow
, 100.0), FieldUnit::PERCENT
);
914 m_xMFKey
->set_value(toInt(mdKey
, 100.0), FieldUnit::PERCENT
);
917 if (n
& UpdateFlags::HSB
) // update HSB
919 m_xMFHue
->set_value(nHue
, FieldUnit::DEGREE
);
920 m_xMFSaturation
->set_value(nSat
, FieldUnit::PERCENT
);
921 m_xMFBrightness
->set_value(nBri
, FieldUnit::PERCENT
);
924 if (n
& UpdateFlags::ColorChooser
) // update Color Chooser 1
929 m_aColorField
.SetValues(nHue
, meMode
, mdSat
, mdBri
);
932 m_aColorField
.SetValues(nSat
, meMode
, mdHue
/ 360.0, mdBri
);
935 m_aColorField
.SetValues(nBri
, meMode
, mdHue
/ 360.0, mdSat
);
938 m_aColorField
.SetValues(nRed
, meMode
, mdBlue
, mdGreen
);
941 m_aColorField
.SetValues(nGreen
, meMode
, mdBlue
, mdRed
);
944 m_aColorField
.SetValues(nBlue
, meMode
, mdRed
, mdGreen
);
949 Color
aColor(nRed
, nGreen
, nBlue
);
951 if (n
& UpdateFlags::ColorSlider
) // update Color Chooser 2
956 m_aColorSlider
.SetValue(aColor
, meMode
, mdHue
/ 360.0);
959 m_aColorSlider
.SetValue(aColor
, meMode
, mdSat
);
962 m_aColorSlider
.SetValue(aColor
, meMode
, mdBri
);
965 m_aColorSlider
.SetValue(aColor
, meMode
, mdRed
);
968 m_aColorSlider
.SetValue(aColor
, meMode
, mdGreen
);
971 m_aColorSlider
.SetValue(aColor
, meMode
, mdBlue
);
976 if (n
& UpdateFlags::Hex
) // update hex
978 m_xFISliderLeft
->set_margin_top(m_aColorSlider
.GetLevel());
979 m_xFISliderRight
->set_margin_top(m_aColorSlider
.GetLevel());
980 m_xEDHex
->SetColor(aColor
);
982 m_aColorPreview
.SetColor(aColor
);
985 IMPL_LINK_NOARG(ColorPickerDialog
, ColorFieldControlModifydl
, ColorFieldControl
&, void)
987 double x
= m_aColorField
.GetX();
988 double y
= m_aColorField
.GetY();
994 setColorComponent( ColorComponent::Brightness
, y
);
998 setColorComponent( ColorComponent::Brightness
, y
);
1002 setColorComponent( ColorComponent::Saturation
, y
);
1006 setColorComponent( ColorComponent::Green
, y
);
1010 setColorComponent( ColorComponent::Red
, y
);
1014 setColorComponent( ColorComponent::Green
, y
);
1018 update_color(UpdateFlags::All
& ~UpdateFlags::ColorChooser
);
1021 IMPL_LINK_NOARG(ColorPickerDialog
, ColorSliderControlModifyHdl
, ColorSliderControl
&, void)
1023 double dValue
= m_aColorSlider
.GetValue();
1027 setColorComponent( ColorComponent::Hue
, dValue
* 360.0 );
1030 setColorComponent( ColorComponent::Saturation
, dValue
);
1033 setColorComponent( ColorComponent::Brightness
, dValue
);
1036 setColorComponent( ColorComponent::Red
, dValue
);
1039 setColorComponent( ColorComponent::Green
, dValue
);
1042 setColorComponent( ColorComponent::Blue
, dValue
);
1046 update_color(UpdateFlags::All
& ~UpdateFlags::ColorSlider
);
1049 IMPL_LINK(ColorPickerDialog
, ColorModifyMetricHdl
, weld::MetricSpinButton
&, rEdit
, void)
1051 UpdateFlags n
= UpdateFlags::NONE
;
1053 if (&rEdit
== m_xMFHue
.get())
1055 setColorComponent( ColorComponent::Hue
, static_cast<double>(m_xMFHue
->get_value(FieldUnit::DEGREE
)) );
1056 n
= UpdateFlags::All
& ~UpdateFlags::HSB
;
1058 else if (&rEdit
== m_xMFSaturation
.get())
1060 setColorComponent( ColorComponent::Saturation
, static_cast<double>(m_xMFSaturation
->get_value(FieldUnit::PERCENT
)) / 100.0 );
1061 n
= UpdateFlags::All
& ~UpdateFlags::HSB
;
1063 else if (&rEdit
== m_xMFBrightness
.get())
1065 setColorComponent( ColorComponent::Brightness
, static_cast<double>(m_xMFBrightness
->get_value(FieldUnit::PERCENT
)) / 100.0 );
1066 n
= UpdateFlags::All
& ~UpdateFlags::HSB
;
1068 else if (&rEdit
== m_xMFCyan
.get())
1070 setColorComponent( ColorComponent::Cyan
, static_cast<double>(m_xMFCyan
->get_value(FieldUnit::PERCENT
)) / 100.0 );
1071 n
= UpdateFlags::All
& ~UpdateFlags::CMYK
;
1073 else if (&rEdit
== m_xMFMagenta
.get())
1075 setColorComponent( ColorComponent::Magenta
, static_cast<double>(m_xMFMagenta
->get_value(FieldUnit::PERCENT
)) / 100.0 );
1076 n
= UpdateFlags::All
& ~UpdateFlags::CMYK
;
1078 else if (&rEdit
== m_xMFYellow
.get())
1080 setColorComponent( ColorComponent::Yellow
, static_cast<double>(m_xMFYellow
->get_value(FieldUnit::PERCENT
)) / 100.0 );
1081 n
= UpdateFlags::All
& ~UpdateFlags::CMYK
;
1083 else if (&rEdit
== m_xMFKey
.get())
1085 setColorComponent( ColorComponent::Key
, static_cast<double>(m_xMFKey
->get_value(FieldUnit::PERCENT
)) / 100.0 );
1086 n
= UpdateFlags::All
& ~UpdateFlags::CMYK
;
1089 if (n
!= UpdateFlags::NONE
)
1093 IMPL_LINK_NOARG(ColorPickerDialog
, ColorModifyEditHdl
, weld::Entry
&, void)
1095 UpdateFlags n
= UpdateFlags::NONE
;
1097 Color aColor
= m_xEDHex
->GetColor();
1099 if (aColor
!= COL_AUTO
&& aColor
!= GetColor())
1101 mdRed
= static_cast<double>(aColor
.GetRed()) / 255.0;
1102 mdGreen
= static_cast<double>(aColor
.GetGreen()) / 255.0;
1103 mdBlue
= static_cast<double>(aColor
.GetBlue()) / 255.0;
1105 RGBtoHSV( mdRed
, mdGreen
, mdBlue
, mdHue
, mdSat
, mdBri
);
1106 RGBtoCMYK( mdRed
, mdGreen
, mdBlue
, mdCyan
, mdMagenta
, mdYellow
, mdKey
);
1107 n
= UpdateFlags::All
& ~UpdateFlags::Hex
;
1110 if (n
!= UpdateFlags::NONE
)
1114 IMPL_LINK(ColorPickerDialog
, ColorModifySpinHdl
, weld::SpinButton
&, rEdit
, void)
1116 UpdateFlags n
= UpdateFlags::NONE
;
1118 if (&rEdit
== m_xMFRed
.get())
1120 setColorComponent( ColorComponent::Red
, static_cast<double>(m_xMFRed
->get_value()) / 255.0 );
1121 n
= UpdateFlags::All
& ~UpdateFlags::RGB
;
1123 else if (&rEdit
== m_xMFGreen
.get())
1125 setColorComponent( ColorComponent::Green
, static_cast<double>(m_xMFGreen
->get_value()) / 255.0 );
1126 n
= UpdateFlags::All
& ~UpdateFlags::RGB
;
1128 else if (&rEdit
== m_xMFBlue
.get())
1130 setColorComponent( ColorComponent::Blue
, static_cast<double>(m_xMFBlue
->get_value()) / 255.0 );
1131 n
= UpdateFlags::All
& ~UpdateFlags::RGB
;
1134 if (n
!= UpdateFlags::NONE
)
1139 IMPL_LINK_NOARG(ColorPickerDialog
, ModeModifyHdl
, weld::Toggleable
&, void)
1141 ColorMode eMode
= HUE
;
1143 if (m_xRBRed
->get_active())
1147 else if (m_xRBGreen
->get_active())
1151 else if (m_xRBBlue
->get_active())
1155 else if (m_xRBSaturation
->get_active())
1159 else if (m_xRBBrightness
->get_active())
1164 if (meMode
!= eMode
)
1167 update_color(UpdateFlags::ColorChooser
| UpdateFlags::ColorSlider
);
1171 void ColorPickerDialog::setColorComponent( ColorComponent nComp
, double dValue
)
1175 case ColorComponent::Red
:
1178 case ColorComponent::Green
:
1181 case ColorComponent::Blue
:
1184 case ColorComponent::Hue
:
1187 case ColorComponent::Saturation
:
1190 case ColorComponent::Brightness
:
1193 case ColorComponent::Cyan
:
1196 case ColorComponent::Yellow
:
1199 case ColorComponent::Magenta
:
1202 case ColorComponent::Key
:
1207 if (nComp
== ColorComponent::Red
|| nComp
== ColorComponent::Green
|| nComp
== ColorComponent::Blue
)
1209 RGBtoHSV( mdRed
, mdGreen
, mdBlue
, mdHue
, mdSat
, mdBri
);
1210 RGBtoCMYK( mdRed
, mdGreen
, mdBlue
, mdCyan
, mdMagenta
, mdYellow
, mdKey
);
1212 else if (nComp
== ColorComponent::Hue
|| nComp
== ColorComponent::Saturation
|| nComp
== ColorComponent::Brightness
)
1214 HSVtoRGB( mdHue
, mdSat
, mdBri
, mdRed
, mdGreen
, mdBlue
);
1215 RGBtoCMYK( mdRed
, mdGreen
, mdBlue
, mdCyan
, mdMagenta
, mdYellow
, mdKey
);
1219 CMYKtoRGB( mdCyan
, mdMagenta
, mdYellow
, mdKey
, mdRed
, mdGreen
, mdBlue
);
1220 RGBtoHSV( mdRed
, mdGreen
, mdBlue
, mdHue
, mdSat
, mdBri
);
1224 typedef ::comphelper::WeakComponentImplHelper
< XServiceInfo
, XExecutableDialog
, XAsynchronousExecutableDialog
, XInitialization
, XPropertyAccess
> ColorPickerBase
;
1228 class ColorPicker
: public ColorPickerBase
1231 explicit ColorPicker();
1234 virtual void SAL_CALL
initialize( const Sequence
< Any
>& aArguments
) override
;
1237 virtual OUString SAL_CALL
getImplementationName( ) override
;
1238 virtual sal_Bool SAL_CALL
supportsService( const OUString
& ServiceName
) override
;
1239 virtual Sequence
< OUString
> SAL_CALL
getSupportedServiceNames( ) override
;
1242 virtual Sequence
< PropertyValue
> SAL_CALL
getPropertyValues( ) override
;
1243 virtual void SAL_CALL
setPropertyValues( const Sequence
< PropertyValue
>& aProps
) override
;
1245 // XExecutableDialog
1246 virtual void SAL_CALL
setTitle( const OUString
& aTitle
) override
;
1247 virtual sal_Int16 SAL_CALL
execute( ) override
;
1249 // XAsynchronousExecutableDialog
1250 virtual void SAL_CALL
setDialogTitle( const OUString
& aTitle
) override
;
1251 virtual void SAL_CALL
startExecuteModal( const css::uno::Reference
< css::ui::dialogs::XDialogClosedListener
>& xListener
) override
;
1256 Reference
<css::awt::XWindow
> mxParent
;
1261 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
1262 com_sun_star_cui_ColorPicker_get_implementation(
1263 css::uno::XComponentContext
*, css::uno::Sequence
<css::uno::Any
> const&)
1265 return cppu::acquire( new ColorPicker
);
1269 constexpr OUString
gsColorKey( u
"Color"_ustr
);
1270 constexpr OUStringLiteral
gsModeKey( u
"Mode" );
1272 ColorPicker::ColorPicker()
1279 void SAL_CALL
ColorPicker::initialize( const Sequence
< Any
>& aArguments
)
1281 if( aArguments
.getLength() == 1 )
1283 aArguments
[0] >>= mxParent
;
1288 OUString SAL_CALL
ColorPicker::getImplementationName( )
1290 return u
"com.sun.star.cui.ColorPicker"_ustr
;
1293 sal_Bool SAL_CALL
ColorPicker::supportsService( const OUString
& sServiceName
)
1295 return cppu::supportsService(this, sServiceName
);
1298 Sequence
< OUString
> SAL_CALL
ColorPicker::getSupportedServiceNames( )
1300 return { u
"com.sun.star.ui.dialogs.ColorPicker"_ustr
,
1301 u
"com.sun.star.ui.dialogs.AsynchronousColorPicker"_ustr
};
1305 Sequence
< PropertyValue
> SAL_CALL
ColorPicker::getPropertyValues( )
1307 Sequence
< PropertyValue
> props
{ comphelper::makePropertyValue(gsColorKey
, mnColor
) };
1311 void SAL_CALL
ColorPicker::setPropertyValues( const Sequence
< PropertyValue
>& aProps
)
1313 for ( const PropertyValue
& rProp
: aProps
)
1315 if( rProp
.Name
== gsColorKey
)
1317 rProp
.Value
>>= mnColor
;
1319 else if( rProp
.Name
== gsModeKey
)
1321 rProp
.Value
>>= mnMode
;
1326 // XExecutableDialog
1327 void SAL_CALL
ColorPicker::setTitle( const OUString
& )
1331 sal_Int16 SAL_CALL
ColorPicker::execute()
1333 std::unique_ptr
<ColorPickerDialog
> xDlg(new ColorPickerDialog(Application::GetFrameWeld(mxParent
), mnColor
, mnMode
));
1334 sal_Int16 ret
= xDlg
->run();
1336 mnColor
= xDlg
->GetColor();
1340 // XAsynchronousExecutableDialog
1341 void SAL_CALL
ColorPicker::setDialogTitle( const OUString
& )
1345 void SAL_CALL
ColorPicker::startExecuteModal( const css::uno::Reference
< css::ui::dialogs::XDialogClosedListener
>& xListener
)
1347 std::shared_ptr
<ColorPickerDialog
> xDlg
= std::make_shared
<ColorPickerDialog
>(Application::GetFrameWeld(mxParent
), mnColor
, mnMode
);
1348 rtl::Reference
<ColorPicker
> xThis(this);
1349 weld::DialogController::runAsync(xDlg
, [xThis
=std::move(xThis
), xDlg
, xListener
] (sal_Int32 nResult
) {
1351 xThis
->mnColor
= xDlg
->GetColor();
1353 sal_Int16 nRet
= static_cast<sal_Int16
>(nResult
);
1354 css::ui::dialogs::DialogClosedEvent
aEvent( *xThis
, nRet
);
1355 xListener
->dialogClosed( aEvent
);
1361 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */