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__ ) && !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 )
548
549 if( aChanged != RED_CHANGED )
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 )
569 else
570 m_colorValue->ChangeValue( m_newColor4D.ToHexString() );
571}
572
573
575{
576 m_cursorsSize = ToPhys( FromDIP( 8 ) ); // Size of square cursors drawn on color bitmaps
577}
578
579
581{
583 m_NewColorRect->Freeze(); // Avoid flicker
584 m_HsvBitmap->Freeze();
585 m_RgbBitmap->Freeze();
589 m_NewColorRect->Thaw();
590 m_HsvBitmap->Thaw();
591 m_RgbBitmap->Thaw();
592 m_NewColorRect->Refresh();
593 m_HsvBitmap->Refresh();
594 m_RgbBitmap->Refresh();
595}
596
597
598void DIALOG_COLOR_PICKER::colorDClick( wxMouseEvent& event )
599{
600 wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
601}
602
603
604void DIALOG_COLOR_PICKER::buttColorClick( wxMouseEvent& event )
605{
606 int id = event.GetId();
608 m_newColor4D.r = color.r;
609 m_newColor4D.g = color.g;
610 m_newColor4D.b = color.b;
611 m_newColor4D.a = color.a;
612
614 SetEditVals( ALL_CHANGED, false );
615
616 drawAll();
617
618 event.Skip();
619}
620
621
622void DIALOG_COLOR_PICKER::onRGBMouseClick( wxMouseEvent& event )
623{
624 m_allowMouseEvents = true;
625
626 // The cursor position is relative to the m_bitmapHSV wxBitmap center
627 wxPoint mousePos = ToPhys( event.GetPosition() );
628 wxSize bmsize = m_bitmapRGB->GetSize();
629 int half_size = std::min( bmsize.x, bmsize.y ) / 2;
630
631 mousePos.x -= half_size;
632 mousePos.y -= half_size;
633 mousePos.y = -mousePos.y; // Use the bottom to top vertical axis
634
635 wxPoint dist = m_cursorBitmapRed - mousePos;
636
637 if( std::abs( dist.x ) <= m_cursorsSize/2 && std::abs( dist.y ) <= m_cursorsSize/2 )
638 {
640 return;
641 }
642
643 dist = m_cursorBitmapGreen - mousePos;
644
645 if( std::abs( dist.x ) <= m_cursorsSize / 2 && std::abs( dist.y ) <= m_cursorsSize / 2 )
646 {
648 return;
649 }
650
651 dist = m_cursorBitmapBlue - mousePos;
652
653 if( std::abs( dist.x ) <= m_cursorsSize / 2 && std::abs( dist.y ) <= m_cursorsSize / 2 )
654 {
656 return;
657 }
658
659 m_selectedCursor = nullptr;
660}
661
662
663void DIALOG_COLOR_PICKER::onRGBMouseDrag( wxMouseEvent& event )
664{
665 if( !event.Dragging() || !m_allowMouseEvents )
666 {
667 m_selectedCursor = nullptr;
668 return;
669 }
670
674 {
675 return;
676 }
677
678 // Adjust the HSV cursor position to follow the mouse cursor
679 // The cursor position is relative to the m_bitmapHSV wxBitmap center
680 wxPoint mousePos = ToPhys( event.GetPosition() );
681 wxSize bmsize = m_bitmapRGB->GetSize();
682 int half_size = std::min( bmsize.x, bmsize.y ) / 2;
683
684 mousePos.x -= half_size;
685 mousePos.y -= half_size;
686 mousePos.y = -mousePos.y; // Use the bottom to top vertical axis
687
688 half_size -= m_cursorsSize / 2; // the actual half_size of the palette area
689
690 // Change colors according to the selected cursor:
692 {
693 if( mousePos.y >= 0 && mousePos.y <= half_size )
694 m_newColor4D.r = (double)mousePos.y / half_size;
695 else
696 return;
697 }
698
700 {
701 mousePos.x = -mousePos.x;
702
703 if( mousePos.x >= 0 && mousePos.x <= half_size )
704 m_newColor4D.g = (double)mousePos.x / half_size;
705 else
706 return;
707 }
708
710 {
711 if( mousePos.x >= 0 && mousePos.x <= half_size )
712 m_newColor4D.b = (double)mousePos.x / half_size;
713 else
714 return;
715 }
716
718 SetEditVals( ALL_CHANGED, true );
719
720 drawAll();
721}
722
723
724void DIALOG_COLOR_PICKER::onHSVMouseClick( wxMouseEvent& event )
725{
726 m_allowMouseEvents = true;
727
728 if( setHSvaluesFromCursor( event.GetPosition() ) )
729 drawAll();
730}
731
732
733void DIALOG_COLOR_PICKER::onHSVMouseDrag( wxMouseEvent& event )
734{
735 if( !event.Dragging() || !m_allowMouseEvents )
736 return;
737
738 if( setHSvaluesFromCursor( event.GetPosition() ) )
739 drawAll();
740}
741
742
743void DIALOG_COLOR_PICKER::onSize( wxSizeEvent& event )
744{
745 drawAll();
746
747 event.Skip();
748}
749
750
751void DIALOG_COLOR_PICKER::OnColorValueText( wxCommandEvent& event )
752{
753 if( m_newColor4D.SetFromHexString( m_colorValue->GetValue() ) )
754 {
756
757 SetEditVals( HEX_CHANGED, false );
758 drawAll();
759 }
760}
761
762
763bool DIALOG_COLOR_PICKER::setHSvaluesFromCursor( const wxPoint& aMouseCursor )
764{
765 wxPoint mousePos = ToPhys( aMouseCursor );
766 wxSize bmsize = m_bitmapHSV->GetSize();
767 int half_size = std::min( bmsize.x, bmsize.y ) / 2;
768
769 // Make the cursor position relative to the m_bitmapHSV wxBitmap center
770 mousePos.x -= half_size;
771 mousePos.y -= half_size;
772 mousePos.y = -mousePos.y; // Use the bottom to top vertical axis
773
774 // The HS cursor position is restricted to a circle of radius half_size
775 double dist_from_centre = hypot( (double)mousePos.x, (double)mousePos.y );
776
777 if( dist_from_centre > half_size )
778 {
779 // Saturation cannot be calculated:
780 return false;
781 }
782
783 m_cursorBitmapHSV = mousePos;
784
785 // Set saturation and hue from new cursor position:
786 half_size -= m_cursorsSize / 2; // the actual half_size of the palette area
787 m_sat = dist_from_centre / half_size;
788
789 if( m_sat > 1.0 )
790 m_sat = 1.0;
791
792 m_hue = atan2( mousePos.y, mousePos.x ) / M_PI * 180.0;
793
794 if( m_hue < 0 )
795 m_hue += 360.0;
796
798 SetEditVals( ALL_CHANGED, true );
799
800 return true;
801}
802
803
804void DIALOG_COLOR_PICKER::OnChangeAlpha( wxScrollEvent& event )
805{
806 double alpha = (double)event.GetPosition() / ALPHA_MAX;
807 m_newColor4D.a = alpha;
808 m_NewColorRect->Freeze(); // Avoid flicker
810 m_NewColorRect->Thaw();
811 m_NewColorRect->Refresh();
812 SetEditVals( ALPHA_CHANGED, false );
813}
814
815
816void DIALOG_COLOR_PICKER::OnChangeEditRed( wxSpinEvent& event )
817{
818 double val = (double)event.GetPosition() / 255.0;
819 m_newColor4D.r = val;
820 SetEditVals( RED_CHANGED, true );
821
822 drawAll();
823}
824
825
827{
828 double val = (double)event.GetPosition() / 255.0;
829 m_newColor4D.g = val;
830 SetEditVals( GREEN_CHANGED, true );
831
832 drawAll();
833}
834
835
837{
838 double val = (double)event.GetPosition() / 255.0;
839 m_newColor4D.b = val;
840 SetEditVals( BLUE_CHANGED, true );
841
842 drawAll();
843}
844
845
846void DIALOG_COLOR_PICKER::OnChangeEditHue( wxSpinEvent& event )
847{
848 m_hue = (double)event.GetPosition();
849
851
852 SetEditVals( HUE_CHANGED, true );
853
854 drawAll();
855}
856
857
858void DIALOG_COLOR_PICKER::OnChangeEditSat( wxSpinEvent& event )
859{
860 m_sat = (double)event.GetPosition() / 255.0;
861
863
864 SetEditVals( SAT_CHANGED, true );
865
866 drawAll();
867}
868
869
870void DIALOG_COLOR_PICKER::OnChangeBrightness( wxScrollEvent& event )
871{
872 m_val = (double)event.GetPosition() / 255.0;
873
875
876 SetEditVals( VAL_CHANGED, true );
877
878 drawAll();
879}
880
881
882void DIALOG_COLOR_PICKER::OnResetButton( wxCommandEvent& aEvent )
883{
888
890 SetEditVals( ALL_CHANGED, false );
891
892 drawAll();
893}
int color
Definition: DXF_plotter.cpp:63
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:108
COLOR_PICKER m_ColorPicker
Definition: app_settings.h:221
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:400
A class to handle a custom color (predefined color) for the color picker dialog.
KIGFX::COLOR4D m_Color