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/datatransfer/XTransferable.hpp>
26 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
27 #include <com/sun/star/awt/XWindow.hpp>
28 #include <cppuhelper/compbase.hxx>
29 #include <cppuhelper/supportsservice.hxx>
30 #include <cppuhelper/basemutex.hxx>
31 #include <vcl/customweld.hxx>
32 #include <vcl/bitmapaccess.hxx>
33 #include <vcl/event.hxx>
34 #include <vcl/svapp.hxx>
35 #include <vcl/virdev.hxx>
36 #include <vcl/weld.hxx>
37 #include <toolkit/helper/vclunohelper.hxx>
38 #include <sot/exchange.hxx>
39 #include <sot/formats.hxx>
40 #include <svx/hexcolorcontrol.hxx>
41 #include <sax/tools/converter.hxx>
42 #include <basegfx/color/bcolortools.hxx>
43 #include <colorpicker.hxx>
44 #include <bitmaps.hlst>
47 #include <o3tl/typed_flags_set.hxx>
49 using namespace ::com::sun::star::uno
;
50 using namespace ::com::sun::star::lang
;
51 using namespace ::com::sun::star::ui::dialogs
;
52 using namespace ::com::sun::star::beans
;
53 using namespace ::basegfx
;
55 enum class UpdateFlags
67 template<> struct typed_flags
<UpdateFlags
> : is_typed_flags
<UpdateFlags
, 0x3f> {};
74 enum class ColorComponent
{
88 // color space conversion helpers
90 static void RGBtoHSV( double dR
, double dG
, double dB
, double& dH
, double& dS
, double& dV
)
92 BColor result
= basegfx::utils::rgb2hsv( BColor( dR
, dG
, dB
) );
99 static void HSVtoRGB(double dH
, double dS
, double dV
, double& dR
, double& dG
, double& dB
)
101 BColor result
= basegfx::utils::hsv2rgb( BColor( dH
, dS
, dV
) );
103 dR
= result
.getRed();
104 dG
= result
.getGreen();
105 dB
= result
.getBlue();
108 // CMYK values from 0 to 1
109 static void CMYKtoRGB( double fCyan
, double fMagenta
, double fYellow
, double fKey
, double& dR
, double& dG
, double& dB
)
111 fCyan
= (fCyan
* ( 1.0 - fKey
)) + fKey
;
112 fMagenta
= (fMagenta
* ( 1.0 - fKey
)) + fKey
;
113 fYellow
= (fYellow
* ( 1.0 - fKey
)) + fKey
;
115 dR
= std::max( std::min( ( 1.0 - fCyan
), 1.0), 0.0 );
116 dG
= std::max( std::min( ( 1.0 - fMagenta
), 1.0), 0.0 );
117 dB
= std::max( std::min( ( 1.0 - fYellow
), 1.0), 0.0 );
120 // CMY results from 0 to 1
121 static void RGBtoCMYK( double dR
, double dG
, double dB
, double& fCyan
, double& fMagenta
, double& fYellow
, double& fKey
)
127 //CMYK and CMY values from 0 to 1
129 if( fCyan
< fKey
) fKey
= fCyan
;
130 if( fMagenta
< fKey
) fKey
= fMagenta
;
131 if( fYellow
< fKey
) fKey
= fYellow
;
142 fCyan
= ( fCyan
- fKey
) / ( 1.0 - fKey
);
143 fMagenta
= ( fMagenta
- fKey
) / ( 1.0 - fKey
);
144 fYellow
= ( fYellow
- fKey
) / ( 1.0 - fKey
);
148 class ColorPreviewControl
: public weld::CustomWidgetController
153 virtual void Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&) override
;
155 ColorPreviewControl()
159 virtual void SetDrawingArea(weld::DrawingArea
* pDrawingArea
) override
161 CustomWidgetController::SetDrawingArea(pDrawingArea
);
162 pDrawingArea
->set_size_request(pDrawingArea
->get_approximate_digit_width() * 10,
163 pDrawingArea
->get_text_height() * 2);
166 void SetColor(const Color
& rCol
)
168 if (rCol
!= m_aColor
)
176 void ColorPreviewControl::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&)
178 rRenderContext
.SetFillColor(m_aColor
);
179 rRenderContext
.SetLineColor(m_aColor
);
180 rRenderContext
.DrawRect(tools::Rectangle(Point(0, 0), GetOutputSizePixel()));
183 enum ColorMode
{ HUE
, SATURATION
, BRIGHTNESS
, RED
, GREEN
, BLUE
};
184 const ColorMode DefaultMode
= HUE
;
186 class ColorFieldControl
: public weld::CustomWidgetController
190 : meMode( DefaultMode
)
193 , mbMouseCaptured(false)
197 virtual void SetDrawingArea(weld::DrawingArea
* pDrawingArea
) override
199 CustomWidgetController::SetDrawingArea(pDrawingArea
);
200 pDrawingArea
->set_size_request(pDrawingArea
->get_approximate_digit_width() * 40,
201 pDrawingArea
->get_text_height() * 10);
204 virtual ~ColorFieldControl() override
206 mxBitmap
.disposeAndClear();
209 virtual void Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& rRect
) override
;
210 virtual void Resize() override
;
211 virtual bool MouseButtonDown(const MouseEvent
& rMEvt
) override
;
212 virtual bool MouseMove(const MouseEvent
& rMEvt
) override
;
213 virtual bool MouseButtonUp(const MouseEvent
& rMEvt
) override
;
216 void ShowPosition( const Point
& rPos
, bool bUpdate
);
217 void UpdatePosition();
220 void SetValues(Color aColor
, ColorMode eMode
, double x
, double y
);
221 double GetX() { return mdX
;}
222 double GetY() { return mdY
;}
224 void SetModifyHdl(const Link
<ColorFieldControl
&,void>& rLink
) { maModifyHdl
= rLink
; }
231 bool mbMouseCaptured
;
233 VclPtr
<VirtualDevice
> mxBitmap
;
234 Link
<ColorFieldControl
&,void> maModifyHdl
;
235 std::vector
<sal_uInt8
> maRGB_Horiz
;
236 std::vector
<sal_uInt16
> maGrad_Horiz
;
237 std::vector
<sal_uInt16
> maPercent_Horiz
;
238 std::vector
<sal_uInt8
> maRGB_Vert
;
239 std::vector
<sal_uInt16
> maPercent_Vert
;
242 void ColorFieldControl::UpdateBitmap()
244 const Size
aSize(GetOutputSizePixel());
246 if (mxBitmap
&& mxBitmap
->GetOutputSizePixel() != aSize
)
247 mxBitmap
.disposeAndClear();
249 const sal_Int32 nWidth
= aSize
.Width();
250 const sal_Int32 nHeight
= aSize
.Height();
252 if (nWidth
== 0 || nHeight
== 0)
257 mxBitmap
= VclPtr
<VirtualDevice
>::Create();
258 mxBitmap
->SetOutputSizePixel(aSize
);
260 maRGB_Horiz
.resize( nWidth
);
261 maGrad_Horiz
.resize( nWidth
);
262 maPercent_Horiz
.resize( nWidth
);
264 sal_uInt8
* pRGB
= maRGB_Horiz
.data();
265 sal_uInt16
* pGrad
= maGrad_Horiz
.data();
266 sal_uInt16
* pPercent
= maPercent_Horiz
.data();
268 for( sal_Int32 x
= 0; x
< nWidth
; x
++ )
270 *pRGB
++ = static_cast<sal_uInt8
>((x
* 256) / nWidth
);
271 *pGrad
++ = static_cast<sal_uInt16
>((x
* 359) / nWidth
);
272 *pPercent
++ = static_cast<sal_uInt16
>((x
* 100) / nWidth
);
275 maRGB_Vert
.resize(nHeight
);
276 maPercent_Vert
.resize(nHeight
);
278 pRGB
= maRGB_Vert
.data();
279 pPercent
= maPercent_Vert
.data();
281 sal_Int32 y
= nHeight
;
284 *pRGB
++ = static_cast<sal_uInt8
>((y
* 256) / nHeight
);
285 *pPercent
++ = static_cast<sal_uInt16
>((y
* 100) / nHeight
);
289 sal_uInt8
* pRGB_Horiz
= maRGB_Horiz
.data();
290 sal_uInt16
* pGrad_Horiz
= maGrad_Horiz
.data();
291 sal_uInt16
* pPercent_Horiz
= maPercent_Horiz
.data();
292 sal_uInt8
* pRGB_Vert
= maRGB_Vert
.data();
293 sal_uInt16
* pPercent_Vert
= maPercent_Vert
.data();
295 Color
aBitmapColor(maColor
);
297 sal_uInt16 nHue
, nSat
, nBri
;
298 maColor
.RGBtoHSB(nHue
, nSat
, nBri
);
300 // this has been unlooped for performance reason, please do not merge back!
302 sal_uInt16 y
= nHeight
,x
;
309 nBri
= pPercent_Vert
[y
];
313 nSat
= pPercent_Horiz
[x
];
314 mxBitmap
->DrawPixel(Point(x
,y
), Color::HSBtoRGB(nHue
, nSat
, nBri
));
321 nBri
= pPercent_Vert
[y
];
325 nHue
= pGrad_Horiz
[x
];
326 mxBitmap
->DrawPixel(Point(x
,y
), Color::HSBtoRGB(nHue
, nSat
, nBri
));
333 nSat
= pPercent_Vert
[y
];
337 nHue
= pGrad_Horiz
[x
];
338 mxBitmap
->DrawPixel(Point(x
,y
), Color::HSBtoRGB(nHue
, nSat
, nBri
));
345 aBitmapColor
.SetGreen(pRGB_Vert
[y
]);
349 aBitmapColor
.SetBlue(pRGB_Horiz
[x
]);
350 mxBitmap
->DrawPixel(Point(x
,y
), aBitmapColor
);
357 aBitmapColor
.SetRed(pRGB_Vert
[y
]);
361 aBitmapColor
.SetBlue(pRGB_Horiz
[x
]);
362 mxBitmap
->DrawPixel(Point(x
,y
), aBitmapColor
);
369 aBitmapColor
.SetGreen(pRGB_Vert
[y
]);
373 aBitmapColor
.SetRed(pRGB_Horiz
[x
]);
374 mxBitmap
->DrawPixel(Point(x
,y
), aBitmapColor
);
381 void ColorFieldControl::ShowPosition( const Point
& rPos
, bool bUpdate
)
392 const Size
aSize(mxBitmap
->GetOutputSizePixel());
398 else if (nX
>= aSize
.Width())
399 nX
= aSize
.Width() - 1;
403 else if (nY
>= aSize
.Height())
404 nY
= aSize
.Height() - 1;
406 Point aPos
= maPosition
;
407 maPosition
.setX( nX
- 5 );
408 maPosition
.setY( nY
- 5 );
409 Invalidate(tools::Rectangle(aPos
, Size(11, 11)));
410 Invalidate(tools::Rectangle(maPosition
, Size(11, 11)));
414 mdX
= double(nX
) / double(aSize
.Width() - 1.0);
415 mdY
= double(aSize
.Height() - 1.0 - nY
) / double(aSize
.Height() - 1.0);
417 maColor
= mxBitmap
->GetPixel(Point(nX
, nY
));
421 bool ColorFieldControl::MouseButtonDown(const MouseEvent
& rMEvt
)
424 mbMouseCaptured
= true;
425 ShowPosition(rMEvt
.GetPosPixel(), true);
430 bool ColorFieldControl::MouseMove(const MouseEvent
& rMEvt
)
434 ShowPosition(rMEvt
.GetPosPixel(), true);
440 bool ColorFieldControl::MouseButtonUp(const MouseEvent
&)
443 mbMouseCaptured
= false;
447 void ColorFieldControl::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&)
454 Size
aSize(GetOutputSizePixel());
455 rRenderContext
.DrawOutDev(Point(0, 0), aSize
, Point(0, 0), aSize
, *mxBitmap
);
458 // draw circle around current color
459 if (maColor
.IsDark())
460 rRenderContext
.SetLineColor( COL_WHITE
);
462 rRenderContext
.SetLineColor( COL_BLACK
);
464 rRenderContext
.SetFillColor();
466 rRenderContext
.DrawEllipse(::tools::Rectangle(maPosition
, Size(11, 11)));
469 void ColorFieldControl::Resize()
471 CustomWidgetController::Resize();
476 void ColorFieldControl::Modify()
478 maModifyHdl
.Call( *this );
481 void ColorFieldControl::SetValues( Color aColor
, ColorMode eMode
, double x
, double y
)
483 bool bUpdateBitmap
= (maColor
!= aColor
) || (meMode
!= eMode
);
484 if( bUpdateBitmap
|| (mdX
!= x
) || (mdY
!= y
) )
499 void ColorFieldControl::UpdatePosition()
501 Size
aSize(GetOutputSizePixel());
502 ShowPosition(Point(static_cast<long>(mdX
* aSize
.Width()), static_cast<long>((1.0 - mdY
) * aSize
.Height())), false);
505 class ColorSliderControl
: public weld::CustomWidgetController
508 ColorSliderControl();
509 virtual ~ColorSliderControl() override
;
511 virtual void SetDrawingArea(weld::DrawingArea
* pDrawingArea
) override
;
513 virtual bool MouseButtonDown(const MouseEvent
& rMEvt
) override
;
514 virtual bool MouseMove(const MouseEvent
& rMEvt
) override
;
515 virtual bool MouseButtonUp(const MouseEvent
& rMEvt
) override
;
516 virtual void Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&) override
;
517 virtual void Resize() override
;
520 void ChangePosition( long nY
);
523 void SetValue( const Color
& rColor
, ColorMode eMode
, double dValue
);
524 double GetValue() const { return mdValue
; }
526 void SetModifyHdl( const Link
<ColorSliderControl
&,void>& rLink
) { maModifyHdl
= rLink
; }
528 sal_Int16
GetLevel() const { return mnLevel
; }
531 Link
<ColorSliderControl
&,void> maModifyHdl
;
534 VclPtr
<VirtualDevice
> mxBitmap
;
539 ColorSliderControl::ColorSliderControl()
540 : meMode( DefaultMode
)
546 void ColorSliderControl::SetDrawingArea(weld::DrawingArea
* pDrawingArea
)
548 CustomWidgetController::SetDrawingArea(pDrawingArea
);
549 pDrawingArea
->set_size_request(pDrawingArea
->get_approximate_digit_width() * 3, -1);
552 ColorSliderControl::~ColorSliderControl()
554 mxBitmap
.disposeAndClear();
557 void ColorSliderControl::UpdateBitmap()
559 Size
aSize(1, GetOutputSizePixel().Height());
561 if (mxBitmap
&& mxBitmap
->GetOutputSizePixel() != aSize
)
562 mxBitmap
.disposeAndClear();
566 mxBitmap
= VclPtr
<VirtualDevice
>::Create();
567 mxBitmap
->SetOutputSizePixel(aSize
);
570 const long nY
= aSize
.Height() - 1;
572 Color
aBitmapColor(maColor
);
574 sal_uInt16 nHue
, nSat
, nBri
;
575 maColor
.RGBtoHSB(nHue
, nSat
, nBri
);
577 // this has been unlooped for performance reason, please do not merge back!
584 for (long y
= 0; y
<= nY
; y
++)
586 nHue
= static_cast<sal_uInt16
>((359 * y
) / nY
);
587 mxBitmap
->DrawPixel(Point(0, nY
- y
), Color::HSBtoRGB(nHue
, nSat
, nBri
));
592 nBri
= std::max(sal_uInt16(32), nBri
);
593 for (long y
= 0; y
<= nY
; y
++)
595 nSat
= static_cast<sal_uInt16
>((100 * y
) / nY
);
596 mxBitmap
->DrawPixel(Point(0, nY
- y
), Color::HSBtoRGB(nHue
, nSat
, nBri
));
601 for (long y
= 0; y
<= nY
; y
++)
603 nBri
= static_cast<sal_uInt16
>((100 * y
) / nY
);
604 mxBitmap
->DrawPixel(Point(0, nY
- y
), Color::HSBtoRGB(nHue
, nSat
, nBri
));
609 for (long y
= 0; y
<= nY
; y
++)
611 aBitmapColor
.SetRed(sal_uInt8((long(255) * y
) / nY
));
612 mxBitmap
->DrawPixel(Point(0, nY
- y
), aBitmapColor
);
617 for (long y
= 0; y
<= nY
; y
++)
619 aBitmapColor
.SetGreen(sal_uInt8((long(255) * y
) / nY
));
620 mxBitmap
->DrawPixel(Point(0, nY
- y
), aBitmapColor
);
625 for (long y
= 0; y
<= nY
; y
++)
627 aBitmapColor
.SetBlue(sal_uInt8((long(255) * y
) / nY
));
628 mxBitmap
->DrawPixel(Point(0, nY
- y
), aBitmapColor
);
634 void ColorSliderControl::ChangePosition(long nY
)
636 const long nHeight
= GetOutputSizePixel().Height() - 1;
640 else if (nY
> nHeight
)
644 mdValue
= double(nHeight
- nY
) / double(nHeight
);
647 bool ColorSliderControl::MouseButtonDown(const MouseEvent
& rMEvt
)
650 ChangePosition(rMEvt
.GetPosPixel().Y());
655 bool ColorSliderControl::MouseMove(const MouseEvent
& rMEvt
)
657 if (IsMouseCaptured())
659 ChangePosition(rMEvt
.GetPosPixel().Y());
665 bool ColorSliderControl::MouseButtonUp(const MouseEvent
&)
671 void ColorSliderControl::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&)
676 const Size
aSize(GetOutputSizePixel());
679 int x
= aSize
.Width();
682 rRenderContext
.DrawOutDev(aPos
, aSize
, Point(0,0), aSize
, *mxBitmap
);
687 void ColorSliderControl::Resize()
689 CustomWidgetController::Resize();
693 void ColorSliderControl::Modify()
695 maModifyHdl
.Call(*this);
698 void ColorSliderControl::SetValue(const Color
& rColor
, ColorMode eMode
, double dValue
)
700 bool bUpdateBitmap
= (rColor
!= maColor
) || (eMode
!= meMode
);
701 if( bUpdateBitmap
|| (mdValue
!= dValue
))
705 mnLevel
= static_cast<sal_Int16
>((1.0-dValue
) * GetOutputSizePixel().Height());
713 class ColorPickerDialog
: public weld::GenericDialogController
716 ColorFieldControl m_aColorField
;
717 ColorSliderControl m_aColorSlider
;
718 ColorPreviewControl m_aColorPreview
;
719 ColorPreviewControl m_aColorPrevious
;
721 std::unique_ptr
<weld::CustomWeld
> m_xColorField
;
722 std::unique_ptr
<weld::CustomWeld
> m_xColorSlider
;
723 std::unique_ptr
<weld::CustomWeld
> m_xColorPreview
;
724 std::unique_ptr
<weld::CustomWeld
> m_xColorPrevious
;
726 std::unique_ptr
<weld::Widget
> m_xFISliderLeft
;
727 std::unique_ptr
<weld::Widget
> m_xFISliderRight
;
728 std::unique_ptr
<weld::RadioButton
> m_xRBRed
;
729 std::unique_ptr
<weld::RadioButton
> m_xRBGreen
;
730 std::unique_ptr
<weld::RadioButton
> m_xRBBlue
;
731 std::unique_ptr
<weld::RadioButton
> m_xRBHue
;
732 std::unique_ptr
<weld::RadioButton
> m_xRBSaturation
;
733 std::unique_ptr
<weld::RadioButton
> m_xRBBrightness
;
735 std::unique_ptr
<weld::SpinButton
> m_xMFRed
;
736 std::unique_ptr
<weld::SpinButton
> m_xMFGreen
;
737 std::unique_ptr
<weld::SpinButton
> m_xMFBlue
;
738 std::unique_ptr
<weld::HexColorControl
> m_xEDHex
;
740 std::unique_ptr
<weld::MetricSpinButton
> m_xMFHue
;
741 std::unique_ptr
<weld::MetricSpinButton
> m_xMFSaturation
;
742 std::unique_ptr
<weld::MetricSpinButton
> m_xMFBrightness
;
744 std::unique_ptr
<weld::MetricSpinButton
> m_xMFCyan
;
745 std::unique_ptr
<weld::MetricSpinButton
> m_xMFMagenta
;
746 std::unique_ptr
<weld::MetricSpinButton
> m_xMFYellow
;
747 std::unique_ptr
<weld::MetricSpinButton
> m_xMFKey
;
750 ColorPickerDialog(weld::Window
* pParent
, Color nColor
, sal_Int16 nMode
);
752 void update_color(UpdateFlags n
= UpdateFlags::All
);
754 DECL_LINK(ColorFieldControlModifydl
, ColorFieldControl
&, void);
755 DECL_LINK(ColorSliderControlModifyHdl
, ColorSliderControl
&, void);
756 DECL_LINK(ColorModifyMetricHdl
, weld::MetricSpinButton
&, void);
757 DECL_LINK(ColorModifySpinHdl
, weld::SpinButton
&, void);
758 DECL_LINK(ColorModifyEditHdl
, weld::Entry
&, void);
759 DECL_LINK(ModeModifyHdl
, weld::ToggleButton
&, void);
761 Color
GetColor() const;
763 void setColorComponent(ColorComponent nComp
, double dValue
);
768 double mdRed
, mdGreen
, mdBlue
;
769 double mdHue
, mdSat
, mdBri
;
770 double mdCyan
, mdMagenta
, mdYellow
, mdKey
;
773 ColorPickerDialog::ColorPickerDialog(weld::Window
* pParent
, Color nColor
, sal_Int16 nDialogMode
)
774 : GenericDialogController(pParent
, "cui/ui/colorpickerdialog.ui", "ColorPicker")
775 , m_xColorField(new weld::CustomWeld(*m_xBuilder
, "colorField", m_aColorField
))
776 , m_xColorSlider(new weld::CustomWeld(*m_xBuilder
, "colorSlider", m_aColorSlider
))
777 , m_xColorPreview(new weld::CustomWeld(*m_xBuilder
, "preview", m_aColorPreview
))
778 , m_xColorPrevious(new weld::CustomWeld(*m_xBuilder
, "previous", m_aColorPrevious
))
779 , m_xFISliderLeft(m_xBuilder
->weld_widget("leftImage"))
780 , m_xFISliderRight(m_xBuilder
->weld_widget("rightImage"))
781 , m_xRBRed(m_xBuilder
->weld_radio_button("redRadiobutton"))
782 , m_xRBGreen(m_xBuilder
->weld_radio_button("greenRadiobutton"))
783 , m_xRBBlue(m_xBuilder
->weld_radio_button("blueRadiobutton"))
784 , m_xRBHue(m_xBuilder
->weld_radio_button("hueRadiobutton"))
785 , m_xRBSaturation(m_xBuilder
->weld_radio_button("satRadiobutton"))
786 , m_xRBBrightness(m_xBuilder
->weld_radio_button("brightRadiobutton"))
787 , m_xMFRed(m_xBuilder
->weld_spin_button("redSpinbutton"))
788 , m_xMFGreen(m_xBuilder
->weld_spin_button("greenSpinbutton"))
789 , m_xMFBlue(m_xBuilder
->weld_spin_button("blueSpinbutton"))
790 , m_xEDHex(new weld::HexColorControl(m_xBuilder
->weld_entry("hexEntry")))
791 , m_xMFHue(m_xBuilder
->weld_metric_spin_button("hueSpinbutton", FieldUnit::DEGREE
))
792 , m_xMFSaturation(m_xBuilder
->weld_metric_spin_button("satSpinbutton", FieldUnit::PERCENT
))
793 , m_xMFBrightness(m_xBuilder
->weld_metric_spin_button("brightSpinbutton", FieldUnit::PERCENT
))
794 , m_xMFCyan(m_xBuilder
->weld_metric_spin_button("cyanSpinbutton", FieldUnit::PERCENT
))
795 , m_xMFMagenta(m_xBuilder
->weld_metric_spin_button("magSpinbutton", FieldUnit::PERCENT
))
796 , m_xMFYellow(m_xBuilder
->weld_metric_spin_button("yellowSpinbutton", FieldUnit::PERCENT
))
797 , m_xMFKey(m_xBuilder
->weld_metric_spin_button("keySpinbutton", FieldUnit::PERCENT
))
798 , meMode( DefaultMode
)
800 m_aColorField
.SetModifyHdl( LINK( this, ColorPickerDialog
, ColorFieldControlModifydl
) );
801 m_aColorSlider
.SetModifyHdl( LINK( this, ColorPickerDialog
, ColorSliderControlModifyHdl
) );
803 int nMargin
= (m_xFISliderLeft
->get_preferred_size().Height() + 1) / 2;
804 m_xColorSlider
->set_margin_top(nMargin
);
805 m_xColorSlider
->set_margin_bottom(nMargin
);
807 Link
<weld::MetricSpinButton
&,void> aLink3( LINK( this, ColorPickerDialog
, ColorModifyMetricHdl
) );
808 m_xMFCyan
->connect_value_changed( aLink3
);
809 m_xMFMagenta
->connect_value_changed( aLink3
);
810 m_xMFYellow
->connect_value_changed( aLink3
);
811 m_xMFKey
->connect_value_changed( aLink3
);
813 m_xMFHue
->connect_value_changed( aLink3
);
814 m_xMFSaturation
->connect_value_changed( aLink3
);
815 m_xMFBrightness
->connect_value_changed( aLink3
);
817 Link
<weld::SpinButton
&,void> aLink4(LINK(this, ColorPickerDialog
, ColorModifySpinHdl
));
818 m_xMFRed
->connect_value_changed(aLink4
);
819 m_xMFGreen
->connect_value_changed(aLink4
);
820 m_xMFBlue
->connect_value_changed(aLink4
);
822 m_xEDHex
->connect_changed(LINK(this, ColorPickerDialog
, ColorModifyEditHdl
));
824 Link
<weld::ToggleButton
&,void> aLink2
= LINK( this, ColorPickerDialog
, ModeModifyHdl
);
825 m_xRBRed
->connect_toggled( aLink2
);
826 m_xRBGreen
->connect_toggled( aLink2
);
827 m_xRBBlue
->connect_toggled( aLink2
);
828 m_xRBHue
->connect_toggled( aLink2
);
829 m_xRBSaturation
->connect_toggled( aLink2
);
830 m_xRBBrightness
->connect_toggled( aLink2
);
832 Color
aColor(nColor
);
835 if (nDialogMode
== 2)
837 m_aColorPrevious
.SetColor(aColor
);
838 m_xColorPrevious
->show();
841 mdRed
= static_cast<double>(aColor
.GetRed()) / 255.0;
842 mdGreen
= static_cast<double>(aColor
.GetGreen()) / 255.0;
843 mdBlue
= static_cast<double>(aColor
.GetBlue()) / 255.0;
845 RGBtoHSV( mdRed
, mdGreen
, mdBlue
, mdHue
, mdSat
, mdBri
);
846 RGBtoCMYK( mdRed
, mdGreen
, mdBlue
, mdCyan
, mdMagenta
, mdYellow
, mdKey
);
851 static int toInt( double dValue
, double dRange
)
853 return static_cast< int >( std::floor((dValue
* dRange
) + 0.5 ) );
856 Color
ColorPickerDialog::GetColor() const
858 return Color( toInt(mdRed
,255.0), toInt(mdGreen
,255.0), toInt(mdBlue
,255.0) );
861 void ColorPickerDialog::update_color( UpdateFlags n
)
863 sal_uInt8 nRed
= toInt(mdRed
,255.0);
864 sal_uInt8 nGreen
= toInt(mdGreen
,255.0);
865 sal_uInt8 nBlue
= toInt(mdBlue
,255.0);
867 Color
aColor(nRed
, nGreen
, nBlue
);
869 if (n
& UpdateFlags::RGB
) // update RGB
871 m_xMFRed
->set_value(nRed
);
872 m_xMFGreen
->set_value(nGreen
);
873 m_xMFBlue
->set_value(nBlue
);
876 if (n
& UpdateFlags::CMYK
) // update CMYK
878 m_xMFCyan
->set_value(toInt(mdCyan
, 100.0), FieldUnit::PERCENT
);
879 m_xMFMagenta
->set_value(toInt(mdMagenta
, 100.0), FieldUnit::PERCENT
);
880 m_xMFYellow
->set_value(toInt(mdYellow
, 100.0), FieldUnit::PERCENT
);
881 m_xMFKey
->set_value(toInt(mdKey
, 100.0), FieldUnit::PERCENT
);
884 if (n
& UpdateFlags::HSB
) // update HSB
886 m_xMFHue
->set_value(toInt(mdHue
, 1.0), FieldUnit::DEGREE
);
887 m_xMFSaturation
->set_value(toInt( mdSat
, 100.0), FieldUnit::PERCENT
);
888 m_xMFBrightness
->set_value(toInt( mdBri
, 100.0), FieldUnit::PERCENT
);
891 if (n
& UpdateFlags::ColorChooser
) // update Color Chooser 1
896 m_aColorField
.SetValues(aColor
, meMode
, mdSat
, mdBri
);
899 m_aColorField
.SetValues(aColor
, meMode
, mdHue
/ 360.0, mdBri
);
902 m_aColorField
.SetValues(aColor
, meMode
, mdHue
/ 360.0, mdSat
);
905 m_aColorField
.SetValues(aColor
, meMode
, mdBlue
, mdGreen
);
908 m_aColorField
.SetValues(aColor
, meMode
, mdBlue
, mdRed
);
911 m_aColorField
.SetValues(aColor
, meMode
, mdRed
, mdGreen
);
916 if (n
& UpdateFlags::ColorSlider
) // update Color Chooser 2
921 m_aColorSlider
.SetValue(aColor
, meMode
, mdHue
/ 360.0);
924 m_aColorSlider
.SetValue(aColor
, meMode
, mdSat
);
927 m_aColorSlider
.SetValue(aColor
, meMode
, mdBri
);
930 m_aColorSlider
.SetValue(aColor
, meMode
, mdRed
);
933 m_aColorSlider
.SetValue(aColor
, meMode
, mdGreen
);
936 m_aColorSlider
.SetValue(aColor
, meMode
, mdBlue
);
941 if (n
& UpdateFlags::Hex
) // update hex
943 m_xFISliderLeft
->set_margin_top(m_aColorSlider
.GetLevel());
944 m_xFISliderRight
->set_margin_top(m_aColorSlider
.GetLevel());
945 m_xEDHex
->SetColor(aColor
);
947 m_aColorPreview
.SetColor(aColor
);
950 IMPL_LINK_NOARG(ColorPickerDialog
, ColorFieldControlModifydl
, ColorFieldControl
&, void)
952 double x
= m_aColorField
.GetX();
953 double y
= m_aColorField
.GetY();
959 setColorComponent( ColorComponent::Brightness
, y
);
963 setColorComponent( ColorComponent::Brightness
, y
);
967 setColorComponent( ColorComponent::Saturation
, y
);
971 setColorComponent( ColorComponent::Green
, y
);
975 setColorComponent( ColorComponent::Red
, y
);
979 setColorComponent( ColorComponent::Green
, y
);
983 update_color(UpdateFlags::All
& ~UpdateFlags::ColorChooser
);
986 IMPL_LINK_NOARG(ColorPickerDialog
, ColorSliderControlModifyHdl
, ColorSliderControl
&, void)
988 double dValue
= m_aColorSlider
.GetValue();
992 setColorComponent( ColorComponent::Hue
, dValue
* 360.0 );
995 setColorComponent( ColorComponent::Saturation
, dValue
);
998 setColorComponent( ColorComponent::Brightness
, dValue
);
1001 setColorComponent( ColorComponent::Red
, dValue
);
1004 setColorComponent( ColorComponent::Green
, dValue
);
1007 setColorComponent( ColorComponent::Blue
, dValue
);
1011 update_color(UpdateFlags::All
& ~UpdateFlags::ColorSlider
);
1014 IMPL_LINK(ColorPickerDialog
, ColorModifyMetricHdl
, weld::MetricSpinButton
&, rEdit
, void)
1016 UpdateFlags n
= UpdateFlags::NONE
;
1018 if (&rEdit
== m_xMFHue
.get())
1020 setColorComponent( ColorComponent::Hue
, static_cast<double>(m_xMFHue
->get_value(FieldUnit::DEGREE
)) );
1021 n
= UpdateFlags::All
& ~UpdateFlags::HSB
;
1023 else if (&rEdit
== m_xMFSaturation
.get())
1025 setColorComponent( ColorComponent::Saturation
, static_cast<double>(m_xMFSaturation
->get_value(FieldUnit::PERCENT
)) / 100.0 );
1026 n
= UpdateFlags::All
& ~UpdateFlags::HSB
;
1028 else if (&rEdit
== m_xMFBrightness
.get())
1030 setColorComponent( ColorComponent::Brightness
, static_cast<double>(m_xMFBrightness
->get_value(FieldUnit::PERCENT
)) / 100.0 );
1031 n
= UpdateFlags::All
& ~UpdateFlags::HSB
;
1033 else if (&rEdit
== m_xMFCyan
.get())
1035 setColorComponent( ColorComponent::Cyan
, static_cast<double>(m_xMFCyan
->get_value(FieldUnit::PERCENT
)) / 100.0 );
1036 n
= UpdateFlags::All
& ~UpdateFlags::CMYK
;
1038 else if (&rEdit
== m_xMFMagenta
.get())
1040 setColorComponent( ColorComponent::Magenta
, static_cast<double>(m_xMFMagenta
->get_value(FieldUnit::PERCENT
)) / 100.0 );
1041 n
= UpdateFlags::All
& ~UpdateFlags::CMYK
;
1043 else if (&rEdit
== m_xMFYellow
.get())
1045 setColorComponent( ColorComponent::Yellow
, static_cast<double>(m_xMFYellow
->get_value(FieldUnit::PERCENT
)) / 100.0 );
1046 n
= UpdateFlags::All
& ~UpdateFlags::CMYK
;
1048 else if (&rEdit
== m_xMFKey
.get())
1050 setColorComponent( ColorComponent::Key
, static_cast<double>(m_xMFKey
->get_value(FieldUnit::PERCENT
)) / 100.0 );
1051 n
= UpdateFlags::All
& ~UpdateFlags::CMYK
;
1054 if (n
!= UpdateFlags::NONE
)
1058 IMPL_LINK_NOARG(ColorPickerDialog
, ColorModifyEditHdl
, weld::Entry
&, void)
1060 UpdateFlags n
= UpdateFlags::NONE
;
1062 Color aColor
= m_xEDHex
->GetColor();
1064 if (aColor
!= Color(0xffffffff) && aColor
!= GetColor())
1066 mdRed
= static_cast<double>(aColor
.GetRed()) / 255.0;
1067 mdGreen
= static_cast<double>(aColor
.GetGreen()) / 255.0;
1068 mdBlue
= static_cast<double>(aColor
.GetBlue()) / 255.0;
1070 RGBtoHSV( mdRed
, mdGreen
, mdBlue
, mdHue
, mdSat
, mdBri
);
1071 RGBtoCMYK( mdRed
, mdGreen
, mdBlue
, mdCyan
, mdMagenta
, mdYellow
, mdKey
);
1072 n
= UpdateFlags::All
& ~UpdateFlags::Hex
;
1075 if (n
!= UpdateFlags::NONE
)
1079 IMPL_LINK(ColorPickerDialog
, ColorModifySpinHdl
, weld::SpinButton
&, rEdit
, void)
1081 UpdateFlags n
= UpdateFlags::NONE
;
1083 if (&rEdit
== m_xMFRed
.get())
1085 setColorComponent( ColorComponent::Red
, static_cast<double>(m_xMFRed
->get_value()) / 255.0 );
1086 n
= UpdateFlags::All
& ~UpdateFlags::RGB
;
1088 else if (&rEdit
== m_xMFGreen
.get())
1090 setColorComponent( ColorComponent::Green
, static_cast<double>(m_xMFGreen
->get_value()) / 255.0 );
1091 n
= UpdateFlags::All
& ~UpdateFlags::RGB
;
1093 else if (&rEdit
== m_xMFBlue
.get())
1095 setColorComponent( ColorComponent::Blue
, static_cast<double>(m_xMFBlue
->get_value()) / 255.0 );
1096 n
= UpdateFlags::All
& ~UpdateFlags::RGB
;
1099 if (n
!= UpdateFlags::NONE
)
1104 IMPL_LINK_NOARG(ColorPickerDialog
, ModeModifyHdl
, weld::ToggleButton
&, void)
1106 ColorMode eMode
= HUE
;
1108 if (m_xRBRed
->get_active())
1112 else if (m_xRBGreen
->get_active())
1116 else if (m_xRBBlue
->get_active())
1120 else if (m_xRBSaturation
->get_active())
1124 else if (m_xRBBrightness
->get_active())
1129 if (meMode
!= eMode
)
1132 update_color(UpdateFlags::ColorChooser
| UpdateFlags::ColorSlider
);
1136 void ColorPickerDialog::setColorComponent( ColorComponent nComp
, double dValue
)
1140 case ColorComponent::Red
:
1143 case ColorComponent::Green
:
1146 case ColorComponent::Blue
:
1149 case ColorComponent::Hue
:
1152 case ColorComponent::Saturation
:
1155 case ColorComponent::Brightness
:
1158 case ColorComponent::Cyan
:
1161 case ColorComponent::Yellow
:
1164 case ColorComponent::Magenta
:
1167 case ColorComponent::Key
:
1172 if (nComp
== ColorComponent::Red
|| nComp
== ColorComponent::Green
|| nComp
== ColorComponent::Blue
)
1174 RGBtoHSV( mdRed
, mdGreen
, mdBlue
, mdHue
, mdSat
, mdBri
);
1175 RGBtoCMYK( mdRed
, mdGreen
, mdBlue
, mdCyan
, mdMagenta
, mdYellow
, mdKey
);
1177 else if (nComp
== ColorComponent::Hue
|| nComp
== ColorComponent::Saturation
|| nComp
== ColorComponent::Brightness
)
1179 HSVtoRGB( mdHue
, mdSat
, mdBri
, mdRed
, mdGreen
, mdBlue
);
1180 RGBtoCMYK( mdRed
, mdGreen
, mdBlue
, mdCyan
, mdMagenta
, mdYellow
, mdKey
);
1184 CMYKtoRGB( mdCyan
, mdMagenta
, mdYellow
, mdKey
, mdRed
, mdGreen
, mdBlue
);
1185 RGBtoHSV( mdRed
, mdGreen
, mdBlue
, mdHue
, mdSat
, mdBri
);
1189 typedef ::cppu::WeakComponentImplHelper
< XServiceInfo
, XExecutableDialog
, XInitialization
, XPropertyAccess
> ColorPickerBase
;
1191 class ColorPicker
: protected ::cppu::BaseMutex
, // Struct for right initialization of mutex member! Must be first of baseclasses.
1192 public ColorPickerBase
1195 explicit ColorPicker();
1198 virtual void SAL_CALL
initialize( const Sequence
< Any
>& aArguments
) override
;
1201 virtual OUString SAL_CALL
getImplementationName( ) override
;
1202 virtual sal_Bool SAL_CALL
supportsService( const OUString
& ServiceName
) override
;
1203 virtual Sequence
< OUString
> SAL_CALL
getSupportedServiceNames( ) override
;
1206 virtual Sequence
< PropertyValue
> SAL_CALL
getPropertyValues( ) override
;
1207 virtual void SAL_CALL
setPropertyValues( const Sequence
< PropertyValue
>& aProps
) override
;
1209 // XExecutableDialog
1210 virtual void SAL_CALL
setTitle( const OUString
& aTitle
) override
;
1211 virtual sal_Int16 SAL_CALL
execute( ) override
;
1216 Reference
<css::awt::XWindow
> mxParent
;
1219 OUString
ColorPicker_getImplementationName()
1221 return OUString( "com.sun.star.cui.ColorPicker" );
1224 Reference
< XInterface
> ColorPicker_createInstance( Reference
< XComponentContext
> const & )
1226 return static_cast<XWeak
*>( new ColorPicker
);
1229 Sequence
< OUString
> ColorPicker_getSupportedServiceNames()
1231 Sequence
< OUString
> seq
{ "com.sun.star.ui.dialogs.ColorPicker" };
1235 static const OUStringLiteral
gsColorKey( "Color" );
1236 static const OUStringLiteral
gsModeKey( "Mode" );
1238 ColorPicker::ColorPicker()
1239 : ColorPickerBase( m_aMutex
)
1246 void SAL_CALL
ColorPicker::initialize( const Sequence
< Any
>& aArguments
)
1248 if( aArguments
.getLength() == 1 )
1250 aArguments
[0] >>= mxParent
;
1255 OUString SAL_CALL
ColorPicker::getImplementationName( )
1257 return ColorPicker_getImplementationName();
1260 sal_Bool SAL_CALL
ColorPicker::supportsService( const OUString
& sServiceName
)
1262 return cppu::supportsService(this, sServiceName
);
1265 Sequence
< OUString
> SAL_CALL
ColorPicker::getSupportedServiceNames( )
1267 return ColorPicker_getSupportedServiceNames();
1271 Sequence
< PropertyValue
> SAL_CALL
ColorPicker::getPropertyValues( )
1273 Sequence
< PropertyValue
> props(1);
1274 props
[0].Name
= gsColorKey
;
1275 props
[0].Value
<<= mnColor
;
1279 void SAL_CALL
ColorPicker::setPropertyValues( const Sequence
< PropertyValue
>& aProps
)
1281 for( sal_Int32 n
= 0; n
< aProps
.getLength(); n
++ )
1283 if( aProps
[n
].Name
== gsColorKey
)
1285 aProps
[n
].Value
>>= mnColor
;
1287 else if( aProps
[n
].Name
== gsModeKey
)
1289 aProps
[n
].Value
>>= mnMode
;
1294 // XExecutableDialog
1295 void SAL_CALL
ColorPicker::setTitle( const OUString
& )
1299 sal_Int16 SAL_CALL
ColorPicker::execute()
1301 std::unique_ptr
<ColorPickerDialog
> xDlg(new ColorPickerDialog(Application::GetFrameWeld(mxParent
), mnColor
, mnMode
));
1302 sal_Int16 ret
= xDlg
->run();
1304 mnColor
= xDlg
->GetColor();
1310 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */