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/beans/XPropertyAccess.hpp>
23 #include <com/sun/star/lang/XInitialization.hpp>
24 #include <com/sun/star/lang/XServiceInfo.hpp>
25 #include <com/sun/star/awt/XWindow.hpp>
26 #include <cppuhelper/compbase.hxx>
27 #include <cppuhelper/supportsservice.hxx>
28 #include <cppuhelper/basemutex.hxx>
29 #include <vcl/customweld.hxx>
30 #include <vcl/event.hxx>
31 #include <vcl/svapp.hxx>
32 #include <vcl/virdev.hxx>
33 #include <vcl/weld.hxx>
34 #include <svx/hexcolorcontrol.hxx>
35 #include <basegfx/color/bcolortools.hxx>
36 #include <colorpicker.hxx>
38 #include <o3tl/typed_flags_set.hxx>
40 using namespace ::com::sun::star::uno
;
41 using namespace ::com::sun::star::lang
;
42 using namespace ::com::sun::star::ui::dialogs
;
43 using namespace ::com::sun::star::beans
;
44 using namespace ::basegfx
;
46 enum class UpdateFlags
58 template<> struct typed_flags
<UpdateFlags
> : is_typed_flags
<UpdateFlags
, 0x3f> {};
65 enum class ColorComponent
{
79 // color space conversion helpers
81 static void RGBtoHSV( double dR
, double dG
, double dB
, double& dH
, double& dS
, double& dV
)
83 BColor result
= basegfx::utils::rgb2hsv( BColor( dR
, dG
, dB
) );
90 static void HSVtoRGB(double dH
, double dS
, double dV
, double& dR
, double& dG
, double& dB
)
92 BColor result
= basegfx::utils::hsv2rgb( BColor( dH
, dS
, dV
) );
95 dG
= result
.getGreen();
96 dB
= result
.getBlue();
99 // CMYK values from 0 to 1
100 static void CMYKtoRGB( double fCyan
, double fMagenta
, double fYellow
, double fKey
, double& dR
, double& dG
, double& dB
)
102 fCyan
= (fCyan
* ( 1.0 - fKey
)) + fKey
;
103 fMagenta
= (fMagenta
* ( 1.0 - fKey
)) + fKey
;
104 fYellow
= (fYellow
* ( 1.0 - fKey
)) + fKey
;
106 dR
= std::max( std::min( ( 1.0 - fCyan
), 1.0), 0.0 );
107 dG
= std::max( std::min( ( 1.0 - fMagenta
), 1.0), 0.0 );
108 dB
= std::max( std::min( ( 1.0 - fYellow
), 1.0), 0.0 );
111 // CMY results from 0 to 1
112 static void RGBtoCMYK( double dR
, double dG
, double dB
, double& fCyan
, double& fMagenta
, double& fYellow
, double& fKey
)
118 //CMYK and CMY values from 0 to 1
120 if( fCyan
< fKey
) fKey
= fCyan
;
121 if( fMagenta
< fKey
) fKey
= fMagenta
;
122 if( fYellow
< fKey
) fKey
= fYellow
;
133 fCyan
= ( fCyan
- fKey
) / ( 1.0 - fKey
);
134 fMagenta
= ( fMagenta
- fKey
) / ( 1.0 - fKey
);
135 fYellow
= ( fYellow
- fKey
) / ( 1.0 - fKey
);
139 class ColorPreviewControl
: public weld::CustomWidgetController
144 virtual void Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&) override
;
146 ColorPreviewControl()
150 virtual void SetDrawingArea(weld::DrawingArea
* pDrawingArea
) override
152 CustomWidgetController::SetDrawingArea(pDrawingArea
);
153 pDrawingArea
->set_size_request(pDrawingArea
->get_approximate_digit_width() * 10,
154 pDrawingArea
->get_text_height() * 2);
157 void SetColor(const Color
& rCol
)
159 if (rCol
!= m_aColor
)
167 void ColorPreviewControl::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&)
169 rRenderContext
.SetFillColor(m_aColor
);
170 rRenderContext
.SetLineColor(m_aColor
);
171 rRenderContext
.DrawRect(tools::Rectangle(Point(0, 0), GetOutputSizePixel()));
174 enum ColorMode
{ HUE
, SATURATION
, BRIGHTNESS
, RED
, GREEN
, BLUE
};
175 const ColorMode DefaultMode
= HUE
;
177 class ColorFieldControl
: public weld::CustomWidgetController
181 : meMode( DefaultMode
)
184 , mbMouseCaptured(false)
188 virtual void SetDrawingArea(weld::DrawingArea
* pDrawingArea
) override
190 CustomWidgetController::SetDrawingArea(pDrawingArea
);
191 pDrawingArea
->set_size_request(pDrawingArea
->get_approximate_digit_width() * 40,
192 pDrawingArea
->get_text_height() * 10);
195 virtual ~ColorFieldControl() override
197 mxBitmap
.disposeAndClear();
200 virtual void Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& rRect
) override
;
201 virtual void Resize() override
;
202 virtual bool MouseButtonDown(const MouseEvent
& rMEvt
) override
;
203 virtual bool MouseMove(const MouseEvent
& rMEvt
) override
;
204 virtual bool MouseButtonUp(const MouseEvent
& rMEvt
) override
;
207 void ShowPosition( const Point
& rPos
, bool bUpdate
);
208 void UpdatePosition();
211 void SetValues(Color aColor
, ColorMode eMode
, double x
, double y
);
212 double GetX() const { return mdX
;}
213 double GetY() const { return mdY
;}
215 void SetModifyHdl(const Link
<ColorFieldControl
&,void>& rLink
) { maModifyHdl
= rLink
; }
222 bool mbMouseCaptured
;
224 VclPtr
<VirtualDevice
> mxBitmap
;
225 Link
<ColorFieldControl
&,void> maModifyHdl
;
226 std::vector
<sal_uInt8
> maRGB_Horiz
;
227 std::vector
<sal_uInt16
> maGrad_Horiz
;
228 std::vector
<sal_uInt16
> maPercent_Horiz
;
229 std::vector
<sal_uInt8
> maRGB_Vert
;
230 std::vector
<sal_uInt16
> maPercent_Vert
;
233 void ColorFieldControl::UpdateBitmap()
235 const Size
aSize(GetOutputSizePixel());
237 if (mxBitmap
&& mxBitmap
->GetOutputSizePixel() != aSize
)
238 mxBitmap
.disposeAndClear();
240 const sal_Int32 nWidth
= aSize
.Width();
241 const sal_Int32 nHeight
= aSize
.Height();
243 if (nWidth
== 0 || nHeight
== 0)
248 mxBitmap
= VclPtr
<VirtualDevice
>::Create();
249 mxBitmap
->SetOutputSizePixel(aSize
);
251 maRGB_Horiz
.resize( nWidth
);
252 maGrad_Horiz
.resize( nWidth
);
253 maPercent_Horiz
.resize( nWidth
);
255 sal_uInt8
* pRGB
= maRGB_Horiz
.data();
256 sal_uInt16
* pGrad
= maGrad_Horiz
.data();
257 sal_uInt16
* pPercent
= maPercent_Horiz
.data();
259 for( sal_Int32 x
= 0; x
< nWidth
; x
++ )
261 *pRGB
++ = static_cast<sal_uInt8
>((x
* 256) / nWidth
);
262 *pGrad
++ = static_cast<sal_uInt16
>((x
* 359) / nWidth
);
263 *pPercent
++ = static_cast<sal_uInt16
>((x
* 100) / nWidth
);
266 maRGB_Vert
.resize(nHeight
);
267 maPercent_Vert
.resize(nHeight
);
269 pRGB
= maRGB_Vert
.data();
270 pPercent
= maPercent_Vert
.data();
272 sal_Int32 y
= nHeight
;
275 *pRGB
++ = static_cast<sal_uInt8
>((y
* 256) / nHeight
);
276 *pPercent
++ = static_cast<sal_uInt16
>((y
* 100) / nHeight
);
280 sal_uInt8
* pRGB_Horiz
= maRGB_Horiz
.data();
281 sal_uInt16
* pGrad_Horiz
= maGrad_Horiz
.data();
282 sal_uInt16
* pPercent_Horiz
= maPercent_Horiz
.data();
283 sal_uInt8
* pRGB_Vert
= maRGB_Vert
.data();
284 sal_uInt16
* pPercent_Vert
= maPercent_Vert
.data();
286 Color
aBitmapColor(maColor
);
288 sal_uInt16 nHue
, nSat
, nBri
;
289 maColor
.RGBtoHSB(nHue
, nSat
, nBri
);
291 // this has been unlooped for performance reason, please do not merge back!
293 sal_uInt16 y
= nHeight
,x
;
300 nBri
= pPercent_Vert
[y
];
304 nSat
= pPercent_Horiz
[x
];
305 mxBitmap
->DrawPixel(Point(x
,y
), Color::HSBtoRGB(nHue
, nSat
, nBri
));
312 nBri
= pPercent_Vert
[y
];
316 nHue
= pGrad_Horiz
[x
];
317 mxBitmap
->DrawPixel(Point(x
,y
), Color::HSBtoRGB(nHue
, nSat
, nBri
));
324 nSat
= pPercent_Vert
[y
];
328 nHue
= pGrad_Horiz
[x
];
329 mxBitmap
->DrawPixel(Point(x
,y
), Color::HSBtoRGB(nHue
, nSat
, nBri
));
336 aBitmapColor
.SetGreen(pRGB_Vert
[y
]);
340 aBitmapColor
.SetBlue(pRGB_Horiz
[x
]);
341 mxBitmap
->DrawPixel(Point(x
,y
), aBitmapColor
);
348 aBitmapColor
.SetRed(pRGB_Vert
[y
]);
352 aBitmapColor
.SetBlue(pRGB_Horiz
[x
]);
353 mxBitmap
->DrawPixel(Point(x
,y
), aBitmapColor
);
360 aBitmapColor
.SetGreen(pRGB_Vert
[y
]);
364 aBitmapColor
.SetRed(pRGB_Horiz
[x
]);
365 mxBitmap
->DrawPixel(Point(x
,y
), aBitmapColor
);
372 void ColorFieldControl::ShowPosition( const Point
& rPos
, bool bUpdate
)
383 const Size
aSize(mxBitmap
->GetOutputSizePixel());
389 else if (nX
>= aSize
.Width())
390 nX
= aSize
.Width() - 1;
394 else if (nY
>= aSize
.Height())
395 nY
= aSize
.Height() - 1;
397 Point aPos
= maPosition
;
398 maPosition
.setX( nX
- 5 );
399 maPosition
.setY( nY
- 5 );
400 Invalidate(tools::Rectangle(aPos
, Size(11, 11)));
401 Invalidate(tools::Rectangle(maPosition
, Size(11, 11)));
405 mdX
= double(nX
) / double(aSize
.Width() - 1.0);
406 mdY
= double(aSize
.Height() - 1.0 - nY
) / double(aSize
.Height() - 1.0);
408 maColor
= mxBitmap
->GetPixel(Point(nX
, nY
));
412 bool ColorFieldControl::MouseButtonDown(const MouseEvent
& rMEvt
)
415 mbMouseCaptured
= true;
416 ShowPosition(rMEvt
.GetPosPixel(), true);
421 bool ColorFieldControl::MouseMove(const MouseEvent
& rMEvt
)
425 ShowPosition(rMEvt
.GetPosPixel(), true);
431 bool ColorFieldControl::MouseButtonUp(const MouseEvent
&)
434 mbMouseCaptured
= false;
438 void ColorFieldControl::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&)
445 Size
aSize(GetOutputSizePixel());
446 rRenderContext
.DrawOutDev(Point(0, 0), aSize
, Point(0, 0), aSize
, *mxBitmap
);
449 // draw circle around current color
450 if (maColor
.IsDark())
451 rRenderContext
.SetLineColor( COL_WHITE
);
453 rRenderContext
.SetLineColor( COL_BLACK
);
455 rRenderContext
.SetFillColor();
457 rRenderContext
.DrawEllipse(::tools::Rectangle(maPosition
, Size(11, 11)));
460 void ColorFieldControl::Resize()
462 CustomWidgetController::Resize();
467 void ColorFieldControl::Modify()
469 maModifyHdl
.Call( *this );
472 void ColorFieldControl::SetValues( Color aColor
, ColorMode eMode
, double x
, double y
)
474 bool bUpdateBitmap
= (maColor
!= aColor
) || (meMode
!= eMode
);
475 if( bUpdateBitmap
|| (mdX
!= x
) || (mdY
!= y
) )
490 void ColorFieldControl::UpdatePosition()
492 Size
aSize(GetOutputSizePixel());
493 ShowPosition(Point(static_cast<long>(mdX
* aSize
.Width()), static_cast<long>((1.0 - mdY
) * aSize
.Height())), false);
496 class ColorSliderControl
: public weld::CustomWidgetController
499 ColorSliderControl();
500 virtual ~ColorSliderControl() override
;
502 virtual void SetDrawingArea(weld::DrawingArea
* pDrawingArea
) override
;
504 virtual bool MouseButtonDown(const MouseEvent
& rMEvt
) override
;
505 virtual bool MouseMove(const MouseEvent
& rMEvt
) override
;
506 virtual bool MouseButtonUp(const MouseEvent
& rMEvt
) override
;
507 virtual void Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&) override
;
508 virtual void Resize() override
;
511 void ChangePosition( long nY
);
514 void SetValue( const Color
& rColor
, ColorMode eMode
, double dValue
);
515 double GetValue() const { return mdValue
; }
517 void SetModifyHdl( const Link
<ColorSliderControl
&,void>& rLink
) { maModifyHdl
= rLink
; }
519 sal_Int16
GetLevel() const { return mnLevel
; }
522 Link
<ColorSliderControl
&,void> maModifyHdl
;
525 VclPtr
<VirtualDevice
> mxBitmap
;
530 ColorSliderControl::ColorSliderControl()
531 : meMode( DefaultMode
)
537 void ColorSliderControl::SetDrawingArea(weld::DrawingArea
* pDrawingArea
)
539 CustomWidgetController::SetDrawingArea(pDrawingArea
);
540 pDrawingArea
->set_size_request(pDrawingArea
->get_approximate_digit_width() * 3, -1);
543 ColorSliderControl::~ColorSliderControl()
545 mxBitmap
.disposeAndClear();
548 void ColorSliderControl::UpdateBitmap()
550 Size
aSize(1, GetOutputSizePixel().Height());
552 if (mxBitmap
&& mxBitmap
->GetOutputSizePixel() != aSize
)
553 mxBitmap
.disposeAndClear();
557 mxBitmap
= VclPtr
<VirtualDevice
>::Create();
558 mxBitmap
->SetOutputSizePixel(aSize
);
561 const long nY
= aSize
.Height() - 1;
563 Color
aBitmapColor(maColor
);
565 sal_uInt16 nHue
, nSat
, nBri
;
566 maColor
.RGBtoHSB(nHue
, nSat
, nBri
);
568 // this has been unlooped for performance reason, please do not merge back!
575 for (long y
= 0; y
<= nY
; y
++)
577 nHue
= static_cast<sal_uInt16
>((359 * y
) / nY
);
578 mxBitmap
->DrawPixel(Point(0, nY
- y
), Color::HSBtoRGB(nHue
, nSat
, nBri
));
583 nBri
= std::max(sal_uInt16(32), nBri
);
584 for (long y
= 0; y
<= nY
; y
++)
586 nSat
= static_cast<sal_uInt16
>((100 * y
) / nY
);
587 mxBitmap
->DrawPixel(Point(0, nY
- y
), Color::HSBtoRGB(nHue
, nSat
, nBri
));
592 for (long y
= 0; y
<= nY
; y
++)
594 nBri
= static_cast<sal_uInt16
>((100 * y
) / nY
);
595 mxBitmap
->DrawPixel(Point(0, nY
- y
), Color::HSBtoRGB(nHue
, nSat
, nBri
));
600 for (long y
= 0; y
<= nY
; y
++)
602 aBitmapColor
.SetRed(sal_uInt8((long(255) * y
) / nY
));
603 mxBitmap
->DrawPixel(Point(0, nY
- y
), aBitmapColor
);
608 for (long y
= 0; y
<= nY
; y
++)
610 aBitmapColor
.SetGreen(sal_uInt8((long(255) * y
) / nY
));
611 mxBitmap
->DrawPixel(Point(0, nY
- y
), aBitmapColor
);
616 for (long y
= 0; y
<= nY
; y
++)
618 aBitmapColor
.SetBlue(sal_uInt8((long(255) * y
) / nY
));
619 mxBitmap
->DrawPixel(Point(0, nY
- y
), aBitmapColor
);
625 void ColorSliderControl::ChangePosition(long nY
)
627 const long nHeight
= GetOutputSizePixel().Height() - 1;
631 else if (nY
> nHeight
)
635 mdValue
= double(nHeight
- nY
) / double(nHeight
);
638 bool ColorSliderControl::MouseButtonDown(const MouseEvent
& rMEvt
)
641 ChangePosition(rMEvt
.GetPosPixel().Y());
646 bool ColorSliderControl::MouseMove(const MouseEvent
& rMEvt
)
648 if (IsMouseCaptured())
650 ChangePosition(rMEvt
.GetPosPixel().Y());
656 bool ColorSliderControl::MouseButtonUp(const MouseEvent
&)
662 void ColorSliderControl::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&)
667 const Size
aSize(GetOutputSizePixel());
670 int x
= aSize
.Width();
673 rRenderContext
.DrawOutDev(aPos
, aSize
, Point(0,0), aSize
, *mxBitmap
);
678 void ColorSliderControl::Resize()
680 CustomWidgetController::Resize();
684 void ColorSliderControl::Modify()
686 maModifyHdl
.Call(*this);
689 void ColorSliderControl::SetValue(const Color
& rColor
, ColorMode eMode
, double dValue
)
691 bool bUpdateBitmap
= (rColor
!= maColor
) || (eMode
!= meMode
);
692 if( bUpdateBitmap
|| (mdValue
!= dValue
))
696 mnLevel
= static_cast<sal_Int16
>((1.0-dValue
) * GetOutputSizePixel().Height());
704 class ColorPickerDialog
: public weld::GenericDialogController
707 ColorFieldControl m_aColorField
;
708 ColorSliderControl m_aColorSlider
;
709 ColorPreviewControl m_aColorPreview
;
710 ColorPreviewControl m_aColorPrevious
;
712 std::unique_ptr
<weld::CustomWeld
> m_xColorField
;
713 std::unique_ptr
<weld::CustomWeld
> m_xColorSlider
;
714 std::unique_ptr
<weld::CustomWeld
> m_xColorPreview
;
715 std::unique_ptr
<weld::CustomWeld
> m_xColorPrevious
;
717 std::unique_ptr
<weld::Widget
> m_xFISliderLeft
;
718 std::unique_ptr
<weld::Widget
> m_xFISliderRight
;
719 std::unique_ptr
<weld::RadioButton
> m_xRBRed
;
720 std::unique_ptr
<weld::RadioButton
> m_xRBGreen
;
721 std::unique_ptr
<weld::RadioButton
> m_xRBBlue
;
722 std::unique_ptr
<weld::RadioButton
> m_xRBHue
;
723 std::unique_ptr
<weld::RadioButton
> m_xRBSaturation
;
724 std::unique_ptr
<weld::RadioButton
> m_xRBBrightness
;
726 std::unique_ptr
<weld::SpinButton
> m_xMFRed
;
727 std::unique_ptr
<weld::SpinButton
> m_xMFGreen
;
728 std::unique_ptr
<weld::SpinButton
> m_xMFBlue
;
729 std::unique_ptr
<weld::HexColorControl
> m_xEDHex
;
731 std::unique_ptr
<weld::MetricSpinButton
> m_xMFHue
;
732 std::unique_ptr
<weld::MetricSpinButton
> m_xMFSaturation
;
733 std::unique_ptr
<weld::MetricSpinButton
> m_xMFBrightness
;
735 std::unique_ptr
<weld::MetricSpinButton
> m_xMFCyan
;
736 std::unique_ptr
<weld::MetricSpinButton
> m_xMFMagenta
;
737 std::unique_ptr
<weld::MetricSpinButton
> m_xMFYellow
;
738 std::unique_ptr
<weld::MetricSpinButton
> m_xMFKey
;
741 ColorPickerDialog(weld::Window
* pParent
, Color nColor
, sal_Int16 nMode
);
743 void update_color(UpdateFlags n
= UpdateFlags::All
);
745 DECL_LINK(ColorFieldControlModifydl
, ColorFieldControl
&, void);
746 DECL_LINK(ColorSliderControlModifyHdl
, ColorSliderControl
&, void);
747 DECL_LINK(ColorModifyMetricHdl
, weld::MetricSpinButton
&, void);
748 DECL_LINK(ColorModifySpinHdl
, weld::SpinButton
&, void);
749 DECL_LINK(ColorModifyEditHdl
, weld::Entry
&, void);
750 DECL_LINK(ModeModifyHdl
, weld::ToggleButton
&, void);
752 Color
GetColor() const;
754 void setColorComponent(ColorComponent nComp
, double dValue
);
759 double mdRed
, mdGreen
, mdBlue
;
760 double mdHue
, mdSat
, mdBri
;
761 double mdCyan
, mdMagenta
, mdYellow
, mdKey
;
764 ColorPickerDialog::ColorPickerDialog(weld::Window
* pParent
, Color nColor
, sal_Int16 nDialogMode
)
765 : GenericDialogController(pParent
, "cui/ui/colorpickerdialog.ui", "ColorPicker")
766 , m_xColorField(new weld::CustomWeld(*m_xBuilder
, "colorField", m_aColorField
))
767 , m_xColorSlider(new weld::CustomWeld(*m_xBuilder
, "colorSlider", m_aColorSlider
))
768 , m_xColorPreview(new weld::CustomWeld(*m_xBuilder
, "preview", m_aColorPreview
))
769 , m_xColorPrevious(new weld::CustomWeld(*m_xBuilder
, "previous", m_aColorPrevious
))
770 , m_xFISliderLeft(m_xBuilder
->weld_widget("leftImage"))
771 , m_xFISliderRight(m_xBuilder
->weld_widget("rightImage"))
772 , m_xRBRed(m_xBuilder
->weld_radio_button("redRadiobutton"))
773 , m_xRBGreen(m_xBuilder
->weld_radio_button("greenRadiobutton"))
774 , m_xRBBlue(m_xBuilder
->weld_radio_button("blueRadiobutton"))
775 , m_xRBHue(m_xBuilder
->weld_radio_button("hueRadiobutton"))
776 , m_xRBSaturation(m_xBuilder
->weld_radio_button("satRadiobutton"))
777 , m_xRBBrightness(m_xBuilder
->weld_radio_button("brightRadiobutton"))
778 , m_xMFRed(m_xBuilder
->weld_spin_button("redSpinbutton"))
779 , m_xMFGreen(m_xBuilder
->weld_spin_button("greenSpinbutton"))
780 , m_xMFBlue(m_xBuilder
->weld_spin_button("blueSpinbutton"))
781 , m_xEDHex(new weld::HexColorControl(m_xBuilder
->weld_entry("hexEntry")))
782 , m_xMFHue(m_xBuilder
->weld_metric_spin_button("hueSpinbutton", FieldUnit::DEGREE
))
783 , m_xMFSaturation(m_xBuilder
->weld_metric_spin_button("satSpinbutton", FieldUnit::PERCENT
))
784 , m_xMFBrightness(m_xBuilder
->weld_metric_spin_button("brightSpinbutton", FieldUnit::PERCENT
))
785 , m_xMFCyan(m_xBuilder
->weld_metric_spin_button("cyanSpinbutton", FieldUnit::PERCENT
))
786 , m_xMFMagenta(m_xBuilder
->weld_metric_spin_button("magSpinbutton", FieldUnit::PERCENT
))
787 , m_xMFYellow(m_xBuilder
->weld_metric_spin_button("yellowSpinbutton", FieldUnit::PERCENT
))
788 , m_xMFKey(m_xBuilder
->weld_metric_spin_button("keySpinbutton", FieldUnit::PERCENT
))
789 , meMode( DefaultMode
)
791 m_aColorField
.SetModifyHdl( LINK( this, ColorPickerDialog
, ColorFieldControlModifydl
) );
792 m_aColorSlider
.SetModifyHdl( LINK( this, ColorPickerDialog
, ColorSliderControlModifyHdl
) );
794 int nMargin
= (m_xFISliderLeft
->get_preferred_size().Height() + 1) / 2;
795 m_xColorSlider
->set_margin_top(nMargin
);
796 m_xColorSlider
->set_margin_bottom(nMargin
);
798 Link
<weld::MetricSpinButton
&,void> aLink3( LINK( this, ColorPickerDialog
, ColorModifyMetricHdl
) );
799 m_xMFCyan
->connect_value_changed( aLink3
);
800 m_xMFMagenta
->connect_value_changed( aLink3
);
801 m_xMFYellow
->connect_value_changed( aLink3
);
802 m_xMFKey
->connect_value_changed( aLink3
);
804 m_xMFHue
->connect_value_changed( aLink3
);
805 m_xMFSaturation
->connect_value_changed( aLink3
);
806 m_xMFBrightness
->connect_value_changed( aLink3
);
808 Link
<weld::SpinButton
&,void> aLink4(LINK(this, ColorPickerDialog
, ColorModifySpinHdl
));
809 m_xMFRed
->connect_value_changed(aLink4
);
810 m_xMFGreen
->connect_value_changed(aLink4
);
811 m_xMFBlue
->connect_value_changed(aLink4
);
813 m_xEDHex
->connect_changed(LINK(this, ColorPickerDialog
, ColorModifyEditHdl
));
815 Link
<weld::ToggleButton
&,void> aLink2
= LINK( this, ColorPickerDialog
, ModeModifyHdl
);
816 m_xRBRed
->connect_toggled( aLink2
);
817 m_xRBGreen
->connect_toggled( aLink2
);
818 m_xRBBlue
->connect_toggled( aLink2
);
819 m_xRBHue
->connect_toggled( aLink2
);
820 m_xRBSaturation
->connect_toggled( aLink2
);
821 m_xRBBrightness
->connect_toggled( aLink2
);
823 Color
aColor(nColor
);
826 if (nDialogMode
== 2)
828 m_aColorPrevious
.SetColor(aColor
);
829 m_xColorPrevious
->show();
832 mdRed
= static_cast<double>(aColor
.GetRed()) / 255.0;
833 mdGreen
= static_cast<double>(aColor
.GetGreen()) / 255.0;
834 mdBlue
= static_cast<double>(aColor
.GetBlue()) / 255.0;
836 RGBtoHSV( mdRed
, mdGreen
, mdBlue
, mdHue
, mdSat
, mdBri
);
837 RGBtoCMYK( mdRed
, mdGreen
, mdBlue
, mdCyan
, mdMagenta
, mdYellow
, mdKey
);
842 static int toInt( double dValue
, double dRange
)
844 return static_cast< int >( std::floor((dValue
* dRange
) + 0.5 ) );
847 Color
ColorPickerDialog::GetColor() const
849 return Color( toInt(mdRed
,255.0), toInt(mdGreen
,255.0), toInt(mdBlue
,255.0) );
852 void ColorPickerDialog::update_color( UpdateFlags n
)
854 sal_uInt8 nRed
= toInt(mdRed
,255.0);
855 sal_uInt8 nGreen
= toInt(mdGreen
,255.0);
856 sal_uInt8 nBlue
= toInt(mdBlue
,255.0);
858 Color
aColor(nRed
, nGreen
, nBlue
);
860 if (n
& UpdateFlags::RGB
) // update RGB
862 m_xMFRed
->set_value(nRed
);
863 m_xMFGreen
->set_value(nGreen
);
864 m_xMFBlue
->set_value(nBlue
);
867 if (n
& UpdateFlags::CMYK
) // update CMYK
869 m_xMFCyan
->set_value(toInt(mdCyan
, 100.0), FieldUnit::PERCENT
);
870 m_xMFMagenta
->set_value(toInt(mdMagenta
, 100.0), FieldUnit::PERCENT
);
871 m_xMFYellow
->set_value(toInt(mdYellow
, 100.0), FieldUnit::PERCENT
);
872 m_xMFKey
->set_value(toInt(mdKey
, 100.0), FieldUnit::PERCENT
);
875 if (n
& UpdateFlags::HSB
) // update HSB
877 m_xMFHue
->set_value(toInt(mdHue
, 1.0), FieldUnit::DEGREE
);
878 m_xMFSaturation
->set_value(toInt( mdSat
, 100.0), FieldUnit::PERCENT
);
879 m_xMFBrightness
->set_value(toInt( mdBri
, 100.0), FieldUnit::PERCENT
);
882 if (n
& UpdateFlags::ColorChooser
) // update Color Chooser 1
887 m_aColorField
.SetValues(aColor
, meMode
, mdSat
, mdBri
);
890 m_aColorField
.SetValues(aColor
, meMode
, mdHue
/ 360.0, mdBri
);
893 m_aColorField
.SetValues(aColor
, meMode
, mdHue
/ 360.0, mdSat
);
896 m_aColorField
.SetValues(aColor
, meMode
, mdBlue
, mdGreen
);
899 m_aColorField
.SetValues(aColor
, meMode
, mdBlue
, mdRed
);
902 m_aColorField
.SetValues(aColor
, meMode
, mdRed
, mdGreen
);
907 if (n
& UpdateFlags::ColorSlider
) // update Color Chooser 2
912 m_aColorSlider
.SetValue(aColor
, meMode
, mdHue
/ 360.0);
915 m_aColorSlider
.SetValue(aColor
, meMode
, mdSat
);
918 m_aColorSlider
.SetValue(aColor
, meMode
, mdBri
);
921 m_aColorSlider
.SetValue(aColor
, meMode
, mdRed
);
924 m_aColorSlider
.SetValue(aColor
, meMode
, mdGreen
);
927 m_aColorSlider
.SetValue(aColor
, meMode
, mdBlue
);
932 if (n
& UpdateFlags::Hex
) // update hex
934 m_xFISliderLeft
->set_margin_top(m_aColorSlider
.GetLevel());
935 m_xFISliderRight
->set_margin_top(m_aColorSlider
.GetLevel());
936 m_xEDHex
->SetColor(aColor
);
938 m_aColorPreview
.SetColor(aColor
);
941 IMPL_LINK_NOARG(ColorPickerDialog
, ColorFieldControlModifydl
, ColorFieldControl
&, void)
943 double x
= m_aColorField
.GetX();
944 double y
= m_aColorField
.GetY();
950 setColorComponent( ColorComponent::Brightness
, y
);
954 setColorComponent( ColorComponent::Brightness
, y
);
958 setColorComponent( ColorComponent::Saturation
, y
);
962 setColorComponent( ColorComponent::Green
, y
);
966 setColorComponent( ColorComponent::Red
, y
);
970 setColorComponent( ColorComponent::Green
, y
);
974 update_color(UpdateFlags::All
& ~UpdateFlags::ColorChooser
);
977 IMPL_LINK_NOARG(ColorPickerDialog
, ColorSliderControlModifyHdl
, ColorSliderControl
&, void)
979 double dValue
= m_aColorSlider
.GetValue();
983 setColorComponent( ColorComponent::Hue
, dValue
* 360.0 );
986 setColorComponent( ColorComponent::Saturation
, dValue
);
989 setColorComponent( ColorComponent::Brightness
, dValue
);
992 setColorComponent( ColorComponent::Red
, dValue
);
995 setColorComponent( ColorComponent::Green
, dValue
);
998 setColorComponent( ColorComponent::Blue
, dValue
);
1002 update_color(UpdateFlags::All
& ~UpdateFlags::ColorSlider
);
1005 IMPL_LINK(ColorPickerDialog
, ColorModifyMetricHdl
, weld::MetricSpinButton
&, rEdit
, void)
1007 UpdateFlags n
= UpdateFlags::NONE
;
1009 if (&rEdit
== m_xMFHue
.get())
1011 setColorComponent( ColorComponent::Hue
, static_cast<double>(m_xMFHue
->get_value(FieldUnit::DEGREE
)) );
1012 n
= UpdateFlags::All
& ~UpdateFlags::HSB
;
1014 else if (&rEdit
== m_xMFSaturation
.get())
1016 setColorComponent( ColorComponent::Saturation
, static_cast<double>(m_xMFSaturation
->get_value(FieldUnit::PERCENT
)) / 100.0 );
1017 n
= UpdateFlags::All
& ~UpdateFlags::HSB
;
1019 else if (&rEdit
== m_xMFBrightness
.get())
1021 setColorComponent( ColorComponent::Brightness
, static_cast<double>(m_xMFBrightness
->get_value(FieldUnit::PERCENT
)) / 100.0 );
1022 n
= UpdateFlags::All
& ~UpdateFlags::HSB
;
1024 else if (&rEdit
== m_xMFCyan
.get())
1026 setColorComponent( ColorComponent::Cyan
, static_cast<double>(m_xMFCyan
->get_value(FieldUnit::PERCENT
)) / 100.0 );
1027 n
= UpdateFlags::All
& ~UpdateFlags::CMYK
;
1029 else if (&rEdit
== m_xMFMagenta
.get())
1031 setColorComponent( ColorComponent::Magenta
, static_cast<double>(m_xMFMagenta
->get_value(FieldUnit::PERCENT
)) / 100.0 );
1032 n
= UpdateFlags::All
& ~UpdateFlags::CMYK
;
1034 else if (&rEdit
== m_xMFYellow
.get())
1036 setColorComponent( ColorComponent::Yellow
, static_cast<double>(m_xMFYellow
->get_value(FieldUnit::PERCENT
)) / 100.0 );
1037 n
= UpdateFlags::All
& ~UpdateFlags::CMYK
;
1039 else if (&rEdit
== m_xMFKey
.get())
1041 setColorComponent( ColorComponent::Key
, static_cast<double>(m_xMFKey
->get_value(FieldUnit::PERCENT
)) / 100.0 );
1042 n
= UpdateFlags::All
& ~UpdateFlags::CMYK
;
1045 if (n
!= UpdateFlags::NONE
)
1049 IMPL_LINK_NOARG(ColorPickerDialog
, ColorModifyEditHdl
, weld::Entry
&, void)
1051 UpdateFlags n
= UpdateFlags::NONE
;
1053 Color aColor
= m_xEDHex
->GetColor();
1055 if (aColor
!= Color(0xffffffff) && aColor
!= GetColor())
1057 mdRed
= static_cast<double>(aColor
.GetRed()) / 255.0;
1058 mdGreen
= static_cast<double>(aColor
.GetGreen()) / 255.0;
1059 mdBlue
= static_cast<double>(aColor
.GetBlue()) / 255.0;
1061 RGBtoHSV( mdRed
, mdGreen
, mdBlue
, mdHue
, mdSat
, mdBri
);
1062 RGBtoCMYK( mdRed
, mdGreen
, mdBlue
, mdCyan
, mdMagenta
, mdYellow
, mdKey
);
1063 n
= UpdateFlags::All
& ~UpdateFlags::Hex
;
1066 if (n
!= UpdateFlags::NONE
)
1070 IMPL_LINK(ColorPickerDialog
, ColorModifySpinHdl
, weld::SpinButton
&, rEdit
, void)
1072 UpdateFlags n
= UpdateFlags::NONE
;
1074 if (&rEdit
== m_xMFRed
.get())
1076 setColorComponent( ColorComponent::Red
, static_cast<double>(m_xMFRed
->get_value()) / 255.0 );
1077 n
= UpdateFlags::All
& ~UpdateFlags::RGB
;
1079 else if (&rEdit
== m_xMFGreen
.get())
1081 setColorComponent( ColorComponent::Green
, static_cast<double>(m_xMFGreen
->get_value()) / 255.0 );
1082 n
= UpdateFlags::All
& ~UpdateFlags::RGB
;
1084 else if (&rEdit
== m_xMFBlue
.get())
1086 setColorComponent( ColorComponent::Blue
, static_cast<double>(m_xMFBlue
->get_value()) / 255.0 );
1087 n
= UpdateFlags::All
& ~UpdateFlags::RGB
;
1090 if (n
!= UpdateFlags::NONE
)
1095 IMPL_LINK_NOARG(ColorPickerDialog
, ModeModifyHdl
, weld::ToggleButton
&, void)
1097 ColorMode eMode
= HUE
;
1099 if (m_xRBRed
->get_active())
1103 else if (m_xRBGreen
->get_active())
1107 else if (m_xRBBlue
->get_active())
1111 else if (m_xRBSaturation
->get_active())
1115 else if (m_xRBBrightness
->get_active())
1120 if (meMode
!= eMode
)
1123 update_color(UpdateFlags::ColorChooser
| UpdateFlags::ColorSlider
);
1127 void ColorPickerDialog::setColorComponent( ColorComponent nComp
, double dValue
)
1131 case ColorComponent::Red
:
1134 case ColorComponent::Green
:
1137 case ColorComponent::Blue
:
1140 case ColorComponent::Hue
:
1143 case ColorComponent::Saturation
:
1146 case ColorComponent::Brightness
:
1149 case ColorComponent::Cyan
:
1152 case ColorComponent::Yellow
:
1155 case ColorComponent::Magenta
:
1158 case ColorComponent::Key
:
1163 if (nComp
== ColorComponent::Red
|| nComp
== ColorComponent::Green
|| nComp
== ColorComponent::Blue
)
1165 RGBtoHSV( mdRed
, mdGreen
, mdBlue
, mdHue
, mdSat
, mdBri
);
1166 RGBtoCMYK( mdRed
, mdGreen
, mdBlue
, mdCyan
, mdMagenta
, mdYellow
, mdKey
);
1168 else if (nComp
== ColorComponent::Hue
|| nComp
== ColorComponent::Saturation
|| nComp
== ColorComponent::Brightness
)
1170 HSVtoRGB( mdHue
, mdSat
, mdBri
, mdRed
, mdGreen
, mdBlue
);
1171 RGBtoCMYK( mdRed
, mdGreen
, mdBlue
, mdCyan
, mdMagenta
, mdYellow
, mdKey
);
1175 CMYKtoRGB( mdCyan
, mdMagenta
, mdYellow
, mdKey
, mdRed
, mdGreen
, mdBlue
);
1176 RGBtoHSV( mdRed
, mdGreen
, mdBlue
, mdHue
, mdSat
, mdBri
);
1180 typedef ::cppu::WeakComponentImplHelper
< XServiceInfo
, XExecutableDialog
, XInitialization
, XPropertyAccess
> ColorPickerBase
;
1182 class ColorPicker
: protected ::cppu::BaseMutex
, // Struct for right initialization of mutex member! Must be first of baseclasses.
1183 public ColorPickerBase
1186 explicit ColorPicker();
1189 virtual void SAL_CALL
initialize( const Sequence
< Any
>& aArguments
) override
;
1192 virtual OUString SAL_CALL
getImplementationName( ) override
;
1193 virtual sal_Bool SAL_CALL
supportsService( const OUString
& ServiceName
) override
;
1194 virtual Sequence
< OUString
> SAL_CALL
getSupportedServiceNames( ) override
;
1197 virtual Sequence
< PropertyValue
> SAL_CALL
getPropertyValues( ) override
;
1198 virtual void SAL_CALL
setPropertyValues( const Sequence
< PropertyValue
>& aProps
) override
;
1200 // XExecutableDialog
1201 virtual void SAL_CALL
setTitle( const OUString
& aTitle
) override
;
1202 virtual sal_Int16 SAL_CALL
execute( ) override
;
1207 Reference
<css::awt::XWindow
> mxParent
;
1210 OUString
ColorPicker_getImplementationName()
1212 return "com.sun.star.cui.ColorPicker";
1215 Reference
< XInterface
> ColorPicker_createInstance( Reference
< XComponentContext
> const & )
1217 return static_cast<XWeak
*>( new ColorPicker
);
1220 Sequence
< OUString
> ColorPicker_getSupportedServiceNames()
1222 Sequence
< OUString
> seq
{ "com.sun.star.ui.dialogs.ColorPicker" };
1226 static const OUStringLiteral
gsColorKey( "Color" );
1227 static const OUStringLiteral
gsModeKey( "Mode" );
1229 ColorPicker::ColorPicker()
1230 : ColorPickerBase( m_aMutex
)
1237 void SAL_CALL
ColorPicker::initialize( const Sequence
< Any
>& aArguments
)
1239 if( aArguments
.getLength() == 1 )
1241 aArguments
[0] >>= mxParent
;
1246 OUString SAL_CALL
ColorPicker::getImplementationName( )
1248 return ColorPicker_getImplementationName();
1251 sal_Bool SAL_CALL
ColorPicker::supportsService( const OUString
& sServiceName
)
1253 return cppu::supportsService(this, sServiceName
);
1256 Sequence
< OUString
> SAL_CALL
ColorPicker::getSupportedServiceNames( )
1258 return ColorPicker_getSupportedServiceNames();
1262 Sequence
< PropertyValue
> SAL_CALL
ColorPicker::getPropertyValues( )
1264 Sequence
< PropertyValue
> props(1);
1265 props
[0].Name
= gsColorKey
;
1266 props
[0].Value
<<= mnColor
;
1270 void SAL_CALL
ColorPicker::setPropertyValues( const Sequence
< PropertyValue
>& aProps
)
1272 for( sal_Int32 n
= 0; n
< aProps
.getLength(); n
++ )
1274 if( aProps
[n
].Name
== gsColorKey
)
1276 aProps
[n
].Value
>>= mnColor
;
1278 else if( aProps
[n
].Name
== gsModeKey
)
1280 aProps
[n
].Value
>>= mnMode
;
1285 // XExecutableDialog
1286 void SAL_CALL
ColorPicker::setTitle( const OUString
& )
1290 sal_Int16 SAL_CALL
ColorPicker::execute()
1292 std::unique_ptr
<ColorPickerDialog
> xDlg(new ColorPickerDialog(Application::GetFrameWeld(mxParent
), mnColor
, mnMode
));
1293 sal_Int16 ret
= xDlg
->run();
1295 mnColor
= xDlg
->GetColor();
1301 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */