KiCad PCB EDA Suite
Loading...
Searching...
No Matches
color_swatch.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2017-2021 KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
25#include <wx/dcmemory.h>
26
27#include <gal/dpi_scaling.h>
29#include <memory>
30
31wxDEFINE_EVENT( COLOR_SWATCH_CHANGED, wxCommandEvent );
32
33using KIGFX::COLOR4D;
34
35
36// See selcolor.cpp:
37extern COLOR4D DisplayColorFrame( wxWindow* aParent, COLOR4D aOldColor );
38
39
40wxBitmap COLOR_SWATCH::MakeBitmap( const COLOR4D& aColor, const COLOR4D& aBackground,
41 const wxSize& aSize, const wxSize& aCheckerboardSize,
42 const COLOR4D& aCheckerboardBackground )
43{
44 wxBitmap bitmap( aSize );
45 wxBrush brush;
46 wxPen pen;
47 wxMemoryDC iconDC;
48
49 iconDC.SelectObject( bitmap );
50 brush.SetStyle( wxBRUSHSTYLE_SOLID );
51
52 if( aColor == COLOR4D::UNSPECIFIED )
53 {
54 // Draw a checkerboard
55 COLOR4D white;
56 COLOR4D black;
57 bool rowCycle;
58
59 if( aCheckerboardBackground.GetBrightness() > 0.4 )
60 {
61 white = COLOR4D::WHITE;
62 black = white.Darkened( 0.15 );
63 rowCycle = true;
64 }
65 else
66 {
67 black = COLOR4D::BLACK;
68 white = black.Brightened( 0.15 );
69 rowCycle = false;
70 }
71
72 for( int x = 0; x < aSize.x; x += aCheckerboardSize.x )
73 {
74 bool colCycle = rowCycle;
75
76 for( int y = 0; y < aSize.y; y += aCheckerboardSize.y )
77 {
78 COLOR4D color = colCycle ? black : white;
79 brush.SetColour( color.ToColour() );
80 pen.SetColour( color.ToColour() );
81
82 iconDC.SetBrush( brush );
83 iconDC.SetPen( pen );
84 iconDC.DrawRectangle( x, y, x + aCheckerboardSize.x, y + aCheckerboardSize.y );
85
86 colCycle = !colCycle;
87 }
88
89 rowCycle = !rowCycle;
90 }
91 }
92 else
93 {
94 brush.SetColour( aBackground.WithAlpha(1.0).ToColour() );
95 pen.SetColour( aBackground.WithAlpha(1.0).ToColour() );
96
97 iconDC.SetBrush( brush );
98 iconDC.SetPen( pen );
99 iconDC.DrawRectangle( 0, 0, aSize.x, aSize.y );
100
101 brush.SetColour( aColor.ToColour() );
102 pen.SetColour( aColor.ToColour() );
103
104 iconDC.SetBrush( brush );
105 iconDC.SetPen( pen );
106 iconDC.DrawRectangle( 0, 0, aSize.x, aSize.y );
107 }
108
109 return bitmap;
110}
111
112
113COLOR_SWATCH::COLOR_SWATCH( wxWindow* aParent, const COLOR4D& aColor, int aID,
114 const COLOR4D& aBackground, const COLOR4D& aDefault,
115 SWATCH_SIZE aSwatchSize ) :
116 wxPanel( aParent, aID ),
117 m_color( aColor ),
118 m_background( aBackground ),
119 m_default( aDefault ),
120 m_userColors( nullptr ),
121 m_readOnly( false ),
122 m_supportsOpacity( true )
123{
124 wxASSERT_MSG( aSwatchSize != SWATCH_EXPAND, wxS( "SWATCH_EXPAND not supported in COLOR_SWATCH" ) );
125
126 switch( aSwatchSize )
127 {
128 case SWATCH_MEDIUM: m_size = ConvertDialogToPixels( SWATCH_SIZE_MEDIUM_DU ); break;
129 case SWATCH_SMALL: m_size = ConvertDialogToPixels( SWATCH_SIZE_SMALL_DU ); break;
130 case SWATCH_LARGE: m_size = ConvertDialogToPixels( SWATCH_SIZE_LARGE_DU ); break;
131 case SWATCH_EXPAND: m_size = ConvertDialogToPixels( SWATCH_SIZE_LARGE_DU ); break;
132 }
133
134 m_checkerboardSize = ConvertDialogToPixels( CHECKERBOARD_SIZE_DU );
135 m_checkerboardBg = aParent->GetBackgroundColour();
136
137#ifdef __WXMSW__
138 // These need additional scaling on Windows because of some discrepancy between pixel and
139 // content scaling that only affects certain widgets on Windows HiDPI. On other platforms, the
140 // value returned by ConvertDialogToPixels appears to be correct.
141 DPI_SCALING dpi( nullptr, aParent );
142
145#endif
146
147 auto sizer = new wxBoxSizer( wxHORIZONTAL );
148 SetSizer( sizer );
149
150 wxBitmap bitmap = COLOR_SWATCH::MakeBitmap( aColor, aBackground, m_size,
152 m_swatch = new wxStaticBitmap( this, aID, bitmap );
153
154 sizer->Add( m_swatch, 0, 0 );
155
156 setupEvents();
157}
158
159
160COLOR_SWATCH::COLOR_SWATCH( wxWindow* aParent, wxWindowID aID, const wxPoint& aPos,
161 const wxSize& aSize, long aStyle ) :
162 wxPanel( aParent, aID, aPos, aSize, aStyle ),
163 m_userColors( nullptr ),
164 m_readOnly( false ),
165 m_supportsOpacity( true )
166{
167 if( aSize == wxDefaultSize )
168 m_size = ConvertDialogToPixels( SWATCH_SIZE_MEDIUM_DU );
169 else
170 m_size = aSize;
171
172 m_checkerboardSize = ConvertDialogToPixels( CHECKERBOARD_SIZE_DU );
173 m_checkerboardBg = aParent->GetBackgroundColour();
174
175 SetSize( m_size );
176
177 auto sizer = new wxBoxSizer( wxHORIZONTAL );
178 SetSizer( sizer );
179
180 wxBitmap bitmap = COLOR_SWATCH::MakeBitmap( COLOR4D::UNSPECIFIED, COLOR4D::UNSPECIFIED,
182 m_swatch = new wxStaticBitmap( this, aID, bitmap );
183
184 sizer->Add( m_swatch, 0, 0 );
185
186 setupEvents();
187}
188
189
191{
192 wxWindow* topLevelParent = GetParent();
193
194 while( topLevelParent && !topLevelParent->IsTopLevel() )
195 topLevelParent = topLevelParent->GetParent();
196
197 if( topLevelParent && dynamic_cast<DIALOG_SHIM*>( topLevelParent ) )
198 {
199 m_swatch->Bind( wxEVT_LEFT_DOWN,
200 [this] ( wxMouseEvent& aEvt )
201 {
203 } );
204 }
205 else
206 {
207 // forward click to any other listeners, since we don't want them
208 m_swatch->Bind( wxEVT_LEFT_DOWN, &COLOR_SWATCH::rePostEvent, this );
209
210 // bind the events that trigger the dialog
211 m_swatch->Bind( wxEVT_LEFT_DCLICK,
212 [this] ( wxMouseEvent& aEvt )
213 {
215 } );
216 }
217
218 m_swatch->Bind( wxEVT_MIDDLE_DOWN,
219 [this] ( wxMouseEvent& aEvt )
220 {
222 } );
223
224 m_swatch->Bind( wxEVT_RIGHT_DOWN, &COLOR_SWATCH::rePostEvent, this );
225}
226
227
228void COLOR_SWATCH::rePostEvent( wxEvent& aEvent )
229{
230 wxPostEvent( this, aEvent );
231}
232
233
234static void sendSwatchChangeEvent( COLOR_SWATCH& aSender )
235{
236 wxCommandEvent changeEvt( COLOR_SWATCH_CHANGED, aSender.GetId() );
237
238 // use this class as the object (alternative might be to
239 // set a custom event class but that's more work)
240 changeEvt.SetEventObject( &aSender );
241
242 wxPostEvent( &aSender, changeEvt );
243}
244
245
246void COLOR_SWATCH::SetSwatchColor( const COLOR4D& aColor, bool aSendEvent )
247{
248 m_color = aColor;
249
251 m_swatch->SetBitmap( bm );
252
253 if( aSendEvent )
254 sendSwatchChangeEvent( *this );
255}
256
257
259{
260 m_default = aColor;
261}
262
263
265{
266 m_background = aBackground;
268 m_swatch->SetBitmap( bm );
269}
270
271
273{
274 return m_color;
275}
276
277
279{
280 if( m_readOnly )
281 {
284
285 return;
286 }
287
288 DIALOG_COLOR_PICKER dialog( ::wxGetTopLevelParent( this ), m_color, m_supportsOpacity,
290
291 if( dialog.ShowModal() == wxID_OK )
292 {
293 COLOR4D newColor = dialog.GetColor();
294
295 if( newColor != COLOR4D::UNSPECIFIED || m_default == COLOR4D::UNSPECIFIED )
296 {
297 m_color = newColor;
298
299 wxBitmap bm = MakeBitmap( newColor, m_background, m_size, m_checkerboardSize,
301 m_swatch->SetBitmap( bm );
302
303 sendSwatchChangeEvent( *this );
304 }
305 }
306}
307
308
310{
311 m_checkerboardBg = m_parent->GetBackgroundColour();
313 m_swatch->SetBitmap( bm );
314}
int color
Definition: DXF_plotter.cpp:57
A simple color swatch of the kind used to set layer colors.
Definition: color_swatch.h:57
void SetSwatchColor(const KIGFX::COLOR4D &aColor, bool aSendEvent)
Set the current swatch color directly.
wxSize m_checkerboardSize
Definition: color_swatch.h:150
KIGFX::COLOR4D m_checkerboardBg
Definition: color_swatch.h:151
KIGFX::COLOR4D m_default
Definition: color_swatch.h:144
bool m_supportsOpacity
If opacity is not supported the color chooser dialog will be displayed without it.
Definition: color_swatch.h:158
wxStaticBitmap * m_swatch
Definition: color_swatch.h:147
void OnDarkModeToggle()
Respond to a change in the OS's DarkMode setting.
void GetNewSwatchColor()
Prompt for a new colour, using the colour picker dialog.
bool m_readOnly
A read-only swatch won't show the color chooser dialog but otherwise works normally.
Definition: color_swatch.h:154
KIGFX::COLOR4D GetSwatchColor() const
void setupEvents()
KIGFX::COLOR4D m_color
Definition: color_swatch.h:142
KIGFX::COLOR4D m_background
Definition: color_swatch.h:143
std::function< void()> m_readOnlyCallback
Definition: color_swatch.h:155
void SetDefaultColor(const KIGFX::COLOR4D &aColor)
Sets the color that will be chosen with the "Reset to Default" button in the chooser.
void SetSwatchBackground(const KIGFX::COLOR4D &aBackground)
Set the swatch background color.
CUSTOM_COLORS_LIST * m_userColors
Definition: color_swatch.h:145
void rePostEvent(wxEvent &aEvent)
Pass unwanted events on to listeners of this object.
COLOR_SWATCH(wxWindow *aParent, const KIGFX::COLOR4D &aColor, int aID, const KIGFX::COLOR4D &aBackground, const KIGFX::COLOR4D &aDefault, SWATCH_SIZE aSwatchType)
Construct a COLOR_SWATCH.
static wxBitmap MakeBitmap(const KIGFX::COLOR4D &aColor, const KIGFX::COLOR4D &aBackground, const wxSize &aSize, const wxSize &aCheckerboardSize, const KIGFX::COLOR4D &aCheckerboardBackground)
KIGFX::COLOR4D GetColor()
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
Definition: dialog_shim.h:83
Class to handle configuration and automatic determination of the DPI scale to use for canvases.
Definition: dpi_scaling.h:37
double GetContentScaleFactor() const
Get the content scale factor, which may be different from the scale factor on some platforms.
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:103
COLOR4D WithAlpha(double aAlpha) const
Return a color with the same color, but the given alpha.
Definition: color4d.h:310
COLOR4D Darkened(double aFactor) const
Return a color that is darker by a given factor, without modifying object.
Definition: color4d.h:281
double GetBrightness() const
Returns the brightness value of the color ranged from 0.0 to 1.0.
Definition: color4d.h:332
COLOR4D Brightened(double aFactor) const
Return a color that is brighter by a given factor, without modifying object.
Definition: color4d.h:267
wxColour ToColour() const
Definition: color4d.cpp:219
wxDEFINE_EVENT(COLOR_SWATCH_CHANGED, wxCommandEvent)
static void sendSwatchChangeEvent(COLOR_SWATCH &aSender)
COLOR4D DisplayColorFrame(wxWindow *aParent, COLOR4D aOldColor)
static const wxSize SWATCH_SIZE_LARGE_DU(24, 16)
static const wxSize SWATCH_SIZE_MEDIUM_DU(24, 10)
static const wxSize CHECKERBOARD_SIZE_DU(3, 3)
static const wxSize SWATCH_SIZE_SMALL_DU(8, 6)
SWATCH_SIZE
Definition: color_swatch.h:39
@ SWATCH_MEDIUM
Definition: color_swatch.h:41
@ SWATCH_LARGE
Definition: color_swatch.h:42
@ SWATCH_EXPAND
Definition: color_swatch.h:43
@ SWATCH_SMALL
Definition: color_swatch.h:40