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