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( "@{color(DEVICE_BACKGROUND)}" ) ).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( INIT, 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}
340
341
343{
344 wxSize bmsize = ToPhys( m_HsvBitmap->GetSize() );
345 int half_size = std::min( bmsize.x, bmsize.y )/2;
346
347 // We use here a Y axis from bottom to top and origin to center, So we need to map
348 // coordinated to write pixel in a wxImage
349 #define MAPX( xx ) bmsize.x / 2 + ( xx )
350 #define MAPY( yy ) bmsize.y / 2 - ( yy )
351
352 wxImage img( bmsize ); // a temporary buffer to build the color map
353
354 // clear background (set the window bg color)
355 wxColor bg = GetBackgroundColour();
356
357 // Don't do standard-color lookups on OSX each time through the loop
358 wxColourBase::ChannelType bgR = bg.Red();
359 wxColourBase::ChannelType bgG = bg.Green();
360 wxColourBase::ChannelType bgB = bg.Blue();
361
362 for( int xx = 0; xx < bmsize.x; xx++ ) // blue axis
363 {
364 for( int yy = 0; yy < bmsize.y; yy++ ) // Red axis
365 img.SetRGB( xx, yy, bgR, bgG, bgB );
366 }
367
368 // Reserve room to draw cursors inside the bitmap
369 half_size -= m_cursorsSize/2;
370
371 double hue, sat;
372 COLOR4D color;
373 int sq_radius = half_size*half_size;
374
375 // Build the palette
376 for( int xx = -half_size; xx < half_size; xx++ )
377 {
378 for( int yy = -half_size; yy < half_size; yy++ )
379 {
380 sat = double(xx*xx + yy*yy) / sq_radius;
381
382 // sat is <= 1.0
383 // any value > 1.0 is not a valid HSB color:
384 if( sat > 1.0 )
385 continue;
386
387 // sat is the distance from center
388 sat = sqrt( sat );
389 hue = atan2( (double)yy, (double)xx ) * 180 / M_PI;
390
391 if( hue < 0.0 )
392 hue += 360.0;
393
394 color.FromHSV( hue, sat, 1.0 );
395
396 img.SetRGB( MAPX( xx ), MAPY( yy ), color.r * 255, color.g * 255, color.b * 255 );
397 }
398 }
399
400 delete m_bitmapHSV;
401 m_bitmapHSV = new wxBitmap( img, 24 );
402
403 m_bitmapHSV->SetScaleFactor( GetDPIScaleFactor() );
404}
405
406
408{
409 if( !m_bitmapRGB || m_bitmapRGB->GetSize() != ToPhys( m_RgbBitmap->GetSize() ) )
411
412 wxSize bmsize = m_bitmapRGB->GetSize();
413 int half_size = std::min( bmsize.x, bmsize.y ) / 2;
414
415 wxBitmap newBm( *m_bitmapRGB );
416 newBm.SetScaleFactor( 1.0 );
417
418 {
419 wxMemoryDC bitmapDC( newBm );
420
421 // Use Y axis from bottom to top and origin to center
422 bitmapDC.SetAxisOrientation( true, true );
423
424 #if defined( __WXMSW__ ) && !wxCHECK_VERSION( 3, 3, 0 )
425 // For some reason, SetDeviceOrigin has changed in wxWidgets 3.1.6 or 3.1.7
426 // It was fixed in wx >= 3.3
427 bitmapDC.SetDeviceOrigin( half_size, -half_size );
428 #else
429 bitmapDC.SetDeviceOrigin( half_size, half_size );
430 #endif
431
432 // Reserve room to draw cursors inside the bitmap
433 half_size -= m_cursorsSize / 2;
434
435 // Draw the 3 RGB cursors, using white color to make them always visible:
436 wxPen pen( wxColor( 255, 255, 255 ), 2 ); // use 2 pixels for pen size
437 wxBrush brush( wxColor( 0, 0, 0 ), wxBRUSHSTYLE_TRANSPARENT );
438 bitmapDC.SetPen( pen );
439 bitmapDC.SetBrush( brush );
440 int half_csize = m_cursorsSize / 2;
441
442 double slope = SLOPE_AXIS / half_size;
443
444 // Red axis cursor (Z 3Daxis):
445 m_cursorBitmapRed.x = 0;
446 m_cursorBitmapRed.y = m_newColor4D.r * half_size;
447 bitmapDC.DrawRectangle( m_cursorBitmapRed.x - half_csize,
448 m_cursorBitmapRed.y - half_csize,
450
451 // Blue axis cursor (X 3Daxis):
452 m_cursorBitmapBlue.x = m_newColor4D.b * half_size;
454 bitmapDC.DrawRectangle( m_cursorBitmapBlue.x - half_csize,
455 m_cursorBitmapBlue.y - half_csize,
457
458 // Green axis cursor (Y 3Daxis):
459 m_cursorBitmapGreen.x = m_newColor4D.g * half_size;
462
463 bitmapDC.DrawRectangle( m_cursorBitmapGreen.x - half_csize,
464 m_cursorBitmapGreen.y - half_csize,
466
467 // Draw the 3 RGB axis:
468 half_size += half_size/5;
469 bitmapDC.DrawLine( 0, 0, 0, half_size ); // Red axis (Z 3D axis)
470 bitmapDC.DrawLine( 0, 0, half_size, - half_size*slope ); // Blue axis (X 3D axis)
471 bitmapDC.DrawLine( 0, 0, -half_size, - half_size*slope ); // green axis (Y 3D axis)
472 }
473
474 newBm.SetScaleFactor( GetDPIScaleFactor() );
475 m_RgbBitmap->SetBitmap( newBm );
476}
477
478
480{
481 if( !m_bitmapHSV || m_bitmapHSV->GetSize() != ToPhys( m_HsvBitmap->GetSize() ) )
483
484 wxSize bmsize = m_bitmapHSV->GetSize();
485 int half_size = std::min( bmsize.x, bmsize.y ) / 2;
486
487 wxBitmap newBm( *m_bitmapHSV );
488 newBm.SetScaleFactor( 1.0 );
489
490 {
491 wxMemoryDC bitmapDC( newBm );
492
493 // Use Y axis from bottom to top and origin to center
494 bitmapDC.SetAxisOrientation( true, true );
495 #if defined( __WXMSW__ ) && !wxCHECK_VERSION(3,3,0)
496 // For some reason, SetDeviceOrigin has changed in wxWidgets 3.1.6 or 3.1.7
497 // It was fixed in wx >= 3.3
498 bitmapDC.SetDeviceOrigin( half_size, -half_size );
499 #else
500 bitmapDC.SetDeviceOrigin( half_size, half_size );
501 #endif
502
503 // Reserve room to draw cursors inside the bitmap
504 half_size -= m_cursorsSize / 2;
505
506 // Draw the HSB cursor:
507 m_cursorBitmapHSV.x = cos( m_hue * M_PI / 180.0 ) * half_size * m_sat;
508 m_cursorBitmapHSV.y = sin( m_hue * M_PI / 180.0 ) * half_size * m_sat;
509
510 wxPen pen( wxColor( 0, 0, 0 ), 2 ); // Use 2 pixels as pensize
511 wxBrush brush( wxColor( 0, 0, 0 ), wxBRUSHSTYLE_TRANSPARENT );
512 bitmapDC.SetPen( pen );
513 bitmapDC.SetBrush( brush );
514
515 bitmapDC.DrawRectangle( m_cursorBitmapHSV.x - ( m_cursorsSize / 2 ),
518 }
519
520 newBm.SetScaleFactor( GetDPIScaleFactor() );
521 m_HsvBitmap->SetBitmap( newBm );
522}
523
524
525void DIALOG_COLOR_PICKER::SetEditVals( CHANGED_COLOR aChanged, bool aCheckTransparency )
526{
527 if( aCheckTransparency )
528 {
529 // If they've changed the color, they probably don't want it to remain 100% transparent,
530 // and it looks like a bug when changing the color has no effect.
531 if( m_newColor4D.a == 0.0 )
532 m_newColor4D.a = 1.0;
533 }
534
536
537 if( aChanged == RED_CHANGED || aChanged == GREEN_CHANGED || aChanged == BLUE_CHANGED )
538 m_newColor4D.ToHSV( m_hue, m_sat, m_val, true );
539
540 if( aChanged != RED_CHANGED )
541 m_spinCtrlRed->SetValue( normalizeToInt( m_newColor4D.r ) );
542
543 if( aChanged != GREEN_CHANGED )
545
546 if( aChanged != BLUE_CHANGED )
548
549 if( aChanged != HUE_CHANGED )
550 m_spinCtrlHue->SetValue( (int)m_hue );
551
552 if( aChanged != SAT_CHANGED )
553 m_spinCtrlSaturation->SetValue( m_sat * 255 );
554
555 if( aChanged != VAL_CHANGED )
557
558 if( aChanged == INIT )
559 {
560 if( m_newColor4D.m_text )
561 m_colorValue->ChangeValue( *m_newColor4D.m_text );
562 else
563 m_colorValue->ChangeValue( m_newColor4D.ToHexString() );
564 }
565 else if( aChanged != HEX_CHANGED )
566 {
567 m_newColor4D.m_text = nullptr;
568 m_colorValue->ChangeValue( m_newColor4D.ToHexString() );
569 }
570}
571
572
574{
575 m_cursorsSize = ToPhys( FromDIP( 8 ) ); // Size of square cursors drawn on color bitmaps
576}
577
578
580{
582 m_NewColorRect->Freeze(); // Avoid flicker
583 m_HsvBitmap->Freeze();
584 m_RgbBitmap->Freeze();
588 m_NewColorRect->Thaw();
589 m_HsvBitmap->Thaw();
590 m_RgbBitmap->Thaw();
591 m_NewColorRect->Refresh();
592 m_HsvBitmap->Refresh();
593 m_RgbBitmap->Refresh();
594}
595
596
597void DIALOG_COLOR_PICKER::colorDClick( wxMouseEvent& event )
598{
599 wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
600}
601
602
603void DIALOG_COLOR_PICKER::buttColorClick( wxMouseEvent& event )
604{
605 int id = event.GetId();
606 COLOR4D color( m_Color4DList[id - ID_COLOR_BLACK] );
607 m_newColor4D.r = color.r;
608 m_newColor4D.g = color.g;
609 m_newColor4D.b = color.b;
610 m_newColor4D.a = color.a;
611
612 m_newColor4D.ToHSV( m_hue, m_sat, m_val, true );
613 SetEditVals( ALL_CHANGED, false );
614
615 drawAll();
616
617 event.Skip();
618}
619
620
621void DIALOG_COLOR_PICKER::onRGBMouseClick( wxMouseEvent& event )
622{
623 m_allowMouseEvents = true;
624
625 // The cursor position is relative to the m_bitmapHSV wxBitmap center
626 wxPoint mousePos = ToPhys( event.GetPosition() );
627 wxSize bmsize = m_bitmapRGB->GetSize();
628 int half_size = std::min( bmsize.x, bmsize.y ) / 2;
629
630 mousePos.x -= half_size;
631 mousePos.y -= half_size;
632 mousePos.y = -mousePos.y; // Use the bottom to top vertical axis
633
634 wxPoint dist = m_cursorBitmapRed - mousePos;
635
636 if( std::abs( dist.x ) <= m_cursorsSize/2 && std::abs( dist.y ) <= m_cursorsSize/2 )
637 {
639 return;
640 }
641
642 dist = m_cursorBitmapGreen - mousePos;
643
644 if( std::abs( dist.x ) <= m_cursorsSize / 2 && std::abs( dist.y ) <= m_cursorsSize / 2 )
645 {
647 return;
648 }
649
650 dist = m_cursorBitmapBlue - mousePos;
651
652 if( std::abs( dist.x ) <= m_cursorsSize / 2 && std::abs( dist.y ) <= m_cursorsSize / 2 )
653 {
655 return;
656 }
657
658 m_selectedCursor = nullptr;
659}
660
661
662void DIALOG_COLOR_PICKER::onRGBMouseDrag( wxMouseEvent& event )
663{
664 if( !event.Dragging() || !m_allowMouseEvents )
665 {
666 m_selectedCursor = nullptr;
667 return;
668 }
669
673 {
674 return;
675 }
676
677 // Adjust the HSV cursor position to follow the mouse cursor
678 // The cursor position is relative to the m_bitmapHSV wxBitmap center
679 wxPoint mousePos = ToPhys( event.GetPosition() );
680 wxSize bmsize = m_bitmapRGB->GetSize();
681 int half_size = std::min( bmsize.x, bmsize.y ) / 2;
682
683 mousePos.x -= half_size;
684 mousePos.y -= half_size;
685 mousePos.y = -mousePos.y; // Use the bottom to top vertical axis
686
687 half_size -= m_cursorsSize / 2; // the actual half_size of the palette area
688
689 // Change colors according to the selected cursor:
691 {
692 if( mousePos.y >= 0 && mousePos.y <= half_size )
693 m_newColor4D.r = (double)mousePos.y / half_size;
694 else
695 return;
696 }
697
699 {
700 mousePos.x = -mousePos.x;
701
702 if( mousePos.x >= 0 && mousePos.x <= half_size )
703 m_newColor4D.g = (double)mousePos.x / half_size;
704 else
705 return;
706 }
707
709 {
710 if( mousePos.x >= 0 && mousePos.x <= half_size )
711 m_newColor4D.b = (double)mousePos.x / half_size;
712 else
713 return;
714 }
715
716 m_newColor4D.ToHSV( m_hue, m_sat, m_val, true );
717 SetEditVals( ALL_CHANGED, true );
718
719 drawAll();
720}
721
722
723void DIALOG_COLOR_PICKER::onHSVMouseClick( wxMouseEvent& event )
724{
725 m_allowMouseEvents = true;
726
727 if( setHSvaluesFromCursor( event.GetPosition() ) )
728 drawAll();
729}
730
731
732void DIALOG_COLOR_PICKER::onHSVMouseDrag( wxMouseEvent& event )
733{
734 if( !event.Dragging() || !m_allowMouseEvents )
735 return;
736
737 if( setHSvaluesFromCursor( event.GetPosition() ) )
738 drawAll();
739}
740
741
742void DIALOG_COLOR_PICKER::onSize( wxSizeEvent& event )
743{
744 drawAll();
745
746 event.Skip();
747}
748
749
750void DIALOG_COLOR_PICKER::OnColorValueText( wxCommandEvent& event )
751{
752 if( m_newColor4D.SetFromHexString( m_colorValue->GetValue() ) )
753 m_newColor4D.ToHSV( m_hue, m_sat, m_val, true );
754
755 SetEditVals( HEX_CHANGED, false );
756 drawAll();
757}
758
759
760bool DIALOG_COLOR_PICKER::setHSvaluesFromCursor( const wxPoint& aMouseCursor )
761{
762 wxPoint mousePos = ToPhys( aMouseCursor );
763 wxSize bmsize = m_bitmapHSV->GetSize();
764 int half_size = std::min( bmsize.x, bmsize.y ) / 2;
765
766 // Make the cursor position relative to the m_bitmapHSV wxBitmap center
767 mousePos.x -= half_size;
768 mousePos.y -= half_size;
769 mousePos.y = -mousePos.y; // Use the bottom to top vertical axis
770
771 // The HS cursor position is restricted to a circle of radius half_size
772 double dist_from_centre = hypot( (double)mousePos.x, (double)mousePos.y );
773
774 if( dist_from_centre > half_size )
775 {
776 // Saturation cannot be calculated:
777 return false;
778 }
779
780 m_cursorBitmapHSV = mousePos;
781
782 // Set saturation and hue from new cursor position:
783 half_size -= m_cursorsSize / 2; // the actual half_size of the palette area
784 m_sat = dist_from_centre / half_size;
785
786 if( m_sat > 1.0 )
787 m_sat = 1.0;
788
789 m_hue = atan2( mousePos.y, mousePos.x ) / M_PI * 180.0;
790
791 if( m_hue < 0 )
792 m_hue += 360.0;
793
794 m_newColor4D.FromHSV( m_hue, m_sat, m_val );
795 SetEditVals( ALL_CHANGED, true );
796
797 return true;
798}
799
800
801void DIALOG_COLOR_PICKER::OnChangeAlpha( wxScrollEvent& event )
802{
803 double alpha = (double)event.GetPosition() / ALPHA_MAX;
804 m_newColor4D.a = alpha;
805 m_NewColorRect->Freeze(); // Avoid flicker
807 m_NewColorRect->Thaw();
808 m_NewColorRect->Refresh();
809 SetEditVals( ALPHA_CHANGED, false );
810}
811
812
813void DIALOG_COLOR_PICKER::OnChangeEditRed( wxSpinEvent& event )
814{
815 double val = (double)event.GetPosition() / 255.0;
816 m_newColor4D.r = val;
817 SetEditVals( RED_CHANGED, true );
818
819 drawAll();
820}
821
822
824{
825 double val = (double)event.GetPosition() / 255.0;
826 m_newColor4D.g = val;
827 SetEditVals( GREEN_CHANGED, true );
828
829 drawAll();
830}
831
832
834{
835 double val = (double)event.GetPosition() / 255.0;
836 m_newColor4D.b = val;
837 SetEditVals( BLUE_CHANGED, true );
838
839 drawAll();
840}
841
842
843void DIALOG_COLOR_PICKER::OnChangeEditHue( wxSpinEvent& event )
844{
845 m_hue = (double)event.GetPosition();
846
847 m_newColor4D.FromHSV( m_hue, m_sat, m_val );
848
849 SetEditVals( HUE_CHANGED, true );
850
851 drawAll();
852}
853
854
855void DIALOG_COLOR_PICKER::OnChangeEditSat( wxSpinEvent& event )
856{
857 m_sat = (double)event.GetPosition() / 255.0;
858
859 m_newColor4D.FromHSV( m_hue, m_sat, m_val );
860
861 SetEditVals( SAT_CHANGED, true );
862
863 drawAll();
864}
865
866
867void DIALOG_COLOR_PICKER::OnChangeBrightness( wxScrollEvent& event )
868{
869 m_val = (double)event.GetPosition() / 255.0;
870
871 m_newColor4D.FromHSV( m_hue, m_sat, m_val );
872
873 SetEditVals( VAL_CHANGED, true );
874
875 drawAll();
876}
877
878
879void DIALOG_COLOR_PICKER::OnResetButton( wxCommandEvent& aEvent )
880{
885
886 m_newColor4D.ToHSV( m_hue, m_sat, m_val, true );
887 SetEditVals( ALL_CHANGED, false );
888
889 drawAll();
890}
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:441
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