KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_color_picker.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20
21#include <kiplatform/ui.h>
23#include <cmath>
24#include <algorithm>
25#include <kiface_base.h>
28#include <wx/bitmap.h>
29#include <wx/dcmemory.h>
30
31#define ALPHA_MAX 100 // the max value returned by the alpha (opacity) slider
32#define SLOPE_AXIS ( bmsize.y / 5.28 ) // was 50 at 264 size
33
34using KIGFX::COLOR4D;
35
36// Configure the spin controls contained inside the dialog
37void configureSpinCtrl( wxSpinCtrl* aCtrl )
38{
39 wxSize textLength = aCtrl->GetTextExtent( "999" );
40 wxSize ctrlSize = aCtrl->GetSizeFromTextSize( textLength );
41
42 aCtrl->SetMinSize( ctrlSize );
43 aCtrl->SetSize( ctrlSize );
44}
45
46
47DIALOG_COLOR_PICKER::DIALOG_COLOR_PICKER( wxWindow* aParent, const COLOR4D& aCurrentColor,
48 bool aAllowOpacityControl,
49 CUSTOM_COLORS_LIST* aUserColors,
50 const COLOR4D& aDefaultColor ) :
52{
53 m_allowMouseEvents = false;
54 m_allowOpacityCtrl = aAllowOpacityControl;
55 m_previousColor4D = aCurrentColor;
56 m_newColor4D = aCurrentColor;
57 m_newColor4D.ToHSV( m_hue, m_sat, m_val, true );
58 m_bitmapRGB = nullptr;
59 m_bitmapHSV = nullptr;
60 m_selectedCursor = nullptr;
61 m_defaultColor = aDefaultColor;
62
64
65 m_OldColorRect->SetMinSize( FromDIP( wxSize( 20, 20 ) ) );
66 m_NewColorRect->SetMinSize( FromDIP( wxSize( 20, 20 ) ) );
67
68 m_colorValue->SetMinSize( wxSize( GetTextExtent( wxS( "#DDDDDDDD" ) ).x + FromDIP( 8 ), -1 ) );
69
71 {
72 m_SizerTransparency->Show( false );
73
74 if( aCurrentColor != COLOR4D::UNSPECIFIED )
75 {
76 m_previousColor4D.a = 1.0;
77 m_newColor4D.a = 1.0;
78 }
79 }
80
81 // UNSPECIFIED is ( 0, 0, 0, 0 ) but that is unfriendly for editing because you have to notice
82 // first that the value slider is all the way down before you get any color
83 if( aCurrentColor == COLOR4D::UNSPECIFIED )
84 m_val = 1.0;
85
87 wxASSERT( cfg );
88
89 m_notebook->SetSelection( cfg->m_ColorPicker.default_tab );
90
91 // Build the defined colors panel:
92 initDefinedColors( aUserColors );
93
101 if( aDefaultColor == COLOR4D::UNSPECIFIED )
102 m_resetToDefault->SetLabel( _( "Clear Color" ) );
103
105}
106
107
109{
111 wxASSERT( cfg );
112
113 if( cfg )
114 cfg->m_ColorPicker.default_tab = m_notebook->GetSelection();
115
116 delete m_bitmapRGB;
117 delete m_bitmapHSV;
118
119 for( wxStaticBitmap* swatch : m_colorSwatches )
120 {
121 swatch->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED,
122 wxMouseEventHandler( DIALOG_COLOR_PICKER::buttColorClick ),
123 nullptr, this );
124 }
125}
126
127
128void DIALOG_COLOR_PICKER::updatePreview( wxStaticBitmap* aStaticBitmap, COLOR4D& aColor4D )
129{
130 wxSize swatchSize = aStaticBitmap->GetSize();
131 wxSize checkerboardSize = ConvertDialogToPixels( CHECKERBOARD_SIZE_DU );
132
133 wxBitmap newBm = COLOR_SWATCH::MakeBitmap( aColor4D, COLOR4D::WHITE,
134 ToPhys( swatchSize ),
135 ToPhys( checkerboardSize ),
136 aStaticBitmap->GetParent()->GetBackgroundColour() );
137
138 newBm.SetScaleFactor( GetDPIScaleFactor() );
139 aStaticBitmap->SetBitmap( newBm );
140}
141
142
144{
145 SetEditVals( HEX_CHANGED, false );
146
147 // Configure the spin control sizes
153
154 m_notebook->GetPage( 0 )->Layout();
155 m_notebook->GetPage( 1 )->Layout();
156
158
159 // Draw all bitmaps, with colors according to the color 4D
161 drawAll();
162
163 return true;
164}
165
166
168{
169 #define ID_COLOR_BLACK 2000 // colors_id = ID_COLOR_BLACK a ID_COLOR_BLACK + NBCOLORS-1
170
171 // Colors are built from the colorRefs() table (size NBCOLORS).
172 // The look is better when colorRefs() order is displayed in a grid matrix
173 // of 7 row and 5 columns, first filling a row, and after the next column.
174 // But the wxFlexGrid used here must be filled by columns, then next row
175 // the best interval colorRefs() from a matrix row to the next row is 6
176 // So when have to reorder the index used to explore colorRefs()
177 int grid_col = 0;
178 int grid_row = 0;
179 int table_row_count = 7;
180
181 wxSize swatchSize = ConvertDialogToPixels( SWATCH_SIZE_LARGE_DU );
182 wxSize checkerboardSize = ConvertDialogToPixels( CHECKERBOARD_SIZE_DU );
183 COLOR4D checkboardBackground = m_OldColorRect->GetParent()->GetBackgroundColour();
184
185 auto addSwatch =
186 [&]( int aId, COLOR4D aColor, const wxString& aColorName )
187 {
188 wxBitmap bm = COLOR_SWATCH::MakeBitmap( aColor, COLOR4D::WHITE,
189 ToPhys( swatchSize ),
190 ToPhys( checkerboardSize ),
191 checkboardBackground );
192
193 bm.SetScaleFactor( GetDPIScaleFactor() );
194 wxStaticBitmap* swatch = new wxStaticBitmap( m_panelDefinedColors, aId, bm );
195
196 m_fgridColor->Add( swatch, 0, wxALIGN_CENTER_VERTICAL, 5 );
197
198 wxStaticText* label = new wxStaticText( m_panelDefinedColors, wxID_ANY, aColorName,
199 wxDefaultPosition, wxDefaultSize, 0 );
200 m_fgridColor->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxRIGHT, 15 );
201
202 m_colorSwatches.push_back( swatch );
203
204 swatch->Connect( wxEVT_LEFT_DOWN,
205 wxMouseEventHandler( DIALOG_COLOR_PICKER::buttColorClick ),
206 nullptr, this );
207 swatch->Connect( wxEVT_LEFT_DCLICK,
208 wxMouseEventHandler( DIALOG_COLOR_PICKER::colorDClick ),
209 nullptr, this );
210 };
211
212 // If no predefined list is given, build the default predefined colors:
213 if( aPredefinedColors )
214 {
215 for( unsigned jj = 0; jj < aPredefinedColors->size() && jj < NBCOLORS; ++jj )
216 {
217 CUSTOM_COLOR_ITEM* item = & *aPredefinedColors->begin() + jj;
218 int butt_ID = ID_COLOR_BLACK + jj;
219
220 addSwatch( butt_ID, item->m_Color, item->m_ColorName );
221 m_Color4DList.push_back( item->m_Color );
222 }
223 }
224 else
225 {
226 m_Color4DList.assign( NBCOLORS, COLOR4D( 0.0, 0.0, 0.0, 1.0 ) );
227
228 for( int jj = 0; jj < NBCOLORS; ++jj, grid_col++ )
229 {
230 if( grid_col * table_row_count >= NBCOLORS )
231 {
232 // the current grid row is filled, and we must fill the next grid row
233 grid_col = 0;
234 grid_row++;
235 }
236
237 int ii = grid_row + ( grid_col * table_row_count ); // The index in colorRefs()
238 int butt_ID = ID_COLOR_BLACK + ii;
239 COLOR4D buttcolor = COLOR4D( colorRefs()[ii].m_Numcolor );
240
241 addSwatch( butt_ID, buttcolor, wxGetTranslation( colorRefs()[ii].m_ColorName ) );
242 m_Color4DList[ butt_ID - ID_COLOR_BLACK ] = buttcolor;
243 }
244 }
245}
246
247
249{
250 wxSize bmsize = ToPhys( m_RgbBitmap->GetSize() );
251 int half_size = std::min( bmsize.x, bmsize.y )/2;
252
253 // We use here a Y axis from bottom to top and origin to center, So we need to map
254 // coordinated to write pixel in a wxImage. MAPX and MAPY are defined above so they
255 // must be undefined here to prevent compiler warnings.
256#undef MAPX
257#undef MAPY
258#define MAPX( xx ) bmsize.x / 2 + ( xx )
259#define MAPY( yy ) bmsize.y / 2 - ( yy )
260
261 // Reserve room to draw cursors inside the bitmap
262 half_size -= m_cursorsSize/2;
263
264 COLOR4D color;
265
266 // Red blue area in X Z 3d axis
267 double inc = 255.0 / half_size;
268 double slope = SLOPE_AXIS/half_size;
269 color.g = 0.0;
270
271 wxImage img( bmsize ); // a temporary buffer to build the color map
272
273 // clear background (set the window bg color)
274 wxColor bg = GetBackgroundColour();
275
276 // Don't do standard-color lookups on OSX each time through the loop
277 wxColourBase::ChannelType bgR = bg.Red();
278 wxColourBase::ChannelType bgG = bg.Green();
279 wxColourBase::ChannelType bgB = bg.Blue();
280
281 for( int xx = 0; xx < bmsize.x; xx++ ) // blue axis
282 {
283 for( int yy = 0; yy < bmsize.y; yy++ ) // Red axis
284 img.SetRGB( xx, yy, bgR, bgG, bgB );
285 }
286
287 // Build the palette
288 for( int xx = 0; xx < half_size; xx++ ) // blue axis
289 {
290 color.b = inc * xx;
291
292 for( int yy = 0; yy < half_size; yy++ ) // Red axis
293 {
294 color.r = inc * yy;
295 img.SetRGB( MAPX( xx ), MAPY( yy - (slope*xx) ), color.r, color.g, color.b );
296 }
297 }
298
299 // Red green area in y Z 3d axis
300 color.b = 0.0;
301
302 for( int xx = 0; xx < half_size; xx++ ) // green axis
303 {
304 color.g = inc * xx;
305
306 for( int yy = 0; yy < half_size; yy++ ) // Red axis
307 {
308 color.r = inc * yy;
309 img.SetRGB( MAPX( -xx ), MAPY( yy - (slope*xx) ), color.r, color.g, color.b );
310 }
311 }
312
313 // Blue green area in x y 3d axis
314 color.r = 0.0;
315
316 for( int xx = 0; xx < half_size; xx++ ) // green axis
317 {
318 color.g = inc * xx;
319
320 for( int yy = 0; yy < half_size; yy++ ) // blue axis
321 {
322 color.b = inc * yy;
323
324 // Mapping the xx, yy color axis to draw coordinates is more tricky than previously
325 // in DC coordinates:
326 // the blue axis is the (0, 0) to half_size, (-yy - SLOPE_AXIS)
327 // the green axis is the (0, 0) to - half_size, (-yy - SLOPE_AXIS)
328 int drawX = -xx + yy;
329 int drawY = - std::min( xx,yy ) * 0.9;
330 img.SetRGB( MAPX( drawX ), MAPY( drawY - std::abs( slope*drawX ) ),
331 color.r, color.g, color.b );
332 }
333 }
334
335 delete m_bitmapRGB;
336 m_bitmapRGB = new wxBitmap( img, 24 );
337
338 m_bitmapRGB->SetScaleFactor( GetDPIScaleFactor() );
339 m_RgbBitmap->SetBitmap( *m_bitmapRGB );
340}
341
342
344{
345 wxSize bmsize = ToPhys( m_HsvBitmap->GetSize() );
346 int half_size = std::min( bmsize.x, bmsize.y )/2;
347
348 // We use here a Y axis from bottom to top and origin to center, So we need to map
349 // coordinated to write pixel in a wxImage
350 #define MAPX( xx ) bmsize.x / 2 + ( xx )
351 #define MAPY( yy ) bmsize.y / 2 - ( yy )
352
353 wxImage img( bmsize ); // a temporary buffer to build the color map
354
355 // clear background (set the window bg color)
356 wxColor bg = GetBackgroundColour();
357
358 // Don't do standard-color lookups on OSX each time through the loop
359 wxColourBase::ChannelType bgR = bg.Red();
360 wxColourBase::ChannelType bgG = bg.Green();
361 wxColourBase::ChannelType bgB = bg.Blue();
362
363 for( int xx = 0; xx < bmsize.x; xx++ ) // blue axis
364 {
365 for( int yy = 0; yy < bmsize.y; yy++ ) // Red axis
366 img.SetRGB( xx, yy, bgR, bgG, bgB );
367 }
368
369 // Reserve room to draw cursors inside the bitmap
370 half_size -= m_cursorsSize/2;
371
372 double hue, sat;
373 COLOR4D color;
374 int sq_radius = half_size*half_size;
375
376 // Build the palette
377 for( int xx = -half_size; xx < half_size; xx++ )
378 {
379 for( int yy = -half_size; yy < half_size; yy++ )
380 {
381 sat = double(xx*xx + yy*yy) / sq_radius;
382
383 // sat is <= 1.0
384 // any value > 1.0 is not a valid HSB color:
385 if( sat > 1.0 )
386 continue;
387
388 // sat is the distance from center
389 sat = sqrt( sat );
390 hue = atan2( (double)yy, (double)xx ) * 180 / M_PI;
391
392 if( hue < 0.0 )
393 hue += 360.0;
394
395 color.FromHSV( hue, sat, 1.0 );
396
397 img.SetRGB( MAPX( xx ), MAPY( yy ), color.r * 255, color.g * 255, color.b * 255 );
398 }
399 }
400
401 delete m_bitmapHSV;
402 m_bitmapHSV = new wxBitmap( img, 24 );
403
404 m_bitmapHSV->SetScaleFactor( GetDPIScaleFactor() );
405 m_HsvBitmap->SetBitmap( *m_bitmapHSV );
406}
407
408
410{
411 if( !m_bitmapRGB || m_bitmapRGB->GetSize() != ToPhys( m_RgbBitmap->GetSize() ) )
413
414 wxMemoryDC bitmapDC;
415 wxSize bmsize = m_bitmapRGB->GetSize();
416 int half_size = std::min( bmsize.x, bmsize.y ) / 2;
417
418 wxBitmap newBm( *m_bitmapRGB );
419 newBm.SetScaleFactor( 1.0 );
420
421 bitmapDC.SelectObject( newBm );
422
423 // Use Y axis from bottom to top and origin to center
424 bitmapDC.SetAxisOrientation( true, true );
425
426#if defined( __WXMSW__ ) && !wxCHECK_VERSION( 3, 3, 0 )
427 // For some reason, SetDeviceOrigin has changed in wxWidgets 3.1.6 or 3.1.7
428 // It was fixed in wx >= 3.3
429 bitmapDC.SetDeviceOrigin( half_size, -half_size );
430#else
431 bitmapDC.SetDeviceOrigin( half_size, half_size );
432#endif
433
434 // Reserve room to draw cursors inside the bitmap
435 half_size -= m_cursorsSize / 2;
436
437 // Draw the 3 RGB cursors, using white color to make them always visible:
438 wxPen pen( wxColor( 255, 255, 255 ), 2 ); // use 2 pixels for pen size
439 wxBrush brush( wxColor( 0, 0, 0 ), wxBRUSHSTYLE_TRANSPARENT );
440 bitmapDC.SetPen( pen );
441 bitmapDC.SetBrush( brush );
442 int half_csize = m_cursorsSize / 2;
443
444 double slope = SLOPE_AXIS / half_size;
445
446 // Red axis cursor (Z 3Daxis):
447 m_cursorBitmapRed.x = 0;
448 m_cursorBitmapRed.y = m_newColor4D.r * half_size;
449 bitmapDC.DrawRectangle( m_cursorBitmapRed.x - half_csize,
450 m_cursorBitmapRed.y - half_csize,
452
453 // Blue axis cursor (X 3Daxis):
454 m_cursorBitmapBlue.x = m_newColor4D.b * half_size;
456 bitmapDC.DrawRectangle( m_cursorBitmapBlue.x - half_csize,
457 m_cursorBitmapBlue.y - half_csize,
459
460 // Green axis cursor (Y 3Daxis):
461 m_cursorBitmapGreen.x = m_newColor4D.g * half_size;
464
465 bitmapDC.DrawRectangle( m_cursorBitmapGreen.x - half_csize,
466 m_cursorBitmapGreen.y - half_csize,
468
469 // Draw the 3 RGB axis:
470 half_size += half_size/5;
471 bitmapDC.DrawLine( 0, 0, 0, half_size ); // Red axis (Z 3D axis)
472 bitmapDC.DrawLine( 0, 0, half_size, - half_size*slope ); // Blue axis (X 3D axis)
473 bitmapDC.DrawLine( 0, 0, -half_size, - half_size*slope ); // green axis (Y 3D axis)
474
475 newBm.SetScaleFactor( GetDPIScaleFactor() );
476 m_RgbBitmap->SetBitmap( newBm );
477
478 /* Deselect the Tool Bitmap from DC,
479 * in order to delete the MemoryDC safely without deleting the bitmap */
480 bitmapDC.SelectObject( wxNullBitmap );
481}
482
483
485{
486 if( !m_bitmapHSV || m_bitmapHSV->GetSize() != ToPhys( m_HsvBitmap->GetSize() ) )
488
489 wxMemoryDC bitmapDC;
490 wxSize bmsize = m_bitmapHSV->GetSize();
491 int half_size = std::min( bmsize.x, bmsize.y ) / 2;
492
493 wxBitmap newBm( *m_bitmapHSV );
494 newBm.SetScaleFactor( 1.0 );
495
496 bitmapDC.SelectObject( newBm );
497
498 // Use Y axis from bottom to top and origin to center
499 bitmapDC.SetAxisOrientation( true, true );
500#if defined( __WXMSW__ ) && !wxCHECK_VERSION(3,3,0)
501 // For some reason, SetDeviceOrigin has changed in wxWidgets 3.1.6 or 3.1.7
502 // It was fixed in wx >= 3.3
503 bitmapDC.SetDeviceOrigin( half_size, -half_size );
504#else
505 bitmapDC.SetDeviceOrigin( half_size, half_size );
506#endif
507
508 // Reserve room to draw cursors inside the bitmap
509 half_size -= m_cursorsSize / 2;
510
511 // Draw the HSB cursor:
512 m_cursorBitmapHSV.x = cos( m_hue * M_PI / 180.0 ) * half_size * m_sat;
513 m_cursorBitmapHSV.y = sin( m_hue * M_PI / 180.0 ) * half_size * m_sat;
514
515 wxPen pen( wxColor( 0, 0, 0 ), 2 ); // Use 2 pixels as pensize
516 wxBrush brush( wxColor( 0, 0, 0 ), wxBRUSHSTYLE_TRANSPARENT );
517 bitmapDC.SetPen( pen );
518 bitmapDC.SetBrush( brush );
519
520 bitmapDC.DrawRectangle( m_cursorBitmapHSV.x - ( m_cursorsSize / 2 ),
523
524 newBm.SetScaleFactor( GetDPIScaleFactor() );
525 m_HsvBitmap->SetBitmap( newBm );
526
527 /* Deselect the Tool Bitmap from DC,
528 * in order to delete the MemoryDC safely without deleting the bitmap
529 */
530 bitmapDC.SelectObject( wxNullBitmap );
531}
532
533
534void DIALOG_COLOR_PICKER::SetEditVals( CHANGED_COLOR aChanged, bool aCheckTransparency )
535{
536 if( aCheckTransparency )
537 {
538 // If they've changed the color, they probably don't want it to remain 100% transparent,
539 // and it looks like a bug when changing the color has no effect.
540 if( m_newColor4D.a == 0.0 )
541 m_newColor4D.a = 1.0;
542 }
543
545
546 if( aChanged == RED_CHANGED || aChanged == GREEN_CHANGED || aChanged == BLUE_CHANGED )
547 m_newColor4D.ToHSV( m_hue, m_sat, m_val, true );
548
549 if( aChanged != RED_CHANGED )
550 m_spinCtrlRed->SetValue( normalizeToInt( m_newColor4D.r ) );
551
552 if( aChanged != GREEN_CHANGED )
554
555 if( aChanged != BLUE_CHANGED )
557
558 if( aChanged != HUE_CHANGED )
559 m_spinCtrlHue->SetValue( (int)m_hue );
560
561 if( aChanged != SAT_CHANGED )
562 m_spinCtrlSaturation->SetValue( m_sat * 255 );
563
564 if( aChanged != VAL_CHANGED )
566
567 if( aChanged != HEX_CHANGED )
568 {
569 m_newColor4D.m_text = std::nullopt;
570 m_colorValue->ChangeValue( m_newColor4D.ToHexString() );
571 }
572}
573
574
576{
577 m_cursorsSize = ToPhys( FromDIP( 8 ) ); // Size of square cursors drawn on color bitmaps
578}
579
580
582{
584 m_NewColorRect->Freeze(); // Avoid flicker
585 m_HsvBitmap->Freeze();
586 m_RgbBitmap->Freeze();
590 m_NewColorRect->Thaw();
591 m_HsvBitmap->Thaw();
592 m_RgbBitmap->Thaw();
593 m_NewColorRect->Refresh();
594 m_HsvBitmap->Refresh();
595 m_RgbBitmap->Refresh();
596}
597
598
599void DIALOG_COLOR_PICKER::colorDClick( wxMouseEvent& event )
600{
601 wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
602}
603
604
605void DIALOG_COLOR_PICKER::buttColorClick( wxMouseEvent& event )
606{
607 int id = event.GetId();
608 COLOR4D color( m_Color4DList[id - ID_COLOR_BLACK] );
609 m_newColor4D.r = color.r;
610 m_newColor4D.g = color.g;
611 m_newColor4D.b = color.b;
612 m_newColor4D.a = color.a;
613
614 m_newColor4D.ToHSV( m_hue, m_sat, m_val, true );
615 SetEditVals( ALL_CHANGED, false );
616
617 drawAll();
618
619 event.Skip();
620}
621
622
623void DIALOG_COLOR_PICKER::onRGBMouseClick( wxMouseEvent& event )
624{
625 m_allowMouseEvents = true;
626
627 // The cursor position is relative to the m_bitmapHSV wxBitmap center
628 wxPoint mousePos = ToPhys( event.GetPosition() );
629 wxSize bmsize = m_bitmapRGB->GetSize();
630 int half_size = std::min( bmsize.x, bmsize.y ) / 2;
631
632 mousePos.x -= half_size;
633 mousePos.y -= half_size;
634 mousePos.y = -mousePos.y; // Use the bottom to top vertical axis
635
636 wxPoint dist = m_cursorBitmapRed - mousePos;
637
638 if( std::abs( dist.x ) <= m_cursorsSize/2 && std::abs( dist.y ) <= m_cursorsSize/2 )
639 {
641 return;
642 }
643
644 dist = m_cursorBitmapGreen - mousePos;
645
646 if( std::abs( dist.x ) <= m_cursorsSize / 2 && std::abs( dist.y ) <= m_cursorsSize / 2 )
647 {
649 return;
650 }
651
652 dist = m_cursorBitmapBlue - mousePos;
653
654 if( std::abs( dist.x ) <= m_cursorsSize / 2 && std::abs( dist.y ) <= m_cursorsSize / 2 )
655 {
657 return;
658 }
659
660 m_selectedCursor = nullptr;
661}
662
663
664void DIALOG_COLOR_PICKER::onRGBMouseDrag( wxMouseEvent& event )
665{
666 if( !event.Dragging() || !m_allowMouseEvents )
667 {
668 m_selectedCursor = nullptr;
669 return;
670 }
671
675 {
676 return;
677 }
678
679 // Adjust the HSV cursor position to follow the mouse cursor
680 // The cursor position is relative to the m_bitmapHSV wxBitmap center
681 wxPoint mousePos = ToPhys( event.GetPosition() );
682 wxSize bmsize = m_bitmapRGB->GetSize();
683 int half_size = std::min( bmsize.x, bmsize.y ) / 2;
684
685 mousePos.x -= half_size;
686 mousePos.y -= half_size;
687 mousePos.y = -mousePos.y; // Use the bottom to top vertical axis
688
689 half_size -= m_cursorsSize / 2; // the actual half_size of the palette area
690
691 // Change colors according to the selected cursor:
693 {
694 if( mousePos.y >= 0 && mousePos.y <= half_size )
695 m_newColor4D.r = (double)mousePos.y / half_size;
696 else
697 return;
698 }
699
701 {
702 mousePos.x = -mousePos.x;
703
704 if( mousePos.x >= 0 && mousePos.x <= half_size )
705 m_newColor4D.g = (double)mousePos.x / half_size;
706 else
707 return;
708 }
709
711 {
712 if( mousePos.x >= 0 && mousePos.x <= half_size )
713 m_newColor4D.b = (double)mousePos.x / half_size;
714 else
715 return;
716 }
717
718 m_newColor4D.ToHSV( m_hue, m_sat, m_val, true );
719 SetEditVals( ALL_CHANGED, true );
720
721 drawAll();
722}
723
724
725void DIALOG_COLOR_PICKER::onHSVMouseClick( wxMouseEvent& event )
726{
727 m_allowMouseEvents = true;
728
729 if( setHSvaluesFromCursor( event.GetPosition() ) )
730 drawAll();
731}
732
733
734void DIALOG_COLOR_PICKER::onHSVMouseDrag( wxMouseEvent& event )
735{
736 if( !event.Dragging() || !m_allowMouseEvents )
737 return;
738
739 if( setHSvaluesFromCursor( event.GetPosition() ) )
740 drawAll();
741}
742
743
744void DIALOG_COLOR_PICKER::onSize( wxSizeEvent& event )
745{
746 drawAll();
747
748 event.Skip();
749}
750
751
752void DIALOG_COLOR_PICKER::OnColorValueText( wxCommandEvent& event )
753{
754 if( m_newColor4D.SetFromHexString( m_colorValue->GetValue() ) )
755 m_newColor4D.ToHSV( m_hue, m_sat, m_val, true );
756
757 SetEditVals( HEX_CHANGED, false );
758 drawAll();
759}
760
761
762bool DIALOG_COLOR_PICKER::setHSvaluesFromCursor( const wxPoint& aMouseCursor )
763{
764 wxPoint mousePos = ToPhys( aMouseCursor );
765 wxSize bmsize = m_bitmapHSV->GetSize();
766 int half_size = std::min( bmsize.x, bmsize.y ) / 2;
767
768 // Make the cursor position relative to the m_bitmapHSV wxBitmap center
769 mousePos.x -= half_size;
770 mousePos.y -= half_size;
771 mousePos.y = -mousePos.y; // Use the bottom to top vertical axis
772
773 // The HS cursor position is restricted to a circle of radius half_size
774 double dist_from_centre = hypot( (double)mousePos.x, (double)mousePos.y );
775
776 if( dist_from_centre > half_size )
777 {
778 // Saturation cannot be calculated:
779 return false;
780 }
781
782 m_cursorBitmapHSV = mousePos;
783
784 // Set saturation and hue from new cursor position:
785 half_size -= m_cursorsSize / 2; // the actual half_size of the palette area
786 m_sat = dist_from_centre / half_size;
787
788 if( m_sat > 1.0 )
789 m_sat = 1.0;
790
791 m_hue = atan2( mousePos.y, mousePos.x ) / M_PI * 180.0;
792
793 if( m_hue < 0 )
794 m_hue += 360.0;
795
796 m_newColor4D.FromHSV( m_hue, m_sat, m_val );
797 SetEditVals( ALL_CHANGED, true );
798
799 return true;
800}
801
802
803void DIALOG_COLOR_PICKER::OnChangeAlpha( wxScrollEvent& event )
804{
805 double alpha = (double)event.GetPosition() / ALPHA_MAX;
806 m_newColor4D.a = alpha;
807 m_NewColorRect->Freeze(); // Avoid flicker
809 m_NewColorRect->Thaw();
810 m_NewColorRect->Refresh();
811 SetEditVals( ALPHA_CHANGED, false );
812}
813
814
815void DIALOG_COLOR_PICKER::OnChangeEditRed( wxSpinEvent& event )
816{
817 double val = (double)event.GetPosition() / 255.0;
818 m_newColor4D.r = val;
819 SetEditVals( RED_CHANGED, true );
820
821 drawAll();
822}
823
824
826{
827 double val = (double)event.GetPosition() / 255.0;
828 m_newColor4D.g = val;
829 SetEditVals( GREEN_CHANGED, true );
830
831 drawAll();
832}
833
834
836{
837 double val = (double)event.GetPosition() / 255.0;
838 m_newColor4D.b = val;
839 SetEditVals( BLUE_CHANGED, true );
840
841 drawAll();
842}
843
844
845void DIALOG_COLOR_PICKER::OnChangeEditHue( wxSpinEvent& event )
846{
847 m_hue = (double)event.GetPosition();
848
849 m_newColor4D.FromHSV( m_hue, m_sat, m_val );
850
851 SetEditVals( HUE_CHANGED, true );
852
853 drawAll();
854}
855
856
857void DIALOG_COLOR_PICKER::OnChangeEditSat( wxSpinEvent& event )
858{
859 m_sat = (double)event.GetPosition() / 255.0;
860
861 m_newColor4D.FromHSV( m_hue, m_sat, m_val );
862
863 SetEditVals( SAT_CHANGED, true );
864
865 drawAll();
866}
867
868
869void DIALOG_COLOR_PICKER::OnChangeBrightness( wxScrollEvent& event )
870{
871 m_val = (double)event.GetPosition() / 255.0;
872
873 m_newColor4D.FromHSV( m_hue, m_sat, m_val );
874
875 SetEditVals( VAL_CHANGED, true );
876
877 drawAll();
878}
879
880
881void DIALOG_COLOR_PICKER::OnResetButton( wxCommandEvent& aEvent )
882{
887
888 m_newColor4D.ToHSV( m_hue, m_sat, m_val, true );
889 SetEditVals( ALL_CHANGED, false );
890
891 drawAll();
892}
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
APP_SETTINGS_BASE is a settings class that should be derived for each standalone KiCad application.
COLOR_PICKER m_ColorPicker
static const COLOR4D WHITE
Definition color4d.h:405
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition color4d.h:402
static wxBitmap MakeBitmap(const KIGFX::COLOR4D &aColor, const KIGFX::COLOR4D &aBackground, const wxSize &aSize, const wxSize &aCheckerboardSize, const KIGFX::COLOR4D &aCheckerboardBackground, const std::vector< int > &aMargins={ 0, 0, 0, 0 })
DIALOG_COLOR_PICKER_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Color Picker"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
KIGFX::COLOR4D m_previousColor4D
the initial color4d
void buttColorClick(wxMouseEvent &event)
Event handler for double click on color buttons.
void OnResetButton(wxCommandEvent &aEvent) override
void initDefinedColors(CUSTOM_COLORS_LIST *aPredefinedColors)
Create the bitmap buttons for each defined colors.
void colorDClick(wxMouseEvent &event)
called when creating the dialog
void OnChangeAlpha(wxScrollEvent &event) override
Event handlers from wxSpinControl.
void onRGBMouseDrag(wxMouseEvent &event) override
wxPoint m_cursorBitmapGreen
the green cursor on the RGB bitmap palette.
KIGFX::COLOR4D m_newColor4D
the current color4d
double m_val
the current value (0 ... 1.0)
void OnChangeEditGreen(wxSpinEvent &event) override
void createRGBBitmap()
generate the bitmap that shows the RVB color space
DIALOG_COLOR_PICKER(wxWindow *aParent, const KIGFX::COLOR4D &aCurrentColor, bool aAllowOpacityControl, CUSTOM_COLORS_LIST *aUserColors=nullptr, const KIGFX::COLOR4D &aDefaultColor=KIGFX::COLOR4D::UNSPECIFIED)
Dialog constructor.
std::vector< wxStaticBitmap * > m_colorSwatches
list of defined colors buttons
wxBitmap * m_bitmapRGB
the basic RGB palette
void OnChangeEditBlue(wxSpinEvent &event) override
wxPoint m_cursorBitmapBlue
the blue cursor on the RGB bitmap palette.
wxBitmap * m_bitmapHSV
the basic HUV palette
void OnColorValueText(wxCommandEvent &event) override
Event handler for the reset button press.
void createHSVBitmap()
generate the bitmap that shows the HSV color circle
std::vector< KIGFX::COLOR4D > m_Color4DList
the list of color4d ordered by button ID, for predefined colors
void onRGBMouseClick(wxMouseEvent &event) override
wxPoint m_cursorBitmapRed
the red cursor on the RGB bitmap palette.
double m_hue
the current hue, in degrees (0 ... 360)
bool setHSvaluesFromCursor(const wxPoint &aMouseCursor)
Manage the Hue and Saturation settings when the mouse cursor is at aMouseCursor.
void OnChangeEditSat(wxSpinEvent &event) override
mouse handlers, when clicking on a palette bitmap
double m_sat
the current saturation (0 ... 1.0)
bool m_allowOpacityCtrl
true to show the widget, false to keep alpha channel = 1.0
bool TransferDataToWindow() override
void drawHSVPalette()
draws the HSV color circle
void onHSVMouseClick(wxMouseEvent &event) override
void onHSVMouseDrag(wxMouseEvent &event) override
void updatePreview(wxStaticBitmap *aStaticBitmap, KIGFX::COLOR4D &aColor4D)
Event handler from wxSlider: brightness (value) control.
void onSize(wxSizeEvent &event) override
KIGFX::COLOR4D m_defaultColor
The default color4d.
void OnChangeEditRed(wxSpinEvent &event) override
void OnChangeEditHue(wxSpinEvent &event) override
int normalizeToInt(double aValue, int aValMax=255)
void SetEditVals(CHANGED_COLOR aChanged, bool aCheckTransparency)
wxPoint m_cursorBitmapHSV
the cursor on the HSV bitmap palette.
void drawRGBPalette()
draws the RVB color space
void OnChangeBrightness(wxScrollEvent &event) override
Event handler from wxSlider: alpha (transparency) control.
wxPoint * m_selectedCursor
the ref cursor to the selected cursor, if any, or null.
void SetupStandardButtons(std::map< int, wxString > aLabels={})
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
APP_SETTINGS_BASE * KifaceSettings() const
Definition kiface_base.h:95
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:105
double r
Red component.
Definition color4d.h:393
double g
Green component.
Definition color4d.h:394
void FromHSV(double aInH, double aInS, double aInV)
Changes currently used color to the one given by hue, saturation and value parameters.
Definition color4d.cpp:429
double a
Alpha component.
Definition color4d.h:396
double b
Blue component.
Definition color4d.h:395
const StructColors * colorRefs()
Global list of legacy color names, still used all over the place for constructing COLOR4D's.
Definition color4d.cpp:40
@ NBCOLORS
Number of colors.
Definition color4d.h:79
static const wxSize SWATCH_SIZE_LARGE_DU(24, 16)
static const wxSize CHECKERBOARD_SIZE_DU(3, 3)
#define SLOPE_AXIS
#define ID_COLOR_BLACK
void configureSpinCtrl(wxSpinCtrl *aCtrl)
#define ALPHA_MAX
#define MAPX(xx)
#define MAPY(yy)
@ VAL_CHANGED
@ HUE_CHANGED
@ HEX_CHANGED
@ RED_CHANGED
@ ALL_CHANGED
@ ALPHA_CHANGED
@ GREEN_CHANGED
@ SAT_CHANGED
@ BLUE_CHANGED
std::vector< CUSTOM_COLOR_ITEM > CUSTOM_COLORS_LIST
#define _(s)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:400
A class to handle a custom color (predefined color) for the color picker dialog.
#define M_PI