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;
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( ALL_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
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;
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__ )
427 // For some reason, SetDeviceOrigin has changed in wxWidgets 3.1.6 or 3.1.7
428 bitmapDC.SetDeviceOrigin( half_size, -half_size );
429#else
430 bitmapDC.SetDeviceOrigin( half_size, half_size );
431#endif
432
433 // Reserve room to draw cursors inside the bitmap
434 half_size -= m_cursorsSize / 2;
435
436 // Draw the 3 RGB cursors, using white color to make them always visible:
437 wxPen pen( wxColor( 255, 255, 255 ), 2 ); // use 2 pixels for pen size
438 wxBrush brush( wxColor( 0, 0, 0 ), wxBRUSHSTYLE_TRANSPARENT );
439 bitmapDC.SetPen( pen );
440 bitmapDC.SetBrush( brush );
441 int half_csize = m_cursorsSize / 2;
442
443 double slope = SLOPE_AXIS / half_size;
444
445 // Red axis cursor (Z 3Daxis):
446 m_cursorBitmapRed.x = 0;
447 m_cursorBitmapRed.y = m_newColor4D.r * half_size;
448 bitmapDC.DrawRectangle( m_cursorBitmapRed.x - half_csize,
449 m_cursorBitmapRed.y - half_csize,
451
452 // Blue axis cursor (X 3Daxis):
453 m_cursorBitmapBlue.x = m_newColor4D.b * half_size;
455 bitmapDC.DrawRectangle( m_cursorBitmapBlue.x - half_csize,
456 m_cursorBitmapBlue.y - half_csize,
458
459 // Green axis cursor (Y 3Daxis):
460 m_cursorBitmapGreen.x = m_newColor4D.g * half_size;
463
464 bitmapDC.DrawRectangle( m_cursorBitmapGreen.x - half_csize,
465 m_cursorBitmapGreen.y - half_csize,
467
468 // Draw the 3 RGB axis:
469 half_size += half_size/5;
470 bitmapDC.DrawLine( 0, 0, 0, half_size ); // Red axis (Z 3D axis)
471 bitmapDC.DrawLine( 0, 0, half_size, - half_size*slope ); // Blue axis (X 3D axis)
472 bitmapDC.DrawLine( 0, 0, -half_size, - half_size*slope ); // green axis (Y 3D axis)
473
474 newBm.SetScaleFactor( GetDPIScaleFactor() );
475 m_RgbBitmap->SetBitmap( newBm );
476
477 /* Deselect the Tool Bitmap from DC,
478 * in order to delete the MemoryDC safely without deleting the bitmap */
479 bitmapDC.SelectObject( wxNullBitmap );
480}
481
482
484{
485 if( !m_bitmapHSV || m_bitmapHSV->GetSize() != ToPhys( m_HsvBitmap->GetSize() ) )
487
488 wxMemoryDC bitmapDC;
489 wxSize bmsize = m_bitmapHSV->GetSize();
490 int half_size = std::min( bmsize.x, bmsize.y ) / 2;
491
492 wxBitmap newBm( *m_bitmapHSV );
493 newBm.SetScaleFactor( 1.0 );
494
495 bitmapDC.SelectObject( newBm );
496
497 // Use Y axis from bottom to top and origin to center
498 bitmapDC.SetAxisOrientation( true, true );
499#if defined( __WXMSW__)
500 // For some reason, SetDeviceOrigin has changed in wxWidgets 3.1.6 or 3.1.7
501 bitmapDC.SetDeviceOrigin( half_size, -half_size );
502#else
503 bitmapDC.SetDeviceOrigin( half_size, half_size );
504#endif
505
506 // Reserve room to draw cursors inside the bitmap
507 half_size -= m_cursorsSize / 2;
508
509 // Draw the HSB cursor:
510 m_cursorBitmapHSV.x = cos( m_hue * M_PI / 180.0 ) * half_size * m_sat;
511 m_cursorBitmapHSV.y = sin( m_hue * M_PI / 180.0 ) * half_size * m_sat;
512
513 wxPen pen( wxColor( 0, 0, 0 ), 2 ); // Use 2 pixels as pensize
514 wxBrush brush( wxColor( 0, 0, 0 ), wxBRUSHSTYLE_TRANSPARENT );
515 bitmapDC.SetPen( pen );
516 bitmapDC.SetBrush( brush );
517
518 bitmapDC.DrawRectangle( m_cursorBitmapHSV.x - ( m_cursorsSize / 2 ),
521
522 newBm.SetScaleFactor( GetDPIScaleFactor() );
523 m_HsvBitmap->SetBitmap( newBm );
524
525 /* Deselect the Tool Bitmap from DC,
526 * in order to delete the MemoryDC safely without deleting the bitmap
527 */
528 bitmapDC.SelectObject( wxNullBitmap );
529}
530
531
532void DIALOG_COLOR_PICKER::SetEditVals( CHANGED_COLOR aChanged, bool aCheckTransparency )
533{
534 if( aCheckTransparency )
535 {
536 // If they've changed the color, they probably don't want it to remain 100% transparent,
537 // and it looks like a bug when changing the color has no effect.
538 if( m_newColor4D.a == 0.0 )
539 m_newColor4D.a = 1.0;
540 }
541
543
544 if( aChanged == RED_CHANGED || aChanged == GREEN_CHANGED || aChanged == BLUE_CHANGED )
546
547 if( aChanged != RED_CHANGED )
549
550 if( aChanged != GREEN_CHANGED )
552
553 if( aChanged != BLUE_CHANGED )
555
556 if( aChanged != HUE_CHANGED )
557 m_spinCtrlHue->SetValue( (int)m_hue );
558
559 if( aChanged != SAT_CHANGED )
560 m_spinCtrlSaturation->SetValue( m_sat * 255 );
561
562 if( aChanged != VAL_CHANGED )
564
565 if( aChanged == HEX_CHANGED )
567 else
568 m_colorValue->ChangeValue( m_newColor4D.ToHexString() );
569}
570
571
573{
574 m_cursorsSize = ToPhys( FromDIP( 8 ) ); // Size of square cursors drawn on color bitmaps
575}
576
577
579{
581 m_NewColorRect->Freeze(); // Avoid flicker
582 m_HsvBitmap->Freeze();
583 m_RgbBitmap->Freeze();
587 m_NewColorRect->Thaw();
588 m_HsvBitmap->Thaw();
589 m_RgbBitmap->Thaw();
590 m_NewColorRect->Refresh();
591 m_HsvBitmap->Refresh();
592 m_RgbBitmap->Refresh();
593}
594
595
596void DIALOG_COLOR_PICKER::colorDClick( wxMouseEvent& event )
597{
598 wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
599}
600
601
602void DIALOG_COLOR_PICKER::buttColorClick( wxMouseEvent& event )
603{
604 int id = event.GetId();
606 m_newColor4D.r = color.r;
607 m_newColor4D.g = color.g;
608 m_newColor4D.b = color.b;
609 m_newColor4D.a = color.a;
610
612 SetEditVals( ALL_CHANGED, false );
613
614 drawAll();
615
616 event.Skip();
617}
618
619
620void DIALOG_COLOR_PICKER::onRGBMouseClick( wxMouseEvent& event )
621{
622 m_allowMouseEvents = true;
623
624 // The cursor position is relative to the m_bitmapHSV wxBitmap center
625 wxPoint mousePos = ToPhys( event.GetPosition() );
626 wxSize bmsize = m_bitmapRGB->GetSize();
627 int half_size = std::min( bmsize.x, bmsize.y ) / 2;
628
629 mousePos.x -= half_size;
630 mousePos.y -= half_size;
631 mousePos.y = -mousePos.y; // Use the bottom to top vertical axis
632
633 wxPoint dist = m_cursorBitmapRed - mousePos;
634
635 if( std::abs( dist.x ) <= m_cursorsSize/2 && std::abs( dist.y ) <= m_cursorsSize/2 )
636 {
638 return;
639 }
640
641 dist = m_cursorBitmapGreen - mousePos;
642
643 if( std::abs( dist.x ) <= m_cursorsSize / 2 && std::abs( dist.y ) <= m_cursorsSize / 2 )
644 {
646 return;
647 }
648
649 dist = m_cursorBitmapBlue - mousePos;
650
651 if( std::abs( dist.x ) <= m_cursorsSize / 2 && std::abs( dist.y ) <= m_cursorsSize / 2 )
652 {
654 return;
655 }
656
657 m_selectedCursor = nullptr;
658}
659
660
661void DIALOG_COLOR_PICKER::onRGBMouseDrag( wxMouseEvent& event )
662{
663 if( !event.Dragging() || !m_allowMouseEvents )
664 {
665 m_selectedCursor = nullptr;
666 return;
667 }
668
672 {
673 return;
674 }
675
676 // Adjust the HSV cursor position to follow the mouse cursor
677 // The cursor position is relative to the m_bitmapHSV wxBitmap center
678 wxPoint mousePos = ToPhys( event.GetPosition() );
679 wxSize bmsize = m_bitmapRGB->GetSize();
680 int half_size = std::min( bmsize.x, bmsize.y ) / 2;
681
682 mousePos.x -= half_size;
683 mousePos.y -= half_size;
684 mousePos.y = -mousePos.y; // Use the bottom to top vertical axis
685
686 half_size -= m_cursorsSize / 2; // the actual half_size of the palette area
687
688 // Change colors according to the selected cursor:
690 {
691 if( mousePos.y >= 0 && mousePos.y <= half_size )
692 m_newColor4D.r = (double)mousePos.y / half_size;
693 else
694 return;
695 }
696
698 {
699 mousePos.x = -mousePos.x;
700
701 if( mousePos.x >= 0 && mousePos.x <= half_size )
702 m_newColor4D.g = (double)mousePos.x / half_size;
703 else
704 return;
705 }
706
708 {
709 if( mousePos.x >= 0 && mousePos.x <= half_size )
710 m_newColor4D.b = (double)mousePos.x / half_size;
711 else
712 return;
713 }
714
716 SetEditVals( ALL_CHANGED, true );
717
718 drawAll();
719}
720
721
722void DIALOG_COLOR_PICKER::onHSVMouseClick( wxMouseEvent& event )
723{
724 m_allowMouseEvents = true;
725
726 if( setHSvaluesFromCursor( event.GetPosition() ) )
727 drawAll();
728}
729
730
731void DIALOG_COLOR_PICKER::onHSVMouseDrag( wxMouseEvent& event )
732{
733 if( !event.Dragging() || !m_allowMouseEvents )
734 return;
735
736 if( setHSvaluesFromCursor( event.GetPosition() ) )
737 drawAll();
738}
739
740
741void DIALOG_COLOR_PICKER::onSize( wxSizeEvent& event )
742{
743 drawAll();
744
745 event.Skip();
746}
747
748
749void DIALOG_COLOR_PICKER::OnColorValueText( wxCommandEvent& event )
750{
751 if( m_newColor4D.SetFromHexString( m_colorValue->GetValue() ) )
752 {
754
755 SetEditVals( HEX_CHANGED, false );
756 drawAll();
757 }
758}
759
760
761bool DIALOG_COLOR_PICKER::setHSvaluesFromCursor( const wxPoint& aMouseCursor )
762{
763 wxPoint mousePos = ToPhys( aMouseCursor );
764 wxSize bmsize = m_bitmapHSV->GetSize();
765 int half_size = std::min( bmsize.x, bmsize.y ) / 2;
766
767 // Make the cursor position relative to the m_bitmapHSV wxBitmap center
768 mousePos.x -= half_size;
769 mousePos.y -= half_size;
770 mousePos.y = -mousePos.y; // Use the bottom to top vertical axis
771
772 // The HS cursor position is restricted to a circle of radius half_size
773 double dist_from_centre = hypot( (double)mousePos.x, (double)mousePos.y );
774
775 if( dist_from_centre > half_size )
776 {
777 // Saturation cannot be calculated:
778 return false;
779 }
780
781 m_cursorBitmapHSV = mousePos;
782
783 // Set saturation and hue from new cursor position:
784 half_size -= m_cursorsSize / 2; // the actual half_size of the palette area
785 m_sat = dist_from_centre / half_size;
786
787 if( m_sat > 1.0 )
788 m_sat = 1.0;
789
790 m_hue = atan2( mousePos.y, mousePos.x ) / M_PI * 180.0;
791
792 if( m_hue < 0 )
793 m_hue += 360.0;
794
796 SetEditVals( ALL_CHANGED, true );
797
798 return true;
799}
800
801
802void DIALOG_COLOR_PICKER::OnChangeAlpha( wxScrollEvent& event )
803{
804 double alpha = (double)event.GetPosition() / ALPHA_MAX;
805 m_newColor4D.a = alpha;
806 m_NewColorRect->Freeze(); // Avoid flicker
808 m_NewColorRect->Thaw();
809 m_NewColorRect->Refresh();
810 SetEditVals( ALPHA_CHANGED, false );
811}
812
813
814void DIALOG_COLOR_PICKER::OnChangeEditRed( wxSpinEvent& event )
815{
816 double val = (double)event.GetPosition() / 255.0;
817 m_newColor4D.r = val;
818 SetEditVals( RED_CHANGED, true );
819
820 drawAll();
821}
822
823
825{
826 double val = (double)event.GetPosition() / 255.0;
827 m_newColor4D.g = val;
828 SetEditVals( GREEN_CHANGED, true );
829
830 drawAll();
831}
832
833
835{
836 double val = (double)event.GetPosition() / 255.0;
837 m_newColor4D.b = val;
838 SetEditVals( BLUE_CHANGED, true );
839
840 drawAll();
841}
842
843
844void DIALOG_COLOR_PICKER::OnChangeEditHue( wxSpinEvent& event )
845{
846 m_hue = (double)event.GetPosition();
847
849
850 SetEditVals( HUE_CHANGED, true );
851
852 drawAll();
853}
854
855
856void DIALOG_COLOR_PICKER::OnChangeEditSat( wxSpinEvent& event )
857{
858 m_sat = (double)event.GetPosition() / 255.0;
859
861
862 SetEditVals( SAT_CHANGED, true );
863
864 drawAll();
865}
866
867
868void DIALOG_COLOR_PICKER::OnChangeBrightness( wxScrollEvent& event )
869{
870 m_val = (double)event.GetPosition() / 255.0;
871
873
874 SetEditVals( VAL_CHANGED, true );
875
876 drawAll();
877}
878
879
880void DIALOG_COLOR_PICKER::OnResetButton( wxCommandEvent& aEvent )
881{
886
888 SetEditVals( ALL_CHANGED, false );
889
890 drawAll();
891}
int color
Definition: DXF_plotter.cpp:60
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:92
COLOR_PICKER m_ColorPicker
Definition: app_settings.h:184
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.
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:104
double r
Red component.
Definition: color4d.h:392
double g
Green component.
Definition: color4d.h:393
void ToHSV(double &aOutHue, double &aOutSaturation, double &aOutValue, bool aAlwaysDefineHue=false) const
Convert current color (stored in RGB) to HSV format.
Definition: color4d.cpp:368
bool SetFromHexString(const wxString &aColorString)
Definition: color4d.cpp:177
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:422
wxString ToHexString() const
Definition: color4d.cpp:210
double a
Alpha component.
Definition: color4d.h:395
double b
Blue component.
Definition: color4d.h:394
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)
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:390
A class to handle a custom color (predefined color) for the color picker dialog.
KIGFX::COLOR4D m_Color