1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
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 <cmath>
37 #include <o3tl/typed_flags_set.hxx>
38 
39 using namespace ::com::sun::star::uno;
40 using namespace ::com::sun::star::lang;
41 using namespace ::com::sun::star::ui::dialogs;
42 using namespace ::com::sun::star::beans;
43 using namespace ::basegfx;
44 
45 namespace {
46 
47 enum class UpdateFlags
48 {
49     NONE         = 0x00,
50     RGB          = 0x01,
51     CMYK         = 0x02,
52     HSB          = 0x04,
53     ColorChooser = 0x08,
54     ColorSlider  = 0x10,
55     Hex          = 0x20,
56     All          = 0x3f,
57 };
58 
59 }
60 
61 namespace o3tl {
62     template<> struct typed_flags<UpdateFlags> : is_typed_flags<UpdateFlags, 0x3f> {};
63 }
64 
65 
66 namespace cui
67 {
68 
69 namespace {
70 
71 enum class ColorComponent {
72     Red,
73     Green,
74     Blue,
75     Hue,
76     Saturation,
77     Brightness,
78     Cyan,
79     Yellow,
80     Magenta,
81     Key,
82 };
83 
84 }
85 
86 // color space conversion helpers
87 
RGBtoHSV(double dR,double dG,double dB,double & dH,double & dS,double & dV)88 static void RGBtoHSV( double dR, double dG, double dB, double& dH, double& dS, double& dV )
89 {
90     BColor result = basegfx::utils::rgb2hsv( BColor( dR, dG, dB ) );
91 
92     dH = result.getX();
93     dS = result.getY();
94     dV = result.getZ();
95 }
96 
HSVtoRGB(double dH,double dS,double dV,double & dR,double & dG,double & dB)97 static void HSVtoRGB(double dH, double dS, double dV, double& dR, double& dG, double& dB )
98 {
99     BColor result = basegfx::utils::hsv2rgb( BColor( dH, dS, dV ) );
100 
101     dR = result.getRed();
102     dG = result.getGreen();
103     dB = result.getBlue();
104 }
105 
106 // CMYK values from 0 to 1
CMYKtoRGB(double fCyan,double fMagenta,double fYellow,double fKey,double & dR,double & dG,double & dB)107 static void CMYKtoRGB( double fCyan, double fMagenta, double fYellow, double fKey, double& dR, double& dG, double& dB )
108 {
109     fCyan = (fCyan * ( 1.0 - fKey )) + fKey;
110     fMagenta = (fMagenta * ( 1.0 - fKey )) + fKey;
111     fYellow = (fYellow * ( 1.0 - fKey )) + fKey;
112 
113     dR = std::clamp( 1.0 - fCyan, 0.0, 1.0 );
114     dG = std::clamp( 1.0 - fMagenta, 0.0, 1.0 );
115     dB = std::clamp( 1.0 - fYellow, 0.0, 1.0 );
116 }
117 
118 // CMY results from 0 to 1
RGBtoCMYK(double dR,double dG,double dB,double & fCyan,double & fMagenta,double & fYellow,double & fKey)119 static void RGBtoCMYK( double dR, double dG, double dB, double& fCyan, double& fMagenta, double& fYellow, double& fKey )
120 {
121     fCyan = 1 - dR;
122     fMagenta = 1 - dG;
123     fYellow = 1 - dB;
124 
125     //CMYK and CMY values from 0 to 1
126     fKey = 1.0;
127     if( fCyan < fKey ) fKey = fCyan;
128     if( fMagenta < fKey ) fKey = fMagenta;
129     if( fYellow < fKey ) fKey = fYellow;
130 
131     if( fKey >= 1.0 )
132     {
133         //Black
134        fCyan = 0.0;
135        fMagenta = 0.0;
136        fYellow = 0.0;
137     }
138     else
139     {
140        fCyan = ( fCyan - fKey ) / ( 1.0 - fKey );
141        fMagenta = ( fMagenta - fKey ) / ( 1.0 - fKey );
142        fYellow = ( fYellow - fKey ) / ( 1.0 - fKey );
143     }
144 }
145 
146 namespace {
147 
148 class ColorPreviewControl : public weld::CustomWidgetController
149 {
150 private:
151     Color m_aColor;
152 
153     virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&) override;
154 public:
ColorPreviewControl()155     ColorPreviewControl()
156     {
157     }
158 
SetDrawingArea(weld::DrawingArea * pDrawingArea)159     virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override
160     {
161         CustomWidgetController::SetDrawingArea(pDrawingArea);
162         pDrawingArea->set_size_request(pDrawingArea->get_approximate_digit_width() * 10,
163                                        pDrawingArea->get_text_height() * 2);
164     }
165 
SetColor(const Color & rCol)166     void SetColor(const Color& rCol)
167     {
168         if (rCol != m_aColor)
169         {
170             m_aColor = rCol;
171             Invalidate();
172         }
173     }
174 };
175 
176 }
177 
Paint(vcl::RenderContext & rRenderContext,const tools::Rectangle &)178 void ColorPreviewControl::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
179 {
180     rRenderContext.SetFillColor(m_aColor);
181     rRenderContext.SetLineColor(m_aColor);
182     rRenderContext.DrawRect(tools::Rectangle(Point(0, 0), GetOutputSizePixel()));
183 }
184 
185 namespace {
186 
187 enum ColorMode { HUE, SATURATION, BRIGHTNESS, RED, GREEN, BLUE };
188 
189 }
190 
191 const ColorMode DefaultMode = HUE;
192 
193 namespace {
194 
195 class ColorFieldControl : public weld::CustomWidgetController
196 {
197 public:
ColorFieldControl()198     ColorFieldControl()
199         : meMode( DefaultMode )
200         , mdX( -1.0 )
201         , mdY( -1.0 )
202         , mbMouseCaptured(false)
203     {
204     }
205 
SetDrawingArea(weld::DrawingArea * pDrawingArea)206     virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override
207     {
208         CustomWidgetController::SetDrawingArea(pDrawingArea);
209         pDrawingArea->set_size_request(pDrawingArea->get_approximate_digit_width() * 40,
210                                        pDrawingArea->get_text_height() * 10);
211     }
212 
~ColorFieldControl()213     virtual ~ColorFieldControl() override
214     {
215         mxBitmap.disposeAndClear();
216     }
217 
218     virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override;
219     virtual void Resize() override;
220     virtual bool MouseButtonDown(const MouseEvent& rMEvt) override;
221     virtual bool MouseMove(const MouseEvent& rMEvt) override;
222     virtual bool MouseButtonUp(const MouseEvent& rMEvt) override;
223 
224     void UpdateBitmap();
225     void ShowPosition( const Point& rPos, bool bUpdate );
226     void UpdatePosition();
227     void Modify();
228 
229     void SetValues(Color aColor, ColorMode eMode, double x, double y);
GetX() const230     double GetX() const { return mdX;}
GetY() const231     double GetY() const { return mdY;}
232 
SetModifyHdl(const Link<ColorFieldControl &,void> & rLink)233     void SetModifyHdl(const Link<ColorFieldControl&,void>& rLink) { maModifyHdl = rLink; }
234 
235 private:
236     ColorMode meMode;
237     Color maColor;
238     double mdX;
239     double mdY;
240     bool mbMouseCaptured;
241     Point maPosition;
242     VclPtr<VirtualDevice> mxBitmap;
243     Link<ColorFieldControl&,void> maModifyHdl;
244     std::vector<sal_uInt8>  maRGB_Horiz;
245     std::vector<sal_uInt16> maGrad_Horiz;
246     std::vector<sal_uInt16> maPercent_Horiz;
247     std::vector<sal_uInt8>  maRGB_Vert;
248     std::vector<sal_uInt16> maPercent_Vert;
249 };
250 
251 }
252 
UpdateBitmap()253 void ColorFieldControl::UpdateBitmap()
254 {
255     const Size aSize(GetOutputSizePixel());
256 
257     if (mxBitmap && mxBitmap->GetOutputSizePixel() != aSize)
258         mxBitmap.disposeAndClear();
259 
260     const sal_Int32 nWidth = aSize.Width();
261     const sal_Int32 nHeight = aSize.Height();
262 
263     if (nWidth == 0 || nHeight == 0)
264         return;
265 
266     if (!mxBitmap)
267     {
268         mxBitmap = VclPtr<VirtualDevice>::Create();
269         mxBitmap->SetOutputSizePixel(aSize);
270 
271         maRGB_Horiz.resize( nWidth );
272         maGrad_Horiz.resize( nWidth );
273         maPercent_Horiz.resize( nWidth );
274 
275         sal_uInt8* pRGB = maRGB_Horiz.data();
276         sal_uInt16* pGrad = maGrad_Horiz.data();
277         sal_uInt16* pPercent = maPercent_Horiz.data();
278 
279         for( sal_Int32 x = 0; x < nWidth; x++ )
280         {
281             *pRGB++ = static_cast<sal_uInt8>((x * 256) / nWidth);
282             *pGrad++ = static_cast<sal_uInt16>((x * 359) / nWidth);
283             *pPercent++ = static_cast<sal_uInt16>((x * 100) / nWidth);
284         }
285 
286         maRGB_Vert.resize(nHeight);
287         maPercent_Vert.resize(nHeight);
288 
289         pRGB = maRGB_Vert.data();
290         pPercent = maPercent_Vert.data();
291 
292         sal_Int32 y = nHeight;
293         while (y--)
294         {
295             *pRGB++ = static_cast<sal_uInt8>((y * 256) / nHeight);
296             *pPercent++ = static_cast<sal_uInt16>((y * 100) / nHeight);
297         }
298     }
299 
300     sal_uInt8* pRGB_Horiz = maRGB_Horiz.data();
301     sal_uInt16* pGrad_Horiz = maGrad_Horiz.data();
302     sal_uInt16* pPercent_Horiz = maPercent_Horiz.data();
303     sal_uInt8* pRGB_Vert = maRGB_Vert.data();
304     sal_uInt16* pPercent_Vert = maPercent_Vert.data();
305 
306     Color aBitmapColor(maColor);
307 
308     sal_uInt16 nHue, nSat, nBri;
309     maColor.RGBtoHSB(nHue, nSat, nBri);
310 
311         // this has been unlooped for performance reason, please do not merge back!
312 
313     sal_uInt16 y = nHeight,x;
314 
315     switch(meMode)
316     {
317         case HUE:
318             while (y--)
319             {
320                 nBri = pPercent_Vert[y];
321                 x = nWidth;
322                 while (x--)
323                 {
324                     nSat = pPercent_Horiz[x];
325                     mxBitmap->DrawPixel(Point(x,y), Color::HSBtoRGB(nHue, nSat, nBri));
326                 }
327             }
328             break;
329         case SATURATION:
330             while (y--)
331             {
332                 nBri = pPercent_Vert[y];
333                 x = nWidth;
334                 while (x--)
335                 {
336                     nHue = pGrad_Horiz[x];
337                     mxBitmap->DrawPixel(Point(x,y), Color::HSBtoRGB(nHue, nSat, nBri));
338                 }
339             }
340             break;
341         case BRIGHTNESS:
342             while (y--)
343             {
344                 nSat = pPercent_Vert[y];
345                 x = nWidth;
346                 while (x--)
347                 {
348                     nHue = pGrad_Horiz[x];
349                     mxBitmap->DrawPixel(Point(x,y), Color::HSBtoRGB(nHue, nSat, nBri));
350                 }
351             }
352             break;
353         case RED:
354             while (y--)
355             {
356                 aBitmapColor.SetGreen(pRGB_Vert[y]);
357                 x = nWidth;
358                 while (x--)
359                 {
360                     aBitmapColor.SetBlue(pRGB_Horiz[x]);
361                     mxBitmap->DrawPixel(Point(x,y), aBitmapColor);
362                 }
363             }
364             break;
365         case GREEN:
366             while (y--)
367             {
368                 aBitmapColor.SetRed(pRGB_Vert[y]);
369                 x = nWidth;
370                 while (x--)
371                 {
372                     aBitmapColor.SetBlue(pRGB_Horiz[x]);
373                     mxBitmap->DrawPixel(Point(x,y), aBitmapColor);
374                 }
375             }
376             break;
377         case BLUE:
378             while (y--)
379             {
380                 aBitmapColor.SetGreen(pRGB_Vert[y]);
381                 x = nWidth;
382                 while (x--)
383                 {
384                     aBitmapColor.SetRed(pRGB_Horiz[x]);
385                     mxBitmap->DrawPixel(Point(x,y), aBitmapColor);
386                 }
387             }
388             break;
389     }
390 }
391 
ShowPosition(const Point & rPos,bool bUpdate)392 void ColorFieldControl::ShowPosition( const Point& rPos, bool bUpdate )
393 {
394     if (!mxBitmap)
395     {
396         UpdateBitmap();
397         Invalidate();
398     }
399 
400     if (!mxBitmap)
401         return;
402 
403     const Size aSize(mxBitmap->GetOutputSizePixel());
404 
405     tools::Long nX = rPos.X();
406     tools::Long nY = rPos.Y();
407     if (nX < 0)
408         nX = 0;
409     else if (nX >= aSize.Width())
410         nX = aSize.Width() - 1;
411 
412     if (nY < 0)
413         nY = 0;
414     else if (nY >= aSize.Height())
415         nY = aSize.Height() - 1;
416 
417     Point aPos = maPosition;
418     maPosition.setX( nX - 5 );
419     maPosition.setY( nY - 5 );
420     Invalidate(tools::Rectangle(aPos, Size(11, 11)));
421     Invalidate(tools::Rectangle(maPosition, Size(11, 11)));
422 
423     if (bUpdate)
424     {
425         mdX = double(nX) / double(aSize.Width() - 1.0);
426         mdY = double(aSize.Height() - 1.0 - nY) / double(aSize.Height() - 1.0);
427 
428         maColor = mxBitmap->GetPixel(Point(nX, nY));
429     }
430 }
431 
MouseButtonDown(const MouseEvent & rMEvt)432 bool ColorFieldControl::MouseButtonDown(const MouseEvent& rMEvt)
433 {
434     CaptureMouse();
435     mbMouseCaptured = true;
436     ShowPosition(rMEvt.GetPosPixel(), true);
437     Modify();
438     return true;
439 }
440 
MouseMove(const MouseEvent & rMEvt)441 bool ColorFieldControl::MouseMove(const MouseEvent& rMEvt)
442 {
443     if (mbMouseCaptured)
444     {
445         ShowPosition(rMEvt.GetPosPixel(), true);
446         Modify();
447     }
448     return true;
449 }
450 
MouseButtonUp(const MouseEvent &)451 bool ColorFieldControl::MouseButtonUp(const MouseEvent&)
452 {
453     ReleaseMouse();
454     mbMouseCaptured = false;
455     return true;
456 }
457 
Paint(vcl::RenderContext & rRenderContext,const tools::Rectangle &)458 void ColorFieldControl::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
459 {
460     if (!mxBitmap)
461         UpdateBitmap();
462 
463     if (mxBitmap)
464     {
465         Size aSize(GetOutputSizePixel());
466         rRenderContext.DrawOutDev(Point(0, 0), aSize, Point(0, 0), aSize, *mxBitmap);
467     }
468 
469     // draw circle around current color
470     if (maColor.IsDark())
471         rRenderContext.SetLineColor( COL_WHITE );
472     else
473         rRenderContext.SetLineColor( COL_BLACK );
474 
475     rRenderContext.SetFillColor();
476 
477     rRenderContext.DrawEllipse(::tools::Rectangle(maPosition, Size(11, 11)));
478 }
479 
Resize()480 void ColorFieldControl::Resize()
481 {
482     CustomWidgetController::Resize();
483     UpdateBitmap();
484     UpdatePosition();
485 }
486 
Modify()487 void ColorFieldControl::Modify()
488 {
489     maModifyHdl.Call( *this );
490 }
491 
SetValues(Color aColor,ColorMode eMode,double x,double y)492 void ColorFieldControl::SetValues( Color aColor, ColorMode eMode, double x, double y )
493 {
494     bool bUpdateBitmap = (maColor!= aColor) || (meMode != eMode);
495     if( !(bUpdateBitmap || (mdX != x) || (mdY != y)) )
496         return;
497 
498     maColor = aColor;
499     meMode = eMode;
500     mdX = x;
501     mdY = y;
502 
503     if (bUpdateBitmap)
504         UpdateBitmap();
505     UpdatePosition();
506     if (bUpdateBitmap)
507         Invalidate();
508 }
509 
UpdatePosition()510 void ColorFieldControl::UpdatePosition()
511 {
512     Size aSize(GetOutputSizePixel());
513     ShowPosition(Point(static_cast<tools::Long>(mdX * aSize.Width()), static_cast<tools::Long>((1.0 - mdY) * aSize.Height())), false);
514 }
515 
516 namespace {
517 
518 class ColorSliderControl : public weld::CustomWidgetController
519 {
520 public:
521     ColorSliderControl();
522     virtual ~ColorSliderControl() override;
523 
524     virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override;
525 
526     virtual bool MouseButtonDown(const MouseEvent& rMEvt) override;
527     virtual bool MouseMove(const MouseEvent& rMEvt) override;
528     virtual bool MouseButtonUp(const MouseEvent& rMEvt) override;
529     virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&) override;
530     virtual void Resize() override;
531 
532     void UpdateBitmap();
533     void ChangePosition( tools::Long nY );
534     void Modify();
535 
536     void SetValue( const Color& rColor, ColorMode eMode, double dValue );
GetValue() const537     double GetValue() const { return mdValue; }
538 
SetModifyHdl(const Link<ColorSliderControl &,void> & rLink)539     void SetModifyHdl( const Link<ColorSliderControl&,void>& rLink ) { maModifyHdl = rLink; }
540 
GetLevel() const541     sal_Int16 GetLevel() const { return mnLevel; }
542 
543 private:
544     Link<ColorSliderControl&,void> maModifyHdl;
545     Color maColor;
546     ColorMode meMode;
547     VclPtr<VirtualDevice> mxBitmap;
548     sal_Int16 mnLevel;
549     double mdValue;
550 };
551 
552 }
553 
ColorSliderControl()554 ColorSliderControl::ColorSliderControl()
555     : meMode( DefaultMode )
556     , mnLevel( 0 )
557     , mdValue( -1.0 )
558 {
559 }
560 
SetDrawingArea(weld::DrawingArea * pDrawingArea)561 void ColorSliderControl::SetDrawingArea(weld::DrawingArea* pDrawingArea)
562 {
563     CustomWidgetController::SetDrawingArea(pDrawingArea);
564     pDrawingArea->set_size_request(pDrawingArea->get_approximate_digit_width() * 3, -1);
565 }
566 
~ColorSliderControl()567 ColorSliderControl::~ColorSliderControl()
568 {
569     mxBitmap.disposeAndClear();
570 }
571 
UpdateBitmap()572 void ColorSliderControl::UpdateBitmap()
573 {
574     Size aSize(1, GetOutputSizePixel().Height());
575 
576     if (mxBitmap && mxBitmap->GetOutputSizePixel() != aSize)
577         mxBitmap.disposeAndClear();
578 
579     if (!mxBitmap)
580     {
581         mxBitmap = VclPtr<VirtualDevice>::Create();
582         mxBitmap->SetOutputSizePixel(aSize);
583     }
584 
585     const tools::Long nY = aSize.Height() - 1;
586 
587     Color aBitmapColor(maColor);
588 
589     sal_uInt16 nHue, nSat, nBri;
590     maColor.RGBtoHSB(nHue, nSat, nBri);
591 
592     // this has been unlooped for performance reason, please do not merge back!
593 
594     switch (meMode)
595     {
596     case HUE:
597         nSat = 100;
598         nBri = 100;
599         for (tools::Long y = 0; y <= nY; y++)
600         {
601             nHue = static_cast<sal_uInt16>((359 * y) / nY);
602             mxBitmap->DrawPixel(Point(0, nY - y), Color::HSBtoRGB(nHue, nSat, nBri));
603         }
604         break;
605 
606     case SATURATION:
607         nBri = std::max(sal_uInt16(32), nBri);
608         for (tools::Long y = 0; y <= nY; y++)
609         {
610             nSat = static_cast<sal_uInt16>((100 * y) / nY);
611             mxBitmap->DrawPixel(Point(0, nY - y), Color::HSBtoRGB(nHue, nSat, nBri));
612         }
613         break;
614 
615     case BRIGHTNESS:
616         for (tools::Long y = 0; y <= nY; y++)
617         {
618             nBri = static_cast<sal_uInt16>((100 * y) / nY);
619             mxBitmap->DrawPixel(Point(0, nY - y), Color::HSBtoRGB(nHue, nSat, nBri));
620         }
621         break;
622 
623     case RED:
624         for (tools::Long y = 0; y <= nY; y++)
625         {
626             aBitmapColor.SetRed(sal_uInt8((tools::Long(255) * y) / nY));
627             mxBitmap->DrawPixel(Point(0, nY - y), aBitmapColor);
628         }
629         break;
630 
631     case GREEN:
632         for (tools::Long y = 0; y <= nY; y++)
633         {
634             aBitmapColor.SetGreen(sal_uInt8((tools::Long(255) * y) / nY));
635             mxBitmap->DrawPixel(Point(0, nY - y), aBitmapColor);
636         }
637         break;
638 
639     case BLUE:
640         for (tools::Long y = 0; y <= nY; y++)
641         {
642             aBitmapColor.SetBlue(sal_uInt8((tools::Long(255) * y) / nY));
643             mxBitmap->DrawPixel(Point(0, nY - y), aBitmapColor);
644         }
645         break;
646     }
647 }
648 
ChangePosition(tools::Long nY)649 void ColorSliderControl::ChangePosition(tools::Long nY)
650 {
651     const tools::Long nHeight = GetOutputSizePixel().Height() - 1;
652 
653     if (nY < 0)
654         nY = 0;
655     else if (nY > nHeight)
656         nY = nHeight;
657 
658     mnLevel = nY;
659     mdValue = double(nHeight - nY) / double(nHeight);
660 }
661 
MouseButtonDown(const MouseEvent & rMEvt)662 bool ColorSliderControl::MouseButtonDown(const MouseEvent& rMEvt)
663 {
664     CaptureMouse();
665     ChangePosition(rMEvt.GetPosPixel().Y());
666     Modify();
667     return true;
668 }
669 
MouseMove(const MouseEvent & rMEvt)670 bool ColorSliderControl::MouseMove(const MouseEvent& rMEvt)
671 {
672     if (IsMouseCaptured())
673     {
674         ChangePosition(rMEvt.GetPosPixel().Y());
675         Modify();
676     }
677     return true;
678 }
679 
MouseButtonUp(const MouseEvent &)680 bool ColorSliderControl::MouseButtonUp(const MouseEvent&)
681 {
682     ReleaseMouse();
683     return true;
684 }
685 
Paint(vcl::RenderContext & rRenderContext,const tools::Rectangle &)686 void ColorSliderControl::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
687 {
688     if (!mxBitmap)
689         UpdateBitmap();
690 
691     const Size aSize(GetOutputSizePixel());
692 
693     Point aPos;
694     int x = aSize.Width();
695     while (x--)
696     {
697         rRenderContext.DrawOutDev(aPos, aSize, Point(0,0), aSize, *mxBitmap);
698         aPos.AdjustX(1);
699     }
700 }
701 
Resize()702 void ColorSliderControl::Resize()
703 {
704     CustomWidgetController::Resize();
705     UpdateBitmap();
706 }
707 
Modify()708 void ColorSliderControl::Modify()
709 {
710     maModifyHdl.Call(*this);
711 }
712 
SetValue(const Color & rColor,ColorMode eMode,double dValue)713 void ColorSliderControl::SetValue(const Color& rColor, ColorMode eMode, double dValue)
714 {
715     bool bUpdateBitmap = (rColor != maColor) || (eMode != meMode);
716     if( bUpdateBitmap || (mdValue != dValue))
717     {
718         maColor = rColor;
719         mdValue = dValue;
720         mnLevel = static_cast<sal_Int16>((1.0-dValue) * GetOutputSizePixel().Height());
721         meMode = eMode;
722         if (bUpdateBitmap)
723             UpdateBitmap();
724         Invalidate();
725     }
726 }
727 
728 namespace {
729 
730 class ColorPickerDialog : public weld::GenericDialogController
731 {
732 private:
733     ColorFieldControl m_aColorField;
734     ColorSliderControl m_aColorSlider;
735     ColorPreviewControl m_aColorPreview;
736     ColorPreviewControl m_aColorPrevious;
737 
738     std::unique_ptr<weld::CustomWeld> m_xColorField;
739     std::unique_ptr<weld::CustomWeld> m_xColorSlider;
740     std::unique_ptr<weld::CustomWeld> m_xColorPreview;
741     std::unique_ptr<weld::CustomWeld> m_xColorPrevious;
742 
743     std::unique_ptr<weld::Widget> m_xFISliderLeft;
744     std::unique_ptr<weld::Widget> m_xFISliderRight;
745     std::unique_ptr<weld::RadioButton> m_xRBRed;
746     std::unique_ptr<weld::RadioButton> m_xRBGreen;
747     std::unique_ptr<weld::RadioButton> m_xRBBlue;
748     std::unique_ptr<weld::RadioButton> m_xRBHue;
749     std::unique_ptr<weld::RadioButton> m_xRBSaturation;
750     std::unique_ptr<weld::RadioButton> m_xRBBrightness;
751 
752     std::unique_ptr<weld::SpinButton> m_xMFRed;
753     std::unique_ptr<weld::SpinButton> m_xMFGreen;
754     std::unique_ptr<weld::SpinButton> m_xMFBlue;
755     std::unique_ptr<weld::HexColorControl> m_xEDHex;
756 
757     std::unique_ptr<weld::MetricSpinButton> m_xMFHue;
758     std::unique_ptr<weld::MetricSpinButton> m_xMFSaturation;
759     std::unique_ptr<weld::MetricSpinButton> m_xMFBrightness;
760 
761     std::unique_ptr<weld::MetricSpinButton> m_xMFCyan;
762     std::unique_ptr<weld::MetricSpinButton> m_xMFMagenta;
763     std::unique_ptr<weld::MetricSpinButton> m_xMFYellow;
764     std::unique_ptr<weld::MetricSpinButton> m_xMFKey;
765 
766 public:
767     ColorPickerDialog(weld::Window* pParent, Color nColor, sal_Int16 nMode);
768 
769     void update_color(UpdateFlags n = UpdateFlags::All);
770 
771     DECL_LINK(ColorFieldControlModifydl, ColorFieldControl&, void);
772     DECL_LINK(ColorSliderControlModifyHdl, ColorSliderControl&, void);
773     DECL_LINK(ColorModifyMetricHdl, weld::MetricSpinButton&, void);
774     DECL_LINK(ColorModifySpinHdl, weld::SpinButton&, void);
775     DECL_LINK(ColorModifyEditHdl, weld::Entry&, void);
776     DECL_LINK(ModeModifyHdl, weld::Toggleable&, void);
777 
778     Color GetColor() const;
779 
780     void setColorComponent(ColorComponent nComp, double dValue);
781 
782 private:
783     ColorMode meMode;
784 
785     double mdRed, mdGreen, mdBlue;
786     double mdHue, mdSat, mdBri;
787     double mdCyan, mdMagenta, mdYellow, mdKey;
788 };
789 
790 }
791 
ColorPickerDialog(weld::Window * pParent,Color nColor,sal_Int16 nDialogMode)792 ColorPickerDialog::ColorPickerDialog(weld::Window* pParent, Color nColor, sal_Int16 nDialogMode)
793     : GenericDialogController(pParent, "cui/ui/colorpickerdialog.ui", "ColorPicker")
794     , m_xColorField(new weld::CustomWeld(*m_xBuilder, "colorField", m_aColorField))
795     , m_xColorSlider(new weld::CustomWeld(*m_xBuilder, "colorSlider", m_aColorSlider))
796     , m_xColorPreview(new weld::CustomWeld(*m_xBuilder, "preview", m_aColorPreview))
797     , m_xColorPrevious(new weld::CustomWeld(*m_xBuilder, "previous", m_aColorPrevious))
798     , m_xFISliderLeft(m_xBuilder->weld_widget("leftImage"))
799     , m_xFISliderRight(m_xBuilder->weld_widget("rightImage"))
800     , m_xRBRed(m_xBuilder->weld_radio_button("redRadiobutton"))
801     , m_xRBGreen(m_xBuilder->weld_radio_button("greenRadiobutton"))
802     , m_xRBBlue(m_xBuilder->weld_radio_button("blueRadiobutton"))
803     , m_xRBHue(m_xBuilder->weld_radio_button("hueRadiobutton"))
804     , m_xRBSaturation(m_xBuilder->weld_radio_button("satRadiobutton"))
805     , m_xRBBrightness(m_xBuilder->weld_radio_button("brightRadiobutton"))
806     , m_xMFRed(m_xBuilder->weld_spin_button("redSpinbutton"))
807     , m_xMFGreen(m_xBuilder->weld_spin_button("greenSpinbutton"))
808     , m_xMFBlue(m_xBuilder->weld_spin_button("blueSpinbutton"))
809     , m_xEDHex(new weld::HexColorControl(m_xBuilder->weld_entry("hexEntry")))
810     , m_xMFHue(m_xBuilder->weld_metric_spin_button("hueSpinbutton", FieldUnit::DEGREE))
811     , m_xMFSaturation(m_xBuilder->weld_metric_spin_button("satSpinbutton", FieldUnit::PERCENT))
812     , m_xMFBrightness(m_xBuilder->weld_metric_spin_button("brightSpinbutton", FieldUnit::PERCENT))
813     , m_xMFCyan(m_xBuilder->weld_metric_spin_button("cyanSpinbutton", FieldUnit::PERCENT))
814     , m_xMFMagenta(m_xBuilder->weld_metric_spin_button("magSpinbutton", FieldUnit::PERCENT))
815     , m_xMFYellow(m_xBuilder->weld_metric_spin_button("yellowSpinbutton", FieldUnit::PERCENT))
816     , m_xMFKey(m_xBuilder->weld_metric_spin_button("keySpinbutton", FieldUnit::PERCENT))
817     , meMode( DefaultMode )
818 {
819     m_aColorField.SetModifyHdl( LINK( this, ColorPickerDialog, ColorFieldControlModifydl ) );
820     m_aColorSlider.SetModifyHdl( LINK( this, ColorPickerDialog, ColorSliderControlModifyHdl ) );
821 
822     int nMargin = (m_xFISliderLeft->get_preferred_size().Height() + 1) / 2;
823     m_xColorSlider->set_margin_top(nMargin);
824     m_xColorSlider->set_margin_bottom(nMargin);
825 
826     Link<weld::MetricSpinButton&,void> aLink3( LINK( this, ColorPickerDialog, ColorModifyMetricHdl ) );
827     m_xMFCyan->connect_value_changed( aLink3 );
828     m_xMFMagenta->connect_value_changed( aLink3 );
829     m_xMFYellow->connect_value_changed( aLink3 );
830     m_xMFKey->connect_value_changed( aLink3 );
831 
832     m_xMFHue->connect_value_changed( aLink3 );
833     m_xMFSaturation->connect_value_changed( aLink3 );
834     m_xMFBrightness->connect_value_changed( aLink3 );
835 
836     Link<weld::SpinButton&,void> aLink4(LINK(this, ColorPickerDialog, ColorModifySpinHdl));
837     m_xMFRed->connect_value_changed(aLink4);
838     m_xMFGreen->connect_value_changed(aLink4);
839     m_xMFBlue->connect_value_changed(aLink4);
840 
841     m_xEDHex->connect_changed(LINK(this, ColorPickerDialog, ColorModifyEditHdl));
842 
843     Link<weld::Toggleable&,void> aLink2 = LINK( this, ColorPickerDialog, ModeModifyHdl );
844     m_xRBRed->connect_toggled( aLink2 );
845     m_xRBGreen->connect_toggled( aLink2 );
846     m_xRBBlue->connect_toggled( aLink2 );
847     m_xRBHue->connect_toggled( aLink2 );
848     m_xRBSaturation->connect_toggled( aLink2 );
849     m_xRBBrightness->connect_toggled( aLink2 );
850 
851     Color aColor(nColor);
852 
853     // modify
854     if (nDialogMode == 2)
855     {
856         m_aColorPrevious.SetColor(aColor);
857         m_xColorPrevious->show();
858     }
859 
860     mdRed = static_cast<double>(aColor.GetRed()) / 255.0;
861     mdGreen = static_cast<double>(aColor.GetGreen()) / 255.0;
862     mdBlue = static_cast<double>(aColor.GetBlue()) / 255.0;
863 
864     RGBtoHSV( mdRed, mdGreen, mdBlue, mdHue, mdSat, mdBri );
865     RGBtoCMYK( mdRed, mdGreen, mdBlue, mdCyan, mdMagenta, mdYellow, mdKey );
866 
867     update_color();
868 }
869 
toInt(double dValue,double dRange)870 static int toInt( double dValue, double dRange )
871 {
872     return static_cast< int >( std::floor((dValue * dRange) + 0.5 ) );
873 }
874 
GetColor() const875 Color ColorPickerDialog::GetColor() const
876 {
877     return Color( toInt(mdRed,255.0), toInt(mdGreen,255.0), toInt(mdBlue,255.0) );
878 }
879 
update_color(UpdateFlags n)880 void ColorPickerDialog::update_color( UpdateFlags n )
881 {
882     sal_uInt8 nRed = toInt(mdRed,255.0);
883     sal_uInt8 nGreen = toInt(mdGreen,255.0);
884     sal_uInt8 nBlue = toInt(mdBlue,255.0);
885 
886     Color aColor(nRed, nGreen, nBlue);
887 
888     if (n & UpdateFlags::RGB) // update RGB
889     {
890         m_xMFRed->set_value(nRed);
891         m_xMFGreen->set_value(nGreen);
892         m_xMFBlue->set_value(nBlue);
893     }
894 
895     if (n & UpdateFlags::CMYK) // update CMYK
896     {
897         m_xMFCyan->set_value(toInt(mdCyan, 100.0), FieldUnit::PERCENT);
898         m_xMFMagenta->set_value(toInt(mdMagenta, 100.0), FieldUnit::PERCENT);
899         m_xMFYellow->set_value(toInt(mdYellow, 100.0), FieldUnit::PERCENT);
900         m_xMFKey->set_value(toInt(mdKey, 100.0), FieldUnit::PERCENT);
901     }
902 
903     if (n & UpdateFlags::HSB ) // update HSB
904     {
905         m_xMFHue->set_value(toInt(mdHue, 1.0), FieldUnit::DEGREE);
906         m_xMFSaturation->set_value(toInt( mdSat, 100.0), FieldUnit::PERCENT);
907         m_xMFBrightness->set_value(toInt( mdBri, 100.0), FieldUnit::PERCENT);
908     }
909 
910     if (n & UpdateFlags::ColorChooser ) // update Color Chooser 1
911     {
912         switch( meMode )
913         {
914         case HUE:
915             m_aColorField.SetValues(aColor, meMode, mdSat, mdBri);
916             break;
917         case SATURATION:
918             m_aColorField.SetValues(aColor, meMode, mdHue / 360.0, mdBri);
919             break;
920         case BRIGHTNESS:
921             m_aColorField.SetValues(aColor, meMode, mdHue / 360.0, mdSat);
922             break;
923         case RED:
924             m_aColorField.SetValues(aColor, meMode, mdBlue, mdGreen);
925             break;
926         case GREEN:
927             m_aColorField.SetValues(aColor, meMode, mdBlue, mdRed);
928             break;
929         case BLUE:
930             m_aColorField.SetValues(aColor, meMode, mdRed, mdGreen);
931             break;
932         }
933     }
934 
935     if (n & UpdateFlags::ColorSlider) // update Color Chooser 2
936     {
937         switch (meMode)
938         {
939         case HUE:
940             m_aColorSlider.SetValue(aColor, meMode, mdHue / 360.0);
941             break;
942         case SATURATION:
943             m_aColorSlider.SetValue(aColor, meMode, mdSat);
944             break;
945         case BRIGHTNESS:
946             m_aColorSlider.SetValue(aColor, meMode, mdBri);
947             break;
948         case RED:
949             m_aColorSlider.SetValue(aColor, meMode, mdRed);
950             break;
951         case GREEN:
952             m_aColorSlider.SetValue(aColor, meMode, mdGreen);
953             break;
954         case BLUE:
955             m_aColorSlider.SetValue(aColor, meMode, mdBlue);
956             break;
957         }
958     }
959 
960     if (n & UpdateFlags::Hex) // update hex
961     {
962         m_xFISliderLeft->set_margin_top(m_aColorSlider.GetLevel());
963         m_xFISliderRight->set_margin_top(m_aColorSlider.GetLevel());
964         m_xEDHex->SetColor(aColor);
965     }
966     m_aColorPreview.SetColor(aColor);
967 }
968 
IMPL_LINK_NOARG(ColorPickerDialog,ColorFieldControlModifydl,ColorFieldControl &,void)969 IMPL_LINK_NOARG(ColorPickerDialog, ColorFieldControlModifydl, ColorFieldControl&, void)
970 {
971     double x = m_aColorField.GetX();
972     double y = m_aColorField.GetY();
973 
974     switch( meMode )
975     {
976     case HUE:
977         mdSat = x;
978         setColorComponent( ColorComponent::Brightness, y );
979         break;
980     case SATURATION:
981         mdHue = x * 360.0;
982         setColorComponent( ColorComponent::Brightness, y );
983         break;
984     case BRIGHTNESS:
985         mdHue = x * 360.0;
986         setColorComponent( ColorComponent::Saturation, y );
987         break;
988     case RED:
989         mdBlue = x;
990         setColorComponent( ColorComponent::Green, y );
991         break;
992     case GREEN:
993         mdBlue = x;
994         setColorComponent( ColorComponent::Red, y );
995         break;
996     case BLUE:
997         mdRed = x;
998         setColorComponent( ColorComponent::Green, y );
999         break;
1000     }
1001 
1002     update_color(UpdateFlags::All & ~UpdateFlags::ColorChooser);
1003 }
1004 
IMPL_LINK_NOARG(ColorPickerDialog,ColorSliderControlModifyHdl,ColorSliderControl &,void)1005 IMPL_LINK_NOARG(ColorPickerDialog, ColorSliderControlModifyHdl, ColorSliderControl&, void)
1006 {
1007     double dValue = m_aColorSlider.GetValue();
1008     switch (meMode)
1009     {
1010     case HUE:
1011         setColorComponent( ColorComponent::Hue, dValue * 360.0 );
1012         break;
1013     case SATURATION:
1014         setColorComponent( ColorComponent::Saturation, dValue );
1015         break;
1016     case BRIGHTNESS:
1017         setColorComponent( ColorComponent::Brightness, dValue );
1018         break;
1019     case RED:
1020         setColorComponent( ColorComponent::Red, dValue );
1021         break;
1022     case GREEN:
1023         setColorComponent( ColorComponent::Green, dValue );
1024         break;
1025     case BLUE:
1026         setColorComponent( ColorComponent::Blue, dValue );
1027         break;
1028     }
1029 
1030     update_color(UpdateFlags::All & ~UpdateFlags::ColorSlider);
1031 }
1032 
IMPL_LINK(ColorPickerDialog,ColorModifyMetricHdl,weld::MetricSpinButton &,rEdit,void)1033 IMPL_LINK(ColorPickerDialog, ColorModifyMetricHdl, weld::MetricSpinButton&, rEdit, void)
1034 {
1035     UpdateFlags n = UpdateFlags::NONE;
1036 
1037     if (&rEdit == m_xMFHue.get())
1038     {
1039         setColorComponent( ColorComponent::Hue, static_cast<double>(m_xMFHue->get_value(FieldUnit::DEGREE)) );
1040         n = UpdateFlags::All & ~UpdateFlags::HSB;
1041     }
1042     else if (&rEdit == m_xMFSaturation.get())
1043     {
1044         setColorComponent( ColorComponent::Saturation, static_cast<double>(m_xMFSaturation->get_value(FieldUnit::PERCENT)) / 100.0 );
1045         n = UpdateFlags::All & ~UpdateFlags::HSB;
1046     }
1047     else if (&rEdit == m_xMFBrightness.get())
1048     {
1049         setColorComponent( ColorComponent::Brightness, static_cast<double>(m_xMFBrightness->get_value(FieldUnit::PERCENT)) / 100.0 );
1050         n = UpdateFlags::All & ~UpdateFlags::HSB;
1051     }
1052     else if (&rEdit == m_xMFCyan.get())
1053     {
1054         setColorComponent( ColorComponent::Cyan, static_cast<double>(m_xMFCyan->get_value(FieldUnit::PERCENT)) / 100.0 );
1055         n = UpdateFlags::All & ~UpdateFlags::CMYK;
1056     }
1057     else if (&rEdit == m_xMFMagenta.get())
1058     {
1059         setColorComponent( ColorComponent::Magenta, static_cast<double>(m_xMFMagenta->get_value(FieldUnit::PERCENT)) / 100.0 );
1060         n = UpdateFlags::All & ~UpdateFlags::CMYK;
1061     }
1062     else if (&rEdit == m_xMFYellow.get())
1063     {
1064         setColorComponent( ColorComponent::Yellow, static_cast<double>(m_xMFYellow->get_value(FieldUnit::PERCENT)) / 100.0 );
1065         n = UpdateFlags::All & ~UpdateFlags::CMYK;
1066     }
1067     else if (&rEdit == m_xMFKey.get())
1068     {
1069         setColorComponent( ColorComponent::Key, static_cast<double>(m_xMFKey->get_value(FieldUnit::PERCENT)) / 100.0 );
1070         n = UpdateFlags::All & ~UpdateFlags::CMYK;
1071     }
1072 
1073     if (n != UpdateFlags::NONE)
1074         update_color(n);
1075 }
1076 
IMPL_LINK_NOARG(ColorPickerDialog,ColorModifyEditHdl,weld::Entry &,void)1077 IMPL_LINK_NOARG(ColorPickerDialog, ColorModifyEditHdl, weld::Entry&, void)
1078 {
1079     UpdateFlags n = UpdateFlags::NONE;
1080 
1081     Color aColor = m_xEDHex->GetColor();
1082 
1083     if (aColor != COL_AUTO && aColor != GetColor())
1084     {
1085         mdRed = static_cast<double>(aColor.GetRed()) / 255.0;
1086         mdGreen = static_cast<double>(aColor.GetGreen()) / 255.0;
1087         mdBlue = static_cast<double>(aColor.GetBlue()) / 255.0;
1088 
1089         RGBtoHSV( mdRed, mdGreen, mdBlue, mdHue, mdSat, mdBri );
1090         RGBtoCMYK( mdRed, mdGreen, mdBlue, mdCyan, mdMagenta, mdYellow, mdKey );
1091         n = UpdateFlags::All & ~UpdateFlags::Hex;
1092     }
1093 
1094     if (n != UpdateFlags::NONE)
1095         update_color(n);
1096 }
1097 
IMPL_LINK(ColorPickerDialog,ColorModifySpinHdl,weld::SpinButton &,rEdit,void)1098 IMPL_LINK(ColorPickerDialog, ColorModifySpinHdl, weld::SpinButton&, rEdit, void)
1099 {
1100     UpdateFlags n = UpdateFlags::NONE;
1101 
1102     if (&rEdit == m_xMFRed.get())
1103     {
1104         setColorComponent( ColorComponent::Red, static_cast<double>(m_xMFRed->get_value()) / 255.0 );
1105         n = UpdateFlags::All & ~UpdateFlags::RGB;
1106     }
1107     else if (&rEdit == m_xMFGreen.get())
1108     {
1109         setColorComponent( ColorComponent::Green, static_cast<double>(m_xMFGreen->get_value()) / 255.0 );
1110         n = UpdateFlags::All & ~UpdateFlags::RGB;
1111     }
1112     else if (&rEdit == m_xMFBlue.get())
1113     {
1114         setColorComponent( ColorComponent::Blue, static_cast<double>(m_xMFBlue->get_value()) / 255.0 );
1115         n = UpdateFlags::All & ~UpdateFlags::RGB;
1116     }
1117 
1118     if (n != UpdateFlags::NONE)
1119         update_color(n);
1120 }
1121 
1122 
IMPL_LINK_NOARG(ColorPickerDialog,ModeModifyHdl,weld::Toggleable &,void)1123 IMPL_LINK_NOARG(ColorPickerDialog, ModeModifyHdl, weld::Toggleable&, void)
1124 {
1125     ColorMode eMode = HUE;
1126 
1127     if (m_xRBRed->get_active())
1128     {
1129         eMode = RED;
1130     }
1131     else if (m_xRBGreen->get_active())
1132     {
1133         eMode = GREEN;
1134     }
1135     else if (m_xRBBlue->get_active())
1136     {
1137         eMode = BLUE;
1138     }
1139     else if (m_xRBSaturation->get_active())
1140     {
1141         eMode = SATURATION;
1142     }
1143     else if (m_xRBBrightness->get_active())
1144     {
1145         eMode = BRIGHTNESS;
1146     }
1147 
1148     if (meMode != eMode)
1149     {
1150         meMode = eMode;
1151         update_color(UpdateFlags::ColorChooser | UpdateFlags::ColorSlider);
1152     }
1153 }
1154 
setColorComponent(ColorComponent nComp,double dValue)1155 void ColorPickerDialog::setColorComponent( ColorComponent nComp, double dValue )
1156 {
1157     switch( nComp )
1158     {
1159     case ColorComponent::Red:
1160         mdRed = dValue;
1161         break;
1162     case ColorComponent::Green:
1163         mdGreen = dValue;
1164         break;
1165     case ColorComponent::Blue:
1166         mdBlue = dValue;
1167         break;
1168     case ColorComponent::Hue:
1169         mdHue = dValue;
1170         break;
1171     case ColorComponent::Saturation:
1172         mdSat = dValue;
1173         break;
1174     case ColorComponent::Brightness:
1175         mdBri = dValue;
1176         break;
1177     case ColorComponent::Cyan:
1178         mdCyan = dValue;
1179         break;
1180     case ColorComponent::Yellow:
1181         mdYellow = dValue;
1182         break;
1183     case ColorComponent::Magenta:
1184         mdMagenta = dValue;
1185         break;
1186     case ColorComponent::Key:
1187         mdKey = dValue;
1188         break;
1189     }
1190 
1191     if (nComp == ColorComponent::Red || nComp == ColorComponent::Green || nComp == ColorComponent::Blue)
1192     {
1193         RGBtoHSV( mdRed, mdGreen, mdBlue, mdHue, mdSat, mdBri );
1194         RGBtoCMYK( mdRed, mdGreen, mdBlue, mdCyan, mdMagenta, mdYellow, mdKey );
1195     }
1196     else if (nComp == ColorComponent::Hue || nComp == ColorComponent::Saturation || nComp == ColorComponent::Brightness)
1197     {
1198         HSVtoRGB( mdHue, mdSat, mdBri, mdRed, mdGreen, mdBlue );
1199         RGBtoCMYK( mdRed, mdGreen, mdBlue, mdCyan, mdMagenta, mdYellow, mdKey );
1200     }
1201     else
1202     {
1203         CMYKtoRGB( mdCyan, mdMagenta, mdYellow, mdKey, mdRed, mdGreen, mdBlue );
1204         RGBtoHSV( mdRed, mdGreen, mdBlue, mdHue, mdSat, mdBri );
1205     }
1206 }
1207 
1208 typedef ::cppu::WeakComponentImplHelper< XServiceInfo, XExecutableDialog, XInitialization, XPropertyAccess > ColorPickerBase;
1209 
1210 namespace {
1211 
1212 class ColorPicker : protected ::cppu::BaseMutex,    // Struct for right initialization of mutex member! Must be first of baseclasses.
1213                     public ColorPickerBase
1214 {
1215 public:
1216     explicit ColorPicker();
1217 
1218     // XInitialization
1219     virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) override;
1220 
1221     // XInitialization
1222     virtual OUString SAL_CALL getImplementationName(  ) override;
1223     virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
1224     virtual Sequence< OUString > SAL_CALL getSupportedServiceNames(  ) override;
1225 
1226     // XPropertyAccess
1227     virtual Sequence< PropertyValue > SAL_CALL getPropertyValues(  ) override;
1228     virtual void SAL_CALL setPropertyValues( const Sequence< PropertyValue >& aProps ) override;
1229 
1230     // XExecutableDialog
1231     virtual void SAL_CALL setTitle( const OUString& aTitle ) override;
1232     virtual sal_Int16 SAL_CALL execute(  ) override;
1233 
1234 private:
1235     Color mnColor;
1236     sal_Int16 mnMode;
1237     Reference<css::awt::XWindow> mxParent;
1238 };
1239 
1240 }
1241 
1242 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
com_sun_star_cui_ColorPicker_get_implementation(css::uno::XComponentContext *,css::uno::Sequence<css::uno::Any> const &)1243 com_sun_star_cui_ColorPicker_get_implementation(
1244     css::uno::XComponentContext*, css::uno::Sequence<css::uno::Any> const&)
1245 {
1246     return cppu::acquire( new ColorPicker );
1247 }
1248 
1249 
1250 constexpr OUStringLiteral gsColorKey( u"Color" );
1251 constexpr OUStringLiteral gsModeKey( u"Mode" );
1252 
ColorPicker()1253 ColorPicker::ColorPicker()
1254     : ColorPickerBase( m_aMutex )
1255     , mnColor( 0 )
1256     , mnMode( 0 )
1257 {
1258 }
1259 
1260 // XInitialization
initialize(const Sequence<Any> & aArguments)1261 void SAL_CALL ColorPicker::initialize( const Sequence< Any >& aArguments )
1262 {
1263     if( aArguments.getLength() == 1 )
1264     {
1265         aArguments[0] >>= mxParent;
1266     }
1267 }
1268 
1269 // XInitialization
getImplementationName()1270 OUString SAL_CALL ColorPicker::getImplementationName(  )
1271 {
1272     return "com.sun.star.cui.ColorPicker";
1273 }
1274 
supportsService(const OUString & sServiceName)1275 sal_Bool SAL_CALL ColorPicker::supportsService( const OUString& sServiceName )
1276 {
1277     return cppu::supportsService(this, sServiceName);
1278 }
1279 
getSupportedServiceNames()1280 Sequence< OUString > SAL_CALL ColorPicker::getSupportedServiceNames(  )
1281 {
1282     return { "com.sun.star.ui.dialogs.ColorPicker" };
1283 }
1284 
1285 // XPropertyAccess
getPropertyValues()1286 Sequence< PropertyValue > SAL_CALL ColorPicker::getPropertyValues(  )
1287 {
1288     Sequence< PropertyValue > props(1);
1289     props[0].Name = gsColorKey;
1290     props[0].Value <<= mnColor;
1291     return props;
1292 }
1293 
setPropertyValues(const Sequence<PropertyValue> & aProps)1294 void SAL_CALL ColorPicker::setPropertyValues( const Sequence< PropertyValue >& aProps )
1295 {
1296     for ( const PropertyValue& rProp : aProps )
1297     {
1298         if( rProp.Name == gsColorKey )
1299         {
1300             rProp.Value >>= mnColor;
1301         }
1302         else if( rProp.Name == gsModeKey )
1303         {
1304             rProp.Value >>= mnMode;
1305         }
1306     }
1307 }
1308 
1309 // XExecutableDialog
setTitle(const OUString &)1310 void SAL_CALL ColorPicker::setTitle( const OUString& )
1311 {
1312 }
1313 
execute()1314 sal_Int16 SAL_CALL ColorPicker::execute()
1315 {
1316     std::unique_ptr<ColorPickerDialog> xDlg(new ColorPickerDialog(Application::GetFrameWeld(mxParent), mnColor, mnMode));
1317     sal_Int16 ret = xDlg->run();
1318     if (ret)
1319         mnColor = xDlg->GetColor();
1320     return ret;
1321 }
1322 
1323 }
1324 
1325 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1326