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 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 "math.h"
22 #include "dialog_color_picker.h"
23 
24 #define ALPHA_MAX 100 // the max value returned by the alpha (opacity) slider
25 
26 DIALOG_COLOR_PICKER::DIALOG_COLOR_PICKER( wxWindow* aParent, KIGFX::COLOR4D& aCurrentColor,
27  bool aAllowOpacityControl, CUSTOM_COLORS_LIST* aUserColors )
28  : DIALOG_COLOR_PICKER_BASE( aParent )
29 {
30  m_allowMouseEvents = false;
31  m_allowOpacityCtrl = aAllowOpacityControl;
32  m_previousColor4D = aCurrentColor;
33  m_newColor4D = aCurrentColor;
34  m_cursorsSize = 8; // Size of square cursors drawn on color bitmaps
35  m_newColor4D.ToHSV( m_hue, m_sat, m_val, true );
36  m_bitmapRGB = nullptr;
37  m_bitmapHSV = nullptr;
38  m_selectedCursor = nullptr;
39 
40  if( !m_allowOpacityCtrl )
41  {
42  m_SizerTransparency->Show( false );
43  m_previousColor4D.a = 1.0;
44  m_newColor4D.a = 1.0;
45  }
46 
47  if( m_ActivePage >= 0 )
48  m_notebook->SetSelection( (unsigned) m_ActivePage );
49 
50  // Build the defined colors panel:
51  initDefinedColors( aUserColors );
52 
53  m_sdbSizerOK->SetDefault();
54 }
55 
56 int DIALOG_COLOR_PICKER::m_ActivePage = 0; // the active notebook page, stored during a session
57 
58 
60 {
61  delete m_bitmapRGB;
62  delete m_bitmapHSV;
63 
64  m_ActivePage = m_notebook->GetSelection();
65 
66  for( auto button : m_buttonsColor )
67  button->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED,
68  wxCommandEventHandler( DIALOG_COLOR_PICKER::buttColorClick ), NULL, this );
69 }
70 
71 
72 void DIALOG_COLOR_PICKER::setIconColor( wxStaticBitmap* aStaticBitmap, KIGFX::COLOR4D& aColor4D )
73 {
74  // Draw the icon that shows the aColor4D,
75  // with colors according to the color 4D rgb and alpha
76  // for alpha = 1 (no tranparency, the icon is a full rgb color rect
77  // for alpha = 0 (100% tranparency, the icon is a grid of rgb color
78  // and background color small sub rect
79  wxMemoryDC bitmapDC;
80  wxSize size = aStaticBitmap->GetSize();
81  wxBitmap newBm( size );
82  bitmapDC.SelectObject( newBm );
83  wxPen pen( aColor4D.ToColour() );
84  wxBrush brush( aColor4D.ToColour() );
85 
86  // clear background (set bg color to aColor4D )
87  bitmapDC.SetBackground( brush );
88  bitmapDC.Clear();
89 
90 
91  // Draw the alpha subrect
92  int stepx = size.x/8;
93  int stepy = size.y/8;
94 
95  // build the alpha color for icon:
96  // the alpha color is the initial color modified to be
97  // the initial color for transparency = 0 ( alpha = 1 )
98  // and white color for transparency = 1( alpha = 0 )
99  KIGFX::COLOR4D bgcolor( GetBackgroundColour() );
100  KIGFX::COLOR4D alphacolor = aColor4D;
101  alphacolor.r = ( alphacolor.r * aColor4D.a ) + ( bgcolor.r * (1-aColor4D.a) );
102  alphacolor.g = ( alphacolor.g * aColor4D.a ) + ( bgcolor.g * (1-aColor4D.a) );
103  alphacolor.b = ( alphacolor.b * aColor4D.a ) + ( bgcolor.b * (1-aColor4D.a) );
104 
105  pen.SetColour( alphacolor.ToColour() );
106  brush.SetColour( alphacolor.ToColour() );
107  bitmapDC.SetPen( pen );
108  bitmapDC.SetBrush( brush );
109 
110  for( int ii = 0; ii < size.x/stepx; ii+=2 )
111  {
112  for( int jj = 0; jj < size.y/stepy; jj+= 2 )
113  {
114  wxPoint pos( stepx*ii + stepx/2, stepy*jj + stepy/2 );
115  bitmapDC.DrawRectangle( pos, wxSize( stepx, stepy ) );
116  }
117  }
118 
119  aStaticBitmap->SetBitmap( newBm );
120 
121  // Deselect the Tool Bitmap from DC, in order to delete the MemoryDC
122  // safely without deleting the bitmap
123  bitmapDC.SelectObject( wxNullBitmap );
124 }
125 
126 
128 {
129  // Draw all bitmaps, with colors according to the color 4D
132  drawAll();
133 
134  m_notebook->GetPage( 0 )->Layout();
135  m_notebook->GetPage( 1 )->Layout();
136 
138 
139  return true;
140 }
141 
142 
144 {
145  #define ID_COLOR_BLACK 2000 // colors_id = ID_COLOR_BLACK a ID_COLOR_BLACK + NBCOLORS-1
146 
147  // Size of color swatches
148  const int w = 32, h = 32;
149 
150  // Colors are built from the g_ColorRefs table (size NBCOLORS).
151  // The look is better when g_ColorRefs order is displayed in a grid matrix
152  // of 6 row and 5 columns, first filling a row, and after the next column.
153  // But the wxFlexGrid used here must be filled by columns, then next row
154  // the best interval g_ColorRefs from a matrix row to the next row is 6
155  // So when have to reorder the index used to explore g_ColorRefs
156  int grid_col = 0;
157  int grid_row = 0;
158  int table_row_count = 6;
159 
160  // If no predefined list is given, build the default predefined colors:
161  if( aPredefinedColors )
162  {
163  for( unsigned jj = 0; jj < aPredefinedColors->size() && jj < NBCOLORS; ++jj )
164  {
165  CUSTOM_COLOR_ITEM* item = & *aPredefinedColors->begin() + jj;
166  int butt_ID = ID_COLOR_BLACK + jj;
167  wxMemoryDC iconDC;
168  wxBitmap ButtBitmap( w, h );
169  wxBrush brush;
170 
171  iconDC.SelectObject( ButtBitmap );
172 
173  KIGFX::COLOR4D buttcolor = item->m_Color;
174 
175  iconDC.SetPen( *wxBLACK_PEN );
176  brush.SetColour( buttcolor.ToColour() );
177  brush.SetStyle( wxBRUSHSTYLE_SOLID );
178 
179  iconDC.SetBrush( brush );
180  iconDC.SetBackground( *wxGREY_BRUSH );
181  iconDC.Clear();
182  iconDC.DrawRoundedRectangle( 0, 0, w, h, (double) h / 3 );
183 
184  wxBitmapButton* bitmapButton = new wxBitmapButton( m_panelDefinedColors, butt_ID, ButtBitmap,
185  wxDefaultPosition, wxSize( w+8, h+6 ) );
186  m_fgridColor->Add( bitmapButton, 0,
187  wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL |
188  wxLEFT | wxBOTTOM, 5 );
189 
190  wxStaticText* label = new wxStaticText( m_panelDefinedColors, -1,
191  item->m_ColorName,
192  wxDefaultPosition, wxDefaultSize, 0 );
193  m_fgridColor->Add( label, 1,
194  wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL |
195  wxLEFT | wxRIGHT | wxBOTTOM, 5 );
196  m_buttonsColor.push_back( bitmapButton );
197 
198  m_Color4DList.push_back( buttcolor );
199 
200  bitmapButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED,
201  wxCommandEventHandler( DIALOG_COLOR_PICKER::buttColorClick ), NULL, this );
202  }
203  }
204  else
205  {
206  m_Color4DList.assign( NBCOLORS, KIGFX::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  { // the current grid row is filled, and we must fill the next grid row
212  grid_col = 0;
213  grid_row++;
214  }
215 
216  int ii = grid_row + (grid_col*table_row_count); // The index in g_ColorRefs
217 
218  int butt_ID = ID_COLOR_BLACK + ii;
219  wxMemoryDC iconDC;
220  wxBitmap ButtBitmap( w, h );
221  wxBrush brush;
222 
223  iconDC.SelectObject( ButtBitmap );
224 
225  KIGFX::COLOR4D buttcolor = KIGFX::COLOR4D( g_ColorRefs[ii].m_Numcolor );
226  m_Color4DList[ butt_ID - ID_COLOR_BLACK ] = buttcolor;
227 
228  iconDC.SetPen( *wxBLACK_PEN );
229  brush.SetColour( buttcolor.ToColour() );
230  brush.SetStyle( wxBRUSHSTYLE_SOLID );
231 
232  iconDC.SetBrush( brush );
233  iconDC.SetBackground( *wxGREY_BRUSH );
234  iconDC.Clear();
235  iconDC.DrawRoundedRectangle( 0, 0, w, h, (double) h / 3 );
236 
237  wxBitmapButton* bitmapButton = new wxBitmapButton( m_panelDefinedColors, butt_ID, ButtBitmap,
238  wxDefaultPosition, wxSize( w+8, h+6 ) );
239  m_fgridColor->Add( bitmapButton, 0,
240  wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL |
241  wxLEFT | wxBOTTOM, 5 );
242 
243  wxStaticText* label = new wxStaticText( m_panelDefinedColors, -1,
244  wxGetTranslation( g_ColorRefs[ii].m_ColorName ),
245  wxDefaultPosition, wxDefaultSize, 0 );
246  m_fgridColor->Add( label, 1,
247  wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL |
248  wxLEFT | wxRIGHT | wxBOTTOM, 5 );
249  m_buttonsColor.push_back( bitmapButton );
250  bitmapButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED,
251  wxCommandEventHandler( DIALOG_COLOR_PICKER::buttColorClick ), NULL, this );
252  }
253  }
254 }
255 
256 
258 {
259  wxMemoryDC bitmapDC;
260  wxSize bmsize = m_RgbBitmap->GetSize();
261  int half_size = std::min( bmsize.x, bmsize.y )/2;
262  m_bitmapRGB = new wxBitmap( bmsize );
263  bitmapDC.SelectObject( *m_bitmapRGB );
264  wxPen pen;
265 
266  // clear background (set the window bg color)
267  wxBrush bgbrush( GetBackgroundColour() );
268  bitmapDC.SetBackground( bgbrush );
269  bitmapDC.Clear();
270 
271  // Use Y axis from bottom to top and origin to center
272  bitmapDC.SetAxisOrientation( true, true );
273  bitmapDC.SetDeviceOrigin( half_size, half_size );
274 
275  // Reserve room to draw cursors inside the bitmap
276  half_size -= m_cursorsSize/2;
277 
279 
280  // Red blue area in X Z 3d axis
281  double inc = 1.0 / half_size;
282  #define SLOPE_AXIS 50.0
283  double slope = SLOPE_AXIS/half_size;
284  color.g = 0.0;
285 
286  for( int xx = 0; xx < half_size; xx++ ) // blue axis
287  {
288  color.b = inc * xx;
289 
290  for( int yy = 0; yy < half_size; yy++ ) // Red axis
291  {
292  color.r = inc * yy;
293 
294  pen.SetColour( color.ToColour() );
295  bitmapDC.SetPen( pen );
296  bitmapDC.DrawPoint( xx, yy - (slope*xx) );
297  }
298  }
299 
300  // Red green area in y Z 3d axis
301  color.b = 0.0;
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 
310  pen.SetColour( color.ToColour() );
311  bitmapDC.SetPen( pen );
312  bitmapDC.DrawPoint( -xx, yy - (slope*xx) );
313  }
314  }
315 
316  // Blue green area in x y 3d axis
317  color.r = 0.0;
318  for( int xx = 0; xx < half_size; xx++ ) // green axis
319  {
320  color.g = inc * xx;
321 
322  for( int yy = 0; yy < half_size; yy++ ) // blue axis
323  {
324  color.b = inc * yy;
325 
326  pen.SetColour( color.ToColour() );
327  bitmapDC.SetPen( pen );
328 
329  // Mapping the xx, yy color axis to draw coordinates is more tricky than previously
330  // in DC coordinates:
331  // the blue axis is the (0, 0) to half_size, (-yy - SLOPE_AXIS)
332  // the green axis is the (0, 0) to - half_size, (-yy - SLOPE_AXIS)
333  int drawX = -xx + yy;
334  int drawY = - std::min( xx,yy ) * 0.9;
335  bitmapDC.DrawPoint( drawX, drawY - std::abs( slope*drawX ) );
336  }
337  }
338 }
339 
340 
342 {
343  wxMemoryDC bitmapDC;
344  wxSize bmsize = m_HsvBitmap->GetSize();
345  int half_size = std::min( bmsize.x, bmsize.y )/2;
346  delete m_bitmapHSV;
347  m_bitmapHSV = new wxBitmap( bmsize );
348  bitmapDC.SelectObject( *m_bitmapHSV );
349  wxPen pen;
350 
351  // clear background (set the window bd color)
352  wxBrush bgbrush( GetBackgroundColour() );
353  bitmapDC.SetBackground( bgbrush );
354  bitmapDC.Clear();
355 
356  // Use Y axis from bottom to top and origin to center
357  bitmapDC.SetAxisOrientation( true, true );
358  bitmapDC.SetDeviceOrigin( half_size, half_size );
359 
360  // Reserve room to draw cursors inside the bitmap
361  half_size -= m_cursorsSize/2;
362 
363  double hue, sat;
365  int sq_radius = half_size*half_size;
366 
367  for( int xx = -half_size; xx < half_size; xx++ )
368  {
369  for( int yy = -half_size; yy < half_size; yy++ )
370  {
371  sat = double(xx*xx + yy*yy) / sq_radius;
372 
373  // sat is <= 1.0
374  // any value > 1.0 is not a valid HSB color:
375  if( sat > 1.0 )
376  continue;
377 
378  // sat is the distance from center
379  sat = sqrt( sat );
380  hue = atan2( (double)yy, (double)xx ) * 180 / M_PI;
381 
382  if( hue < 0.0 )
383  hue += 360.0;
384 
385  color.FromHSV( hue, sat, 1.0 );
386 
387  pen.SetColour( color.ToColour() );
388  bitmapDC.SetPen( pen );
389  bitmapDC.DrawPoint( xx, yy );
390  }
391  }
392 
393  /* Deselect the Tool Bitmap from DC,
394  * in order to delete the MemoryDC safely without deleting the bitmap
395  */
396  bitmapDC.SelectObject( wxNullBitmap );
397 }
398 
399 
401 {
402  if( !m_bitmapRGB || m_bitmapRGB->GetSize() != m_RgbBitmap->GetSize() )
403  createRGBBitmap();
404 
405  wxMemoryDC bitmapDC;
406  wxSize bmsize = m_bitmapRGB->GetSize();
407  int half_size = std::min( bmsize.x, bmsize.y )/2;
408  wxBitmap newBm( *m_bitmapRGB );
409  bitmapDC.SelectObject( newBm );
410 
411  // Use Y axis from bottom to top and origin to center
412  bitmapDC.SetAxisOrientation( true, true );
413  bitmapDC.SetDeviceOrigin( half_size, half_size );
414 
415  // Reserve room to draw cursors inside the bitmap
416  half_size -= m_cursorsSize/2;
417 
418  // Draw the 3 RGB cursors, usiing white color to make them always visible:
419  wxPen pen( wxColor( 255, 255, 255 ) );
420  wxBrush brush( wxColor( 0, 0, 0 ), wxBRUSHSTYLE_TRANSPARENT );
421  bitmapDC.SetPen( pen );
422  bitmapDC.SetBrush( brush );
423  int half_csize = m_cursorsSize/2;
424 
425  #define SLOPE_AXIS 50.0
426  double slope = SLOPE_AXIS/half_size;
427 
428  // Red axis cursor (Z 3Daxis):
429  m_cursorBitmapRed.x = 0;
430  m_cursorBitmapRed.y = m_newColor4D.r * half_size;
431  bitmapDC.DrawRectangle( m_cursorBitmapRed.x - half_csize,
432  m_cursorBitmapRed.y - half_csize,
434 
435  // Blue axis cursor (X 3Daxis):
436  m_cursorBitmapBlue.x = m_newColor4D.b * half_size;
438  bitmapDC.DrawRectangle( m_cursorBitmapBlue.x - half_csize,
439  m_cursorBitmapBlue.y - half_csize,
441 
442  // Green axis cursor (Y 3Daxis):
443  m_cursorBitmapGreen.x = m_newColor4D.g * half_size;
446 
447  bitmapDC.DrawRectangle( m_cursorBitmapGreen.x - half_csize,
448  m_cursorBitmapGreen.y - half_csize,
450 
451  // Draw the 3 RGB axis:
452  half_size += half_size/5;
453  bitmapDC.DrawLine( 0, 0, 0, half_size ); // Red axis (Z 3D axis)
454  bitmapDC.DrawLine( 0, 0, half_size, - half_size*slope ); // Blue axis (X 3D axis)
455  bitmapDC.DrawLine( 0, 0, -half_size, - half_size*slope ); // green axis (Y 3D axis)
456 
457  m_RgbBitmap->SetBitmap( newBm );
458  /* Deselect the Tool Bitmap from DC,
459  * in order to delete the MemoryDC safely without deleting the bitmap */
460  bitmapDC.SelectObject( wxNullBitmap );
461 }
462 
463 
465 {
466  if( !m_bitmapHSV || m_bitmapHSV->GetSize() != m_HsvBitmap->GetSize() )
467  createHSVBitmap();
468 
469  wxMemoryDC bitmapDC;
470  wxSize bmsize = m_bitmapHSV->GetSize();
471  int half_size = std::min( bmsize.x, bmsize.y )/2;
472  wxBitmap newBm( *m_bitmapHSV );
473  bitmapDC.SelectObject( newBm );
474 
475  // Use Y axis from bottom to top and origin to center
476  bitmapDC.SetAxisOrientation( true, true );
477  bitmapDC.SetDeviceOrigin( half_size, half_size );
478 
479  // Reserve room to draw cursors inside the bitmap
480  half_size -= m_cursorsSize/2;
481 
482  // Draw the HSB cursor:
483  m_cursorBitmapHSV.x = cos( m_hue * M_PI / 180.0 ) * half_size * m_sat;
484  m_cursorBitmapHSV.y = sin( m_hue * M_PI / 180.0 ) * half_size * m_sat;
485 
486  wxPen pen( wxColor( 0, 0, 0 ) );
487  wxBrush brush( wxColor( 0, 0, 0 ), wxBRUSHSTYLE_TRANSPARENT );
488  bitmapDC.SetPen( pen );
489  bitmapDC.SetBrush( brush );
490 
491  int half_csize = m_cursorsSize/2;
492  bitmapDC.DrawRectangle( m_cursorBitmapHSV.x- half_csize,
493  m_cursorBitmapHSV.y-half_csize,
495 
496  m_HsvBitmap->SetBitmap( newBm );
497  /* Deselect the Tool Bitmap from DC,
498  * in order to delete the MemoryDC safely without deleting the bitmap
499  */
500  bitmapDC.SelectObject( wxNullBitmap );
501 }
502 
503 
505 {
507 
508  if( aChanged == RED_CHANGED || aChanged == GREEN_CHANGED || aChanged == BLUE_CHANGED )
509  m_newColor4D.ToHSV( m_hue, m_sat, m_val, true );
510 
511  if( aChanged != RED_CHANGED )
512  m_spinCtrlRed->SetValue( normalizeToInt( m_newColor4D.r ) );
513 
514  if( aChanged != GREEN_CHANGED )
516 
517  if( aChanged != BLUE_CHANGED )
519 
520  if( aChanged != HUE_CHANGED )
521  m_spinCtrlHue->SetValue( (int)m_hue );
522 
523  if( aChanged != SAT_CHANGED )
524  m_spinCtrlSaturation->SetValue( m_sat * 255 );
525 
526  if( aChanged != VAL_CHANGED )
527  {
528  m_sliderBrightness->SetValue(normalizeToInt( m_val ) );
529  }
530 }
531 
532 
534 {
535  m_NewColorRect->Freeze(); // Avoid flicker
536  m_HsvBitmap->Freeze();
537  m_RgbBitmap->Freeze();
539  drawHSVPalette();
540  drawRGBPalette();
541  m_NewColorRect->Thaw();
542  m_HsvBitmap->Thaw();
543  m_RgbBitmap->Thaw();
544  m_NewColorRect->Refresh();
545  m_HsvBitmap->Refresh();
546  m_RgbBitmap->Refresh();
547 }
548 
549 
550 void DIALOG_COLOR_PICKER::buttColorClick( wxCommandEvent& event )
551 {
552  int id = event.GetId();
553  KIGFX::COLOR4D color( m_Color4DList[id - ID_COLOR_BLACK] );//EDA_COLOR_T( id - ID_COLOR_BLACK ) );
554  m_newColor4D.r = color.r;
555  m_newColor4D.g = color.g;
556  m_newColor4D.b = color.b;
557 
558  m_newColor4D.ToHSV( m_hue, m_sat, m_val, true );
560 
561  drawAll();
562 
563  event.Skip();
564 }
565 
566 
567 void DIALOG_COLOR_PICKER::onRGBMouseClick( wxMouseEvent& event )
568 {
569  m_allowMouseEvents = true;
570  wxPoint mousePos = event.GetPosition();
571 
572  // The cursor position is relative to the m_bitmapHSV wxBitmap center
573  wxSize bmsize = m_bitmapRGB->GetSize();
574  int half_size = std::min( bmsize.x, bmsize.y )/2;
575  mousePos.x -= half_size;
576  mousePos.y -= half_size;
577  mousePos.y = -mousePos.y; // Use the bottom to top vertical axis
578 
579  wxPoint dist = m_cursorBitmapRed - mousePos;
580 
581  if( std::abs( dist.x ) <= m_cursorsSize/2 && std::abs( dist.y ) <= m_cursorsSize/2 )
582  {
584  return;
585  }
586 
587  dist = m_cursorBitmapGreen - mousePos;
588 
589  if( std::abs( dist.x ) <= m_cursorsSize/2 && std::abs( dist.y ) <= m_cursorsSize/2 )
590  {
592  return;
593  }
594 
595  dist = m_cursorBitmapBlue - mousePos;
596 
597  if( std::abs( dist.x ) <= m_cursorsSize/2 && std::abs( dist.y ) <= m_cursorsSize/2 )
598  {
600  return;
601  }
602 
603  m_selectedCursor = nullptr;
604 }
605 
606 
607 void DIALOG_COLOR_PICKER::onRGBMouseDrag( wxMouseEvent& event )
608 {
609  if( !event.Dragging() || !m_allowMouseEvents )
610  {
611  m_selectedCursor = nullptr;
612  return;
613  }
614 
618  return;
619 
620  // Adjust the HSV cursor position to follow the mouse cursor
621  // The cursor position is relative to the m_bitmapHSV wxBitmap center
622  wxPoint mousePos = event.GetPosition();
623  wxSize bmsize = m_bitmapRGB->GetSize();
624  int half_size = std::min( bmsize.x, bmsize.y )/2;
625  mousePos.x -= half_size;
626  mousePos.y -= half_size;
627  mousePos.y = -mousePos.y; // Use the bottom to top vertical axis
628 
629  half_size -= m_cursorsSize/2; // the actual half_size of the palette area
630 
631  // Change colors according to the selected cursor:
633  {
634  if( mousePos.y >= 0 && mousePos.y <= half_size )
635  m_newColor4D.r = (double)mousePos.y / half_size;
636  else
637  return;
638  }
639 
641  {
642  mousePos.x = -mousePos.x;
643 
644  if( mousePos.x >= 0 && mousePos.x <= half_size )
645  m_newColor4D.g = (double)mousePos.x / half_size;
646  else
647  return;
648  }
649 
651  {
652  if( mousePos.x >= 0 && mousePos.x <= half_size )
653  m_newColor4D.b = (double)mousePos.x / half_size;
654  else
655  return;
656  }
657 
658  m_newColor4D.ToHSV( m_hue, m_sat, m_val, true );
660 
661  drawAll();
662 }
663 
664 
665 void DIALOG_COLOR_PICKER::onHSVMouseClick( wxMouseEvent& event )
666 {
667  m_allowMouseEvents = true;
668 
669  if( setHSvaluesFromCursor( event.GetPosition() ) )
670  drawAll();
671 }
672 
673 
674 void DIALOG_COLOR_PICKER::onHSVMouseDrag( wxMouseEvent& event )
675 {
676  if( !event.Dragging() || !m_allowMouseEvents )
677  return;
678 
679  if( setHSvaluesFromCursor( event.GetPosition() ) )
680  drawAll();
681 }
682 
683 
685 {
686  wxPoint mousePos = aMouseCursor;
687  wxSize bmsize = m_bitmapHSV->GetSize();
688  int half_size = std::min( bmsize.x, bmsize.y )/2;
689  // Make the cursor position relative to the m_bitmapHSV wxBitmap center
690  mousePos.x -= half_size;
691  mousePos.y -= half_size;
692  mousePos.y = -mousePos.y; // Use the bottom to top vertical axis
693 
694  // The HS cursor position is restricted to a circle of radius half_size
695  double dist_from_centre = hypot( (double)mousePos.x, (double)mousePos.y );
696 
697  if( dist_from_centre > half_size )
698  // Saturation cannot be calculated:
699  return false;
700 
701  m_cursorBitmapHSV = mousePos;
702 
703  // Set saturation and hue from new cursor position:
704  half_size -= m_cursorsSize/2; // the actual half_size of the palette area
705  m_sat = dist_from_centre / half_size;
706 
707  if( m_sat > 1.0 )
708  m_sat = 1.0;
709 
710  m_hue = atan2( mousePos.y, mousePos.x ) / M_PI * 180.0;
711 
712  if( m_hue < 0 )
713  m_hue += 360.0;
714 
717 
718  return true;
719 }
720 
721 
722 void DIALOG_COLOR_PICKER::OnChangeAlpha( wxScrollEvent& event )
723 {
724  double alpha = (double)event.GetPosition() / ALPHA_MAX;
725  m_newColor4D.a = alpha;
726  m_NewColorRect->Freeze(); // Avoid flicker
728  m_NewColorRect->Thaw();
729  m_NewColorRect->Refresh();
730 }
731 
732 
733 void DIALOG_COLOR_PICKER::OnChangeEditRed( wxSpinEvent& event )
734 {
735  double val = (double)event.GetPosition() / 255.0;
736  m_newColor4D.r = val;
738 
739  drawAll();
740 }
741 
742 
743 void DIALOG_COLOR_PICKER::OnChangeEditGreen( wxSpinEvent& event )
744 {
745  double val = (double)event.GetPosition() / 255.0;
746  m_newColor4D.g = val;
748 
749  drawAll();
750 }
751 
752 
753 void DIALOG_COLOR_PICKER::OnChangeEditBlue( wxSpinEvent& event )
754 {
755  double val = (double)event.GetPosition() / 255.0;
756  m_newColor4D.b = val;
758 
759  drawAll();
760 }
761 
762 
763 void DIALOG_COLOR_PICKER::OnChangeEditHue( wxSpinEvent& event )
764 {
765  m_hue = (double)event.GetPosition();
766 
768 
770 
771  drawAll();
772 }
773 
774 
775 void DIALOG_COLOR_PICKER::OnChangeEditSat( wxSpinEvent& event )
776 {
777  m_sat = (double)event.GetPosition() / 255.0;
778 
780 
782 
783  drawAll();
784 }
785 
786 
787 void DIALOG_COLOR_PICKER::OnChangeBrightness( wxScrollEvent& event )
788 {
789  m_val = (double)event.GetPosition() / 255.0;
790 
792 
794 
795  drawAll();
796 }
double m_hue
the current hue, in degrees (0 ... 360)
bool m_allowOpacityCtrl
true to show the widget, false to keep alpha channel = 1.0
double m_sat
the current saturation (0 ... 1.0)
void SetEditVals(CHANGED_COLOR aChanged)
void drawRGBPalette()
draws the RVB color space
static const int dist[10][10]
Definition: ar_matrix.cpp:320
void OnChangeEditGreen(wxSpinEvent &event) override
std::vector< KIGFX::COLOR4D > m_Color4DList
the list of color4d ordered by button ID, for predefined colors
CHANGED_COLOR
int color
Definition: DXF_plotter.cpp:62
void OnChangeAlpha(wxScrollEvent &event) override
Event handlers from wxSpinControl.
int normalizeToInt(double aValue, int aValMax=255)
void FinishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
void onHSVMouseDrag(wxMouseEvent &event) override
double g
Green component.
Definition: color4d.h:288
void drawHSVPalette()
draws the HSV color circle
a class to handle a custom color (predefined color) for the color picker dialog
DIALOG_COLOR_PICKER(wxWindow *aParent, KIGFX::COLOR4D &aCurrentColor, bool aAllowOpacityControl, CUSTOM_COLORS_LIST *aUserColors=nullptr)
Dialog constructor.
std::vector< CUSTOM_COLOR_ITEM > CUSTOM_COLORS_LIST
void createHSVBitmap()
generate the bitmap that shows the HSV color circle
#define abs(a)
Definition: auxiliary.h:84
void setIconColor(wxStaticBitmap *aStaticBitmap, KIGFX::COLOR4D &aColor4D)
repaint a static bitmap with the aColor4D color
bool setHSvaluesFromCursor(wxPoint aMouseCursor)
manage the Hue and Saturation settings when the mouse cursor is at aMouseCursor.
void OnChangeBrightness(wxScrollEvent &event) override
Event handler from wxSlider: alpha (transparency) control.
KIGFX::COLOR4D m_newColor4D
the current color4d
void ToHSV(double &aOutHue, double &aOutSaturation, double &aOutValue, bool aAlwaysDefineHue=false) const
Function ToHSV() Converts current color (stored in RGB) to HSV format.
Definition: color4d.cpp:286
void onHSVMouseClick(wxMouseEvent &event) override
wxPoint m_cursorBitmapHSV
the cursor on the HSV bitmap palette.
double b
Blue component.
Definition: color4d.h:289
double a
Alpha component.
Definition: color4d.h:290
void onRGBMouseClick(wxMouseEvent &event) override
mouse handlers, when clicking on a palette bitmap
KIGFX::COLOR4D m_previousColor4D
the inital color4d
void createRGBBitmap()
generate the bitmap that shows the RVB color space
static int m_ActivePage
the active notebook page, stored during a session
#define ALPHA_MAX
wxBitmap * m_bitmapHSV
the basic HUV palette
void OnChangeEditHue(wxSpinEvent &event) override
void buttColorClick(wxCommandEvent &event)
Event handler for defined color buttons
Class DIALOG_COLOR_PICKER_BASE.
const StructColors g_ColorRefs[NBCOLORS]
The predefined colors used in KiCad.
Definition: colors.cpp:37
void onRGBMouseDrag(wxMouseEvent &event) override
void FromHSV(double aInH, double aInS, double aInV)
Function FromHSV() Changes currently used color to the one given by hue, saturation and value paramet...
Definition: color4d.cpp:339
double m_val
the current value (0 ... 1.0)
wxPoint m_cursorBitmapRed
the red cursor on the RGB bitmap palette.
wxPoint m_cursorBitmapBlue
the blue cursor on the RGB bitmap palette.
void OnChangeEditBlue(wxSpinEvent &event) override
bool TransferDataToWindow() override
called when creating the dialog
void initDefinedColors(CUSTOM_COLORS_LIST *aPredefinedColors)
creates the bitmap buttons for each defined colors if aPredefinedColors is nullptr, a internal predefined list will be used
std::vector< wxBitmapButton * > m_buttonsColor
list of defined colors buttons
KIGFX::COLOR4D m_Color
void OnChangeEditRed(wxSpinEvent &event) override
wxBitmap * m_bitmapRGB
the basic RGB palette
double r
Red component.
Definition: color4d.h:287
Number of colors.
Definition: colors.h:75
#define SLOPE_AXIS
#define ID_COLOR_BLACK
void OnChangeEditSat(wxSpinEvent &event) override
wxPoint m_cursorBitmapGreen
the green cursor on the RGB bitmap palette.
#define min(a, b)
Definition: auxiliary.h:85
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39
wxPoint * m_selectedCursor
the ref cursor to the selected curor, if any, or null.