KiCad PCB EDA Suite
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 (C) 2018-2022 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
22#include <cmath>
23#include <algorithm>
24#include <kiface_base.h>
27#include <wx/bitmap.h>
28#include <wx/dcmemory.h>
29
30#define ALPHA_MAX 100 // the max value returned by the alpha (opacity) slider
31
32using KIGFX::COLOR4D;
33
34// Configure the spin controls contained inside the dialog
35void configureSpinCtrl( wxSpinCtrl* aCtrl )
36{
37 wxSize textLength = aCtrl->GetTextExtent( "999" );
38 wxSize ctrlSize = aCtrl->GetSizeFromTextSize( textLength );
39
40 aCtrl->SetMinSize( ctrlSize );
41 aCtrl->SetSize( ctrlSize );
42}
43
44
45DIALOG_COLOR_PICKER::DIALOG_COLOR_PICKER( wxWindow* aParent, const COLOR4D& aCurrentColor,
46 bool aAllowOpacityControl,
47 CUSTOM_COLORS_LIST* aUserColors,
48 const COLOR4D& aDefaultColor ) :
50{
51 m_allowMouseEvents = false;
52 m_allowOpacityCtrl = aAllowOpacityControl;
53 m_previousColor4D = aCurrentColor;
54 m_newColor4D = aCurrentColor;
55 m_cursorsSize = 8; // Size of square cursors drawn on color bitmaps
57 m_bitmapRGB = nullptr;
58 m_bitmapHSV = nullptr;
59 m_selectedCursor = nullptr;
60 m_defaultColor = aDefaultColor;
61
63 {
64 m_SizerTransparency->Show( false );
65
66 if( aCurrentColor != COLOR4D::UNSPECIFIED )
67 {
68 m_previousColor4D.a = 1.0;
69 m_newColor4D.a = 1.0;
70 }
71 }
72
73 // UNSPECIFIED is ( 0, 0, 0, 0 ) but that is unfriendly for editing because you have to notice
74 // first that the value slider is all the way down before you get any color
75 if( aCurrentColor == COLOR4D::UNSPECIFIED )
76 m_val = 1.0;
77
79 wxASSERT( cfg );
80
81 m_notebook->SetSelection( cfg->m_ColorPicker.default_tab );
82
83 // Build the defined colors panel:
84 initDefinedColors( aUserColors );
85
93 if( aDefaultColor == COLOR4D::UNSPECIFIED )
94 m_resetToDefault->SetLabel( _( "Clear Color" ) );
95
97}
98
99
101{
103 wxASSERT( cfg );
104
105 cfg->m_ColorPicker.default_tab = m_notebook->GetSelection();
106
107 delete m_bitmapRGB;
108 delete m_bitmapHSV;
109
110 for( wxStaticBitmap* swatch : m_colorSwatches )
111 {
112 swatch->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED,
113 wxMouseEventHandler( DIALOG_COLOR_PICKER::buttColorClick ),
114 nullptr, this );
115 }
116}
117
118
119void DIALOG_COLOR_PICKER::updatePreview( wxStaticBitmap* aStaticBitmap, COLOR4D& aColor4D )
120{
121 wxBitmap newBm = COLOR_SWATCH::MakeBitmap( aColor4D, COLOR4D::WHITE, aStaticBitmap->GetSize(),
122 ConvertDialogToPixels( CHECKERBOARD_SIZE_DU ),
123 aStaticBitmap->GetParent()->GetBackgroundColour() );
124 aStaticBitmap->SetBitmap( newBm );
125}
126
127
129{
130 // Draw all bitmaps, with colors according to the color 4D
132 SetEditVals( ALL_CHANGED, false );
133 drawAll();
134
135 // Configure the spin control sizes
141
142 m_notebook->GetPage( 0 )->Layout();
143 m_notebook->GetPage( 1 )->Layout();
144
146
147 return true;
148}
149
150
152{
153 #define ID_COLOR_BLACK 2000 // colors_id = ID_COLOR_BLACK a ID_COLOR_BLACK + NBCOLORS-1
154
155 // Colors are built from the colorRefs() table (size NBCOLORS).
156 // The look is better when colorRefs() order is displayed in a grid matrix
157 // of 7 row and 5 columns, first filling a row, and after the next column.
158 // But the wxFlexGrid used here must be filled by columns, then next row
159 // the best interval colorRefs() from a matrix row to the next row is 6
160 // So when have to reorder the index used to explore colorRefs()
161 int grid_col = 0;
162 int grid_row = 0;
163 int table_row_count = 7;
164
165 wxSize swatchSize = ConvertDialogToPixels( SWATCH_SIZE_LARGE_DU );
166 wxSize checkerboardSize = ConvertDialogToPixels( CHECKERBOARD_SIZE_DU );
167 COLOR4D checkboardBackground = m_OldColorRect->GetParent()->GetBackgroundColour();
168
169 auto addSwatch =
170 [&]( int aId, COLOR4D aColor, const wxString& aColorName )
171 {
172 wxBitmap bm = COLOR_SWATCH::MakeBitmap( aColor, COLOR4D::WHITE, swatchSize,
173 checkerboardSize, checkboardBackground );
174 wxStaticBitmap* swatch = new wxStaticBitmap( m_panelDefinedColors, aId, bm );
175
176 m_fgridColor->Add( swatch, 0, wxALIGN_CENTER_VERTICAL, 5 );
177
178 wxStaticText* label = new wxStaticText( m_panelDefinedColors, wxID_ANY, aColorName,
179 wxDefaultPosition, wxDefaultSize, 0 );
180 m_fgridColor->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxRIGHT, 15 );
181
182 m_colorSwatches.push_back( swatch );
183
184 swatch->Connect( wxEVT_LEFT_DOWN,
185 wxMouseEventHandler( DIALOG_COLOR_PICKER::buttColorClick ),
186 nullptr, this );
187 swatch->Connect( wxEVT_LEFT_DCLICK,
188 wxMouseEventHandler( DIALOG_COLOR_PICKER::colorDClick ),
189 nullptr, this );
190 };
191
192 // If no predefined list is given, build the default predefined colors:
193 if( aPredefinedColors )
194 {
195 for( unsigned jj = 0; jj < aPredefinedColors->size() && jj < NBCOLORS; ++jj )
196 {
197 CUSTOM_COLOR_ITEM* item = & *aPredefinedColors->begin() + jj;
198 int butt_ID = ID_COLOR_BLACK + jj;
199
200 addSwatch( butt_ID, item->m_Color, item->m_ColorName );
201 m_Color4DList.push_back( item->m_Color );
202 }
203 }
204 else
205 {
206 m_Color4DList.assign( NBCOLORS, COLOR4D( 0.0, 0.0, 0.0, 1.0 ) );
207
208 for( int jj = 0; jj < NBCOLORS; ++jj, grid_col++ )
209 {
210 if( grid_col * table_row_count >= NBCOLORS )
211 {
212 // the current grid row is filled, and we must fill the next grid row
213 grid_col = 0;
214 grid_row++;
215 }
216
217 int ii = grid_row + ( grid_col * table_row_count ); // The index in colorRefs()
218 int butt_ID = ID_COLOR_BLACK + ii;
219 COLOR4D buttcolor = COLOR4D( colorRefs()[ii].m_Numcolor );
220
221 addSwatch( butt_ID, buttcolor, wxGetTranslation( colorRefs()[ii].m_ColorName ) );
222 m_Color4DList[ butt_ID - ID_COLOR_BLACK ] = buttcolor;
223 }
224 }
225}
226
227
229{
230 wxSize bmsize = m_RgbBitmap->GetSize();
231 int half_size = std::min( bmsize.x, bmsize.y )/2;
232
233 // We use here a Y axis from bottom to top and origin to center, So we need to map
234 // coordinated to write pixel in a wxImage. MAPX and MAPY are defined above so they
235 // must be undefined here to prevent compiler warnings.
236#undef MAPX
237#undef MAPY
238#define MAPX( xx ) bmsize.x / 2 + ( xx )
239#define MAPY( yy ) bmsize.y / 2 - ( yy )
240
241 // Reserve room to draw cursors inside the bitmap
242 half_size -= m_cursorsSize/2;
243
245
246 // Red blue area in X Z 3d axis
247 double inc = 255.0 / half_size;
248 #define SLOPE_AXIS 50.0
249 double slope = SLOPE_AXIS/half_size;
250 color.g = 0.0;
251
252 wxImage img( bmsize ); // a temporary buffer to build the color map
253
254 // clear background (set the window bg color)
255 wxColor bg = GetBackgroundColour();
256
257 // Don't do standard-color lookups on OSX each time through the loop
258 wxColourBase::ChannelType bgR = bg.Red();
259 wxColourBase::ChannelType bgG = bg.Green();
260 wxColourBase::ChannelType bgB = bg.Blue();
261
262 for( int xx = 0; xx < bmsize.x; xx++ ) // blue axis
263 {
264 for( int yy = 0; yy < bmsize.y; yy++ ) // Red axis
265 img.SetRGB( xx, yy, bgR, bgG, bgB );
266 }
267
268 // Build the palette
269 for( int xx = 0; xx < half_size; xx++ ) // blue axis
270 {
271 color.b = inc * xx;
272
273 for( int yy = 0; yy < half_size; yy++ ) // Red axis
274 {
275 color.r = inc * yy;
276 img.SetRGB( MAPX( xx ), MAPY( yy - (slope*xx) ), color.r, color.g, color.b );
277 }
278 }
279
280 // Red green area in y Z 3d axis
281 color.b = 0.0;
282
283 for( int xx = 0; xx < half_size; xx++ ) // green axis
284 {
285 color.g = inc * xx;
286
287 for( int yy = 0; yy < half_size; yy++ ) // Red axis
288 {
289 color.r = inc * yy;
290 img.SetRGB( MAPX( -xx ), MAPY( yy - (slope*xx) ), color.r, color.g, color.b );
291 }
292 }
293
294 // Blue green area in x y 3d axis
295 color.r = 0.0;
296
297 for( int xx = 0; xx < half_size; xx++ ) // green axis
298 {
299 color.g = inc * xx;
300
301 for( int yy = 0; yy < half_size; yy++ ) // blue axis
302 {
303 color.b = inc * yy;
304
305 // Mapping the xx, yy color axis to draw coordinates is more tricky than previously
306 // in DC coordinates:
307 // the blue axis is the (0, 0) to half_size, (-yy - SLOPE_AXIS)
308 // the green axis is the (0, 0) to - half_size, (-yy - SLOPE_AXIS)
309 int drawX = -xx + yy;
310 int drawY = - std::min( xx,yy ) * 0.9;
311 img.SetRGB( MAPX( drawX ), MAPY( drawY - std::abs( slope*drawX ) ),
312 color.r, color.g, color.b );
313 }
314 }
315
316 delete m_bitmapRGB;
317 m_bitmapRGB = new wxBitmap( img, 24 );
318 m_RgbBitmap->SetBitmap( *m_bitmapRGB );
319}
320
321
323{
324 wxSize bmsize = m_HsvBitmap->GetSize();
325 int half_size = std::min( bmsize.x, bmsize.y )/2;
326
327 // We use here a Y axis from bottom to top and origin to center, So we need to map
328 // coordinated to write pixel in a wxImage
329 #define MAPX( xx ) bmsize.x / 2 + ( xx )
330 #define MAPY( yy ) bmsize.y / 2 - ( yy )
331
332 wxImage img( bmsize ); // a temporary buffer to build the color map
333
334 // clear background (set the window bg color)
335 wxColor bg = GetBackgroundColour();
336
337 // Don't do standard-color lookups on OSX each time through the loop
338 wxColourBase::ChannelType bgR = bg.Red();
339 wxColourBase::ChannelType bgG = bg.Green();
340 wxColourBase::ChannelType bgB = bg.Blue();
341
342 for( int xx = 0; xx < bmsize.x; xx++ ) // blue axis
343 {
344 for( int yy = 0; yy < bmsize.y; yy++ ) // Red axis
345 img.SetRGB( xx, yy, bgR, bgG, bgB );
346 }
347
348 // Reserve room to draw cursors inside the bitmap
349 half_size -= m_cursorsSize/2;
350
351 double hue, sat;
353 int sq_radius = half_size*half_size;
354
355 // Build the palette
356 for( int xx = -half_size; xx < half_size; xx++ )
357 {
358 for( int yy = -half_size; yy < half_size; yy++ )
359 {
360 sat = double(xx*xx + yy*yy) / sq_radius;
361
362 // sat is <= 1.0
363 // any value > 1.0 is not a valid HSB color:
364 if( sat > 1.0 )
365 continue;
366
367 // sat is the distance from center
368 sat = sqrt( sat );
369 hue = atan2( (double)yy, (double)xx ) * 180 / M_PI;
370
371 if( hue < 0.0 )
372 hue += 360.0;
373
374 color.FromHSV( hue, sat, 1.0 );
375
376 img.SetRGB( MAPX( xx ), MAPY( yy ), color.r*255, color.g*255, color.b*255 );
377 }
378 }
379
380 delete m_bitmapHSV;
381 m_bitmapHSV = new wxBitmap( img, 24 );
382 m_HsvBitmap->SetBitmap( *m_bitmapHSV );
383}
384
385
387{
388 if( !m_bitmapRGB || m_bitmapRGB->GetSize() != m_RgbBitmap->GetSize() )
390
391 wxMemoryDC bitmapDC;
392 wxSize bmsize = m_bitmapRGB->GetSize();
393 int half_size = std::min( bmsize.x, bmsize.y )/2;
394 wxBitmap newBm( *m_bitmapRGB );
395 bitmapDC.SelectObject( newBm );
396
397 // Use Y axis from bottom to top and origin to center
398 bitmapDC.SetAxisOrientation( true, true );
399 #if wxCHECK_VERSION( 3, 1, 7 )
400 // For some reason, SetDeviceOrigin has changed in wxWidgets 3.1.6 or 3.1.7
401 bitmapDC.SetDeviceOrigin( half_size, -half_size );
402 #else
403 bitmapDC.SetDeviceOrigin( half_size, half_size );
404 #endif
405
406 // Reserve room to draw cursors inside the bitmap
407 half_size -= m_cursorsSize/2;
408
409 // Draw the 3 RGB cursors, using white color to make them always visible:
410 wxPen pen( wxColor( 255, 255, 255 ), 2 ); // use 2 pixels for pen size
411 wxBrush brush( wxColor( 0, 0, 0 ), wxBRUSHSTYLE_TRANSPARENT );
412 bitmapDC.SetPen( pen );
413 bitmapDC.SetBrush( brush );
414 int half_csize = m_cursorsSize / 2;
415
416 #define SLOPE_AXIS 50.0
417 double slope = SLOPE_AXIS / half_size;
418
419 // Red axis cursor (Z 3Daxis):
420 m_cursorBitmapRed.x = 0;
421 m_cursorBitmapRed.y = m_newColor4D.r * half_size;
422 bitmapDC.DrawRectangle( m_cursorBitmapRed.x - half_csize,
423 m_cursorBitmapRed.y - half_csize,
425
426 // Blue axis cursor (X 3Daxis):
427 m_cursorBitmapBlue.x = m_newColor4D.b * half_size;
429 bitmapDC.DrawRectangle( m_cursorBitmapBlue.x - half_csize,
430 m_cursorBitmapBlue.y - half_csize,
432
433 // Green axis cursor (Y 3Daxis):
434 m_cursorBitmapGreen.x = m_newColor4D.g * half_size;
437
438 bitmapDC.DrawRectangle( m_cursorBitmapGreen.x - half_csize,
439 m_cursorBitmapGreen.y - half_csize,
441
442 // Draw the 3 RGB axis:
443 half_size += half_size/5;
444 bitmapDC.DrawLine( 0, 0, 0, half_size ); // Red axis (Z 3D axis)
445 bitmapDC.DrawLine( 0, 0, half_size, - half_size*slope ); // Blue axis (X 3D axis)
446 bitmapDC.DrawLine( 0, 0, -half_size, - half_size*slope ); // green axis (Y 3D axis)
447
448 m_RgbBitmap->SetBitmap( newBm );
449
450 /* Deselect the Tool Bitmap from DC,
451 * in order to delete the MemoryDC safely without deleting the bitmap */
452 bitmapDC.SelectObject( wxNullBitmap );
453}
454
455
457{
458 if( !m_bitmapHSV || m_bitmapHSV->GetSize() != m_HsvBitmap->GetSize() )
460
461 wxMemoryDC bitmapDC;
462 wxSize bmsize = m_bitmapHSV->GetSize();
463 int half_size = std::min( bmsize.x, bmsize.y ) / 2;
464 wxBitmap newBm( *m_bitmapHSV );
465 bitmapDC.SelectObject( newBm );
466
467 // Use Y axis from bottom to top and origin to center
468 bitmapDC.SetAxisOrientation( true, true );
469 #if wxCHECK_VERSION( 3, 1, 7 )
470 // For some reason, SetDeviceOrigin has changed in wxWidgets 3.1.6 or 3.1.7
471 bitmapDC.SetDeviceOrigin( half_size, -half_size );
472 #else
473 bitmapDC.SetDeviceOrigin( half_size, half_size );
474 #endif
475
476 // Reserve room to draw cursors inside the bitmap
477 half_size -= m_cursorsSize / 2;
478
479 // Draw the HSB cursor:
480 m_cursorBitmapHSV.x = cos( m_hue * M_PI / 180.0 ) * half_size * m_sat;
481 m_cursorBitmapHSV.y = sin( m_hue * M_PI / 180.0 ) * half_size * m_sat;
482
483 wxPen pen( wxColor( 0, 0, 0 ), 2 ); // Use 2 pixels as pensize
484 wxBrush brush( wxColor( 0, 0, 0 ), wxBRUSHSTYLE_TRANSPARENT );
485 bitmapDC.SetPen( pen );
486 bitmapDC.SetBrush( brush );
487
488 int half_csize = m_cursorsSize/2;
489 bitmapDC.DrawRectangle( m_cursorBitmapHSV.x- half_csize,
490 m_cursorBitmapHSV.y-half_csize,
492
493 m_HsvBitmap->SetBitmap( newBm );
494
495 /* Deselect the Tool Bitmap from DC,
496 * in order to delete the MemoryDC safely without deleting the bitmap
497 */
498 bitmapDC.SelectObject( wxNullBitmap );
499}
500
501
502void DIALOG_COLOR_PICKER::SetEditVals( CHANGED_COLOR aChanged, bool aCheckTransparency )
503{
504 if( aCheckTransparency )
505 {
506 // If they've changed the color, they probably don't want it to remain 100% transparent,
507 // and it looks like a bug when changing the color has no effect.
508 if( m_newColor4D.a == 0.0 )
509 m_newColor4D.a = 1.0;
510 }
511
513
514 if( aChanged == RED_CHANGED || aChanged == GREEN_CHANGED || aChanged == BLUE_CHANGED )
516
517 if( aChanged != RED_CHANGED )
519
520 if( aChanged != GREEN_CHANGED )
522
523 if( aChanged != BLUE_CHANGED )
525
526 if( aChanged != HUE_CHANGED )
527 m_spinCtrlHue->SetValue( (int)m_hue );
528
529 if( aChanged != SAT_CHANGED )
530 m_spinCtrlSaturation->SetValue( m_sat * 255 );
531
532 if( aChanged != VAL_CHANGED )
534
535 if( aChanged == HEX_CHANGED )
537 else
538 m_colorValue->ChangeValue( m_newColor4D.ToHexString() );
539}
540
541
543{
544 m_NewColorRect->Freeze(); // Avoid flicker
545 m_HsvBitmap->Freeze();
546 m_RgbBitmap->Freeze();
550 m_NewColorRect->Thaw();
551 m_HsvBitmap->Thaw();
552 m_RgbBitmap->Thaw();
553 m_NewColorRect->Refresh();
554 m_HsvBitmap->Refresh();
555 m_RgbBitmap->Refresh();
556}
557
558
559void DIALOG_COLOR_PICKER::colorDClick( wxMouseEvent& event )
560{
561 wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
562}
563
564
565void DIALOG_COLOR_PICKER::buttColorClick( wxMouseEvent& event )
566{
567 int id = event.GetId();
569 m_newColor4D.r = color.r;
570 m_newColor4D.g = color.g;
571 m_newColor4D.b = color.b;
572 m_newColor4D.a = color.a;
573
575 SetEditVals( ALL_CHANGED, false );
576
577 drawAll();
578
579 event.Skip();
580}
581
582
583void DIALOG_COLOR_PICKER::onRGBMouseClick( wxMouseEvent& event )
584{
585 m_allowMouseEvents = true;
586 wxPoint mousePos = event.GetPosition();
587
588 // The cursor position is relative to the m_bitmapHSV wxBitmap center
589 wxSize bmsize = m_bitmapRGB->GetSize();
590 int half_size = std::min( bmsize.x, bmsize.y ) / 2;
591 mousePos.x -= half_size;
592 mousePos.y -= half_size;
593 mousePos.y = -mousePos.y; // Use the bottom to top vertical axis
594
595 wxPoint dist = m_cursorBitmapRed - mousePos;
596
597 if( std::abs( dist.x ) <= m_cursorsSize/2 && std::abs( dist.y ) <= m_cursorsSize/2 )
598 {
600 return;
601 }
602
603 dist = m_cursorBitmapGreen - mousePos;
604
605 if( std::abs( dist.x ) <= m_cursorsSize/2 && std::abs( dist.y ) <= m_cursorsSize/2 )
606 {
608 return;
609 }
610
611 dist = m_cursorBitmapBlue - mousePos;
612
613 if( std::abs( dist.x ) <= m_cursorsSize/2 && std::abs( dist.y ) <= m_cursorsSize/2 )
614 {
616 return;
617 }
618
619 m_selectedCursor = nullptr;
620}
621
622
623void DIALOG_COLOR_PICKER::onRGBMouseDrag( wxMouseEvent& event )
624{
625 if( !event.Dragging() || !m_allowMouseEvents )
626 {
627 m_selectedCursor = nullptr;
628 return;
629 }
630
634 {
635 return;
636 }
637
638 // Adjust the HSV cursor position to follow the mouse cursor
639 // The cursor position is relative to the m_bitmapHSV wxBitmap center
640 wxPoint mousePos = event.GetPosition();
641 wxSize bmsize = m_bitmapRGB->GetSize();
642 int half_size = std::min( bmsize.x, bmsize.y ) / 2;
643 mousePos.x -= half_size;
644 mousePos.y -= half_size;
645 mousePos.y = -mousePos.y; // Use the bottom to top vertical axis
646
647 half_size -= m_cursorsSize / 2; // the actual half_size of the palette area
648
649 // Change colors according to the selected cursor:
651 {
652 if( mousePos.y >= 0 && mousePos.y <= half_size )
653 m_newColor4D.r = (double)mousePos.y / half_size;
654 else
655 return;
656 }
657
659 {
660 mousePos.x = -mousePos.x;
661
662 if( mousePos.x >= 0 && mousePos.x <= half_size )
663 m_newColor4D.g = (double)mousePos.x / half_size;
664 else
665 return;
666 }
667
669 {
670 if( mousePos.x >= 0 && mousePos.x <= half_size )
671 m_newColor4D.b = (double)mousePos.x / half_size;
672 else
673 return;
674 }
675
677 SetEditVals( ALL_CHANGED, true );
678
679 drawAll();
680}
681
682
683void DIALOG_COLOR_PICKER::onHSVMouseClick( wxMouseEvent& event )
684{
685 m_allowMouseEvents = true;
686
687 if( setHSvaluesFromCursor( event.GetPosition() ) )
688 drawAll();
689}
690
691
692void DIALOG_COLOR_PICKER::onHSVMouseDrag( wxMouseEvent& event )
693{
694 if( !event.Dragging() || !m_allowMouseEvents )
695 return;
696
697 if( setHSvaluesFromCursor( event.GetPosition() ) )
698 drawAll();
699}
700
701
702void DIALOG_COLOR_PICKER::OnColorValueText( wxCommandEvent& event )
703{
704 m_newColor4D.SetFromHexString( m_colorValue->GetValue() );
706
707 SetEditVals( HEX_CHANGED, true );
708 drawAll();
709}
710
711
712bool DIALOG_COLOR_PICKER::setHSvaluesFromCursor( const wxPoint& aMouseCursor )
713{
714 wxPoint mousePos = aMouseCursor;
715 wxSize bmsize = m_bitmapHSV->GetSize();
716 int half_size = std::min( bmsize.x, bmsize.y )/2;
717
718 // Make the cursor position relative to the m_bitmapHSV wxBitmap center
719 mousePos.x -= half_size;
720 mousePos.y -= half_size;
721 mousePos.y = -mousePos.y; // Use the bottom to top vertical axis
722
723 // The HS cursor position is restricted to a circle of radius half_size
724 double dist_from_centre = hypot( (double)mousePos.x, (double)mousePos.y );
725
726 if( dist_from_centre > half_size )
727 {
728 // Saturation cannot be calculated:
729 return false;
730 }
731
732 m_cursorBitmapHSV = mousePos;
733
734 // Set saturation and hue from new cursor position:
735 half_size -= m_cursorsSize / 2; // the actual half_size of the palette area
736 m_sat = dist_from_centre / half_size;
737
738 if( m_sat > 1.0 )
739 m_sat = 1.0;
740
741 m_hue = atan2( mousePos.y, mousePos.x ) / M_PI * 180.0;
742
743 if( m_hue < 0 )
744 m_hue += 360.0;
745
747 SetEditVals( ALL_CHANGED, true );
748
749 return true;
750}
751
752
753void DIALOG_COLOR_PICKER::OnChangeAlpha( wxScrollEvent& event )
754{
755 double alpha = (double)event.GetPosition() / ALPHA_MAX;
756 m_newColor4D.a = alpha;
757 m_NewColorRect->Freeze(); // Avoid flicker
759 m_NewColorRect->Thaw();
760 m_NewColorRect->Refresh();
761 SetEditVals( ALPHA_CHANGED, false );
762}
763
764
765void DIALOG_COLOR_PICKER::OnChangeEditRed( wxSpinEvent& event )
766{
767 double val = (double)event.GetPosition() / 255.0;
768 m_newColor4D.r = val;
769 SetEditVals( RED_CHANGED, true );
770
771 drawAll();
772}
773
774
776{
777 double val = (double)event.GetPosition() / 255.0;
778 m_newColor4D.g = val;
779 SetEditVals( GREEN_CHANGED, true );
780
781 drawAll();
782}
783
784
786{
787 double val = (double)event.GetPosition() / 255.0;
788 m_newColor4D.b = val;
789 SetEditVals( BLUE_CHANGED, true );
790
791 drawAll();
792}
793
794
795void DIALOG_COLOR_PICKER::OnChangeEditHue( wxSpinEvent& event )
796{
797 m_hue = (double)event.GetPosition();
798
800
801 SetEditVals( HUE_CHANGED, true );
802
803 drawAll();
804}
805
806
807void DIALOG_COLOR_PICKER::OnChangeEditSat( wxSpinEvent& event )
808{
809 m_sat = (double)event.GetPosition() / 255.0;
810
812
813 SetEditVals( SAT_CHANGED, true );
814
815 drawAll();
816}
817
818
819void DIALOG_COLOR_PICKER::OnChangeBrightness( wxScrollEvent& event )
820{
821 m_val = (double)event.GetPosition() / 255.0;
822
824
825 SetEditVals( VAL_CHANGED, true );
826
827 drawAll();
828}
829
830
831void DIALOG_COLOR_PICKER::OnResetButton( wxCommandEvent& aEvent )
832{
837
839 SetEditVals( ALL_CHANGED, false );
840
841 drawAll();
842}
int color
Definition: DXF_plotter.cpp:57
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
APP_SETTINGS_BASE is a settings class that should be derived for each standalone KiCad application.
Definition: app_settings.h:101
COLOR_PICKER m_ColorPicker
Definition: app_settings.h:176
static wxBitmap MakeBitmap(const KIGFX::COLOR4D &aColor, const KIGFX::COLOR4D &aBackground, const wxSize &aSize, const wxSize &aCheckerboardSize, const KIGFX::COLOR4D &aCheckerboardBackground)
Class DIALOG_COLOR_PICKER_BASE.
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.
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:93
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
double r
Red component.
Definition: color4d.h:384
double g
Green component.
Definition: color4d.h:385
void ToHSV(double &aOutHue, double &aOutSaturation, double &aOutValue, bool aAlwaysDefineHue=false) const
Convert current color (stored in RGB) to HSV format.
Definition: color4d.cpp:387
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:441
double a
Alpha component.
Definition: color4d.h:387
double b
Blue component.
Definition: color4d.h:386
const StructColors * colorRefs()
Global list of legacy color names, still used all over the place for constructing COLOR4D's.
Definition: color4d.cpp:39
@ WHITE
Definition: color4d.h:48
@ 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)
CHANGED_COLOR
@ 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:401
A class to handle a custom color (predefined color) for the color picker dialog.
KIGFX::COLOR4D m_Color