KiCad PCB EDA Suite
color_swatch.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) 2017-2020 KiCad Developers, see AUTHORS.txt for contributors.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you may find one here:
18  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19  * or you may search the http://www.gnu.org website for the version 2 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 #include <widgets/color_swatch.h>
25 
26 #include "dialog_color_picker.h"
27 #include <memory>
28 
29 wxDEFINE_EVENT(COLOR_SWATCH_CHANGED, wxCommandEvent);
30 
31 using KIGFX::COLOR4D;
32 
33 
34 const static wxSize PALETTE_SWATCH_SIZE_DU( 8, 6 );
35 const static wxSize DIALOG_SWATCH_SIZE_DU( 24, 10 );
36 
37 // See selcolor.cpp:
38 extern COLOR4D DisplayColorFrame( wxWindow* aParent, COLOR4D aOldColor );
39 
40 
46 wxBitmap COLOR_SWATCH::MakeBitmap( COLOR4D aColor, COLOR4D aBackground, wxSize aSize )
47 {
48  wxBitmap bitmap( aSize );
49  wxBrush brush;
50  wxMemoryDC iconDC;
51 
52  iconDC.SelectObject( bitmap );
53 
54  brush.SetStyle( wxBRUSHSTYLE_SOLID );
55  brush.SetColour( aBackground.WithAlpha(1.0).ToColour() );
56  iconDC.SetBrush( brush );
57  iconDC.DrawRectangle( 0, 0, aSize.x, aSize.y );
58 
59  if( aColor == COLOR4D::UNSPECIFIED )
60  {
61  aColor = aBackground.Inverted();
62  brush.SetStyle( wxBRUSHSTYLE_BDIAGONAL_HATCH );
63  }
64 
65  brush.SetColour( aColor.ToColour() );
66  iconDC.SetBrush( brush );
67  iconDC.DrawRectangle( 0, 0, aSize.x, aSize.y );
68 
69  return bitmap;
70 }
71 
72 
73 COLOR_SWATCH::COLOR_SWATCH( wxWindow* aParent, COLOR4D aColor, int aID, COLOR4D aBackground,
74  const COLOR4D aDefault, bool aForDialog ) :
75  wxPanel( aParent, aID ),
76  m_color( aColor ),
77  m_background( aBackground ),
78  m_default( aDefault )
79 {
80  if( aForDialog )
81  m_size = ConvertDialogToPixels( DIALOG_SWATCH_SIZE_DU );
82  else
83  m_size = ConvertDialogToPixels( PALETTE_SWATCH_SIZE_DU );
84 
85  auto sizer = new wxBoxSizer( wxHORIZONTAL );
86  SetSizer( sizer );
87 
88  wxBitmap bitmap = COLOR_SWATCH::MakeBitmap( aColor, aBackground, m_size );
89  m_swatch = new wxStaticBitmap( this, aID, bitmap );
90 
91  sizer->Add( m_swatch, 0, 0 );
92 
93  setupEvents();
94 }
95 
96 
97 COLOR_SWATCH::COLOR_SWATCH( wxWindow *aParent, wxWindowID aID, const wxPoint &aPos,
98  const wxSize &aSize, long aStyle ) :
99  wxPanel( aParent, aID, aPos, aSize, aStyle )
100 {
101  if( aSize == wxDefaultSize )
102  m_size = ConvertDialogToPixels( DIALOG_SWATCH_SIZE_DU );
103  else
104  m_size = aSize;
105 
106  SetSize( m_size );
107 
108  auto sizer = new wxBoxSizer( wxHORIZONTAL );
109  SetSizer( sizer );
110 
113  m_swatch = new wxStaticBitmap( this, aID, bitmap );
114 
115  sizer->Add( m_swatch, 0, 0 );
116 
117  setupEvents();
118 }
119 
120 
122 {
123  wxWindow* topLevelParent = GetParent();
124 
125  while( topLevelParent && !topLevelParent->IsTopLevel() )
126  topLevelParent = topLevelParent->GetParent();
127 
128  if( topLevelParent && dynamic_cast<DIALOG_SHIM*>( topLevelParent ) )
129  {
130  m_swatch->Bind( wxEVT_LEFT_DOWN,
131  [this] ( wxMouseEvent& aEvt )
132  {
134  } );
135  }
136  else
137  {
138  // forward click to any other listeners, since we don't want them
139  m_swatch->Bind( wxEVT_LEFT_DOWN, &COLOR_SWATCH::rePostEvent, this );
140 
141  // bind the events that trigger the dialog
142  m_swatch->Bind( wxEVT_LEFT_DCLICK,
143  [this] ( wxMouseEvent& aEvt )
144  {
146  } );
147  }
148 
149  m_swatch->Bind( wxEVT_MIDDLE_DOWN,
150  [this] ( wxMouseEvent& aEvt )
151  {
153  } );
154 
155  m_swatch->Bind( wxEVT_RIGHT_DOWN, &COLOR_SWATCH::rePostEvent, this );
156 }
157 
158 
159 void COLOR_SWATCH::rePostEvent( wxEvent& aEvt )
160 {
161  wxPostEvent( this, aEvt );
162 }
163 
164 
165 static void sendSwatchChangeEvent( COLOR_SWATCH& aSender )
166 {
167  wxCommandEvent changeEvt( COLOR_SWATCH_CHANGED );
168 
169  // use this class as the object (alternative might be to
170  // set a custom event class but that's more work)
171  changeEvt.SetEventObject( &aSender );
172 
173  wxPostEvent( &aSender, changeEvt );
174 }
175 
176 
177 void COLOR_SWATCH::SetSwatchColor( COLOR4D aColor, bool sendEvent )
178 {
179  m_color = aColor;
180 
181  wxBitmap bm = MakeBitmap( m_color == COLOR4D::UNSPECIFIED ? m_default : m_color,
182  m_background, m_size );
183  m_swatch->SetBitmap( bm );
184 
185  if( sendEvent )
186  sendSwatchChangeEvent( *this );
187 }
188 
189 
191 {
192  m_default = aColor;
193 }
194 
195 
197 {
198  m_background = aBackground;
199  wxBitmap bm = MakeBitmap( m_color, m_background, m_size );
200  m_swatch->SetBitmap( bm );
201 }
202 
203 
205 {
206  return m_color;
207 }
208 
209 
211 {
212  COLOR4D newColor = COLOR4D::UNSPECIFIED;
213 
214  DIALOG_COLOR_PICKER dialog( ::wxGetTopLevelParent( this ), m_color, true, nullptr, m_default );
215 
216  if( dialog.ShowModal() == wxID_OK )
217  newColor = dialog.GetColor();
218 
219  if( newColor != COLOR4D::UNSPECIFIED || m_default == COLOR4D::UNSPECIFIED )
220  {
221  m_color = newColor;
222 
223  wxBitmap bm = MakeBitmap( newColor, m_background, m_size );
224  m_swatch->SetBitmap( bm );
225 
226  sendSwatchChangeEvent( *this );
227  }
228 }
COLOR4D DisplayColorFrame(wxWindow *aParent, COLOR4D aOldColor)
KIGFX::COLOR4D GetSwatchColor() const
void SetSwatchColor(KIGFX::COLOR4D aColor, bool sendEvent)
Set the current swatch color directly.
COLOR4D Inverted() const
Function Inverted Returns an inverted color, alpha remains the same.
Definition: color4d.h:319
void setupEvents()
void SetDefaultColor(KIGFX::COLOR4D aColor)
Sets the color that will be chosen with the "Reset to Default" button in the chooser.
COLOR_SWATCH(wxWindow *aParent, KIGFX::COLOR4D aColor, int aID, KIGFX::COLOR4D aBackground, const KIGFX::COLOR4D aDefault, bool aForDialog)
Construct a COLOR_SWATCH.
static const wxSize PALETTE_SWATCH_SIZE_DU(8, 6)
COLOR4D WithAlpha(double aAlpha) const
Function WithAlpha Returns a colour with the same colour, but the given alpha.
Definition: color4d.h:307
void SetSwatchBackground(KIGFX::COLOR4D aBackground)
Set the swatch background color.
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition: color4d.h:372
KIGFX::COLOR4D m_default
The default color for the swatch
Definition: color_swatch.h:102
void rePostEvent(wxEvent &aEvt)
Pass unwanted events on to listeners of this object.
KIGFX::COLOR4D m_background
The background colour to show the swatch over
Definition: color_swatch.h:99
static wxBitmap MakeBitmap(KIGFX::COLOR4D aColor, KIGFX::COLOR4D aBackground, wxSize aSize)
Make a simple color swatch bitmap.
wxStaticBitmap * m_swatch
Handle of the actual swatch shown
Definition: color_swatch.h:105
wxDEFINE_EVENT(COLOR_SWATCH_CHANGED, wxCommandEvent)
static void sendSwatchChangeEvent(COLOR_SWATCH &aSender)
KIGFX::COLOR4D GetColor()
Class representing a simple color swatch, of the kind used to set layer colors.
Definition: color_swatch.h:38
void GetNewSwatchColor()
Prompt for a new colour, using the colour picker dialog.
KIGFX::COLOR4D m_color
The current colour of the swatch
Definition: color_swatch.h:96
static const wxSize DIALOG_SWATCH_SIZE_DU(24, 10)
COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:99