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