KiCad PCB EDA Suite
layer_widget.cpp
Go to the documentation of this file.
1 
2 /*
3  * This program source code file is part of KiCad, a free EDA CAD application.
4  *
5  * Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
6  * Copyright (C) 2010 KiCad Developers, see change_log.txt for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
26 
27 
28 /* This source module implements the layer visibility and selection widget
29  @todo make bitmap size dependent on the point size.
30 */
31 
32 
33 //#define STAND_ALONE 1 // define to enable test program for LAYER_WIDGET
34 
35 
36 #include <layer_widget.h>
37 
38 #include <macros.h>
39 #include <common.h>
40 
41 #include <widgets/indicator_icon.h>
42 
43 #include <algorithm>
44 
45 #include <menus_helpers.h>
46 
47 
48 const wxEventType LAYER_WIDGET::EVT_LAYER_COLOR_CHANGE = wxNewEventType();
49 
50 
55 static void shrinkFont( wxWindow* aControl, int aPointSize )
56 {
57  wxFont font = aControl->GetFont();
58  font.SetPointSize( aPointSize );
59  aControl->SetFont( font ); // need this?
60 }
61 
62 
63 int LAYER_WIDGET::encodeId( int aColumn, int aId )
64 {
65  int id = aId * LYR_COLUMN_COUNT + aColumn;
66  return id;
67 }
68 
69 
71 {
72  int id = aControlId / LYR_COLUMN_COUNT; // rounding is OK.
73  return id;
74 }
75 
76 
77 void LAYER_WIDGET::OnLeftDownLayers( wxMouseEvent& event )
78 {
79  int row;
80  LAYER_NUM layer;
81 
82  wxWindow* eventSource = (wxWindow*) event.GetEventObject();
83 
84  // if mouse event is coming from the m_LayerScrolledWindow and not one
85  // of its children, we have to find the row manually based on y coord.
86  if( eventSource == m_LayerScrolledWindow )
87  {
88  int y = event.GetY();
89 
90  wxArrayInt heights = m_LayersFlexGridSizer->GetRowHeights();
91 
92  int height = 0;
93 
94  int rowCount = GetLayerRowCount();
95  for( row = 0; row<rowCount; ++row )
96  {
97  if( y < height + heights[row] )
98  break;
99 
100  height += heights[row];
101  }
102 
103  if( row >= rowCount )
104  row = rowCount - 1;
105 
106  layer = getDecodedId( getLayerComp( row, 0 )->GetId() );
107  }
108 
109  else
110  {
111  // all nested controls on a given row will have their ID encoded with
112  // encodeId(), and the corresponding decoding is getDecodedId()
113  int id = eventSource->GetId();
114  layer = getDecodedId( id );
115  row = findLayerRow( layer );
116  }
117 
118  if( OnLayerSelect( layer ) ) // if client allows this change.
119  SelectLayerRow( row );
120 
121  passOnFocus();
122 }
123 
124 
125 void LAYER_WIDGET::OnRightDownLayer( wxMouseEvent& aEvent, COLOR_SWATCH* aColorSwatch, const wxString& aLayerName )
126 {
127  wxMenu menu;
128 
130  _( "Change Layer Color for " ) + aLayerName,
131  KiBitmap( setcolor_copper_xpm ) );
132  menu.AppendSeparator();
133 
134  OnLayerRightClick( menu );
135 
136  menu.Bind( wxEVT_COMMAND_MENU_SELECTED, [this, aColorSwatch]( wxCommandEvent& event ) {
137  if ( event.GetId() == ID_CHANGE_LAYER_COLOR ) {
138  aColorSwatch->GetNewSwatchColor();
139  } else {
140  event.Skip();
141  }
142  } );
143 
144  PopupMenu( &menu );
145  passOnFocus();
146 }
147 
148 
149 void LAYER_WIDGET::OnLayerSwatchChanged( wxCommandEvent& aEvent )
150 {
151  auto eventSource = static_cast<COLOR_SWATCH*>( aEvent.GetEventObject() );
152 
153  COLOR4D newColor = eventSource->GetSwatchColor();
154 
155  LAYER_NUM layer = getDecodedId( eventSource->GetId() );
156 
157  // tell the client code.
158  OnLayerColorChange( layer, newColor );
159 
160  // notify others
161  wxCommandEvent event( EVT_LAYER_COLOR_CHANGE );
162  wxPostEvent( this, event );
163 
164  passOnFocus();
165 }
166 
167 
168 void LAYER_WIDGET::OnLayerCheckBox( wxCommandEvent& event )
169 {
170  wxCheckBox* eventSource = (wxCheckBox*) event.GetEventObject();
171  LAYER_NUM layer = getDecodedId( eventSource->GetId() );
172  OnLayerVisible( layer, eventSource->IsChecked() );
173  passOnFocus();
174 }
175 
176 
177 void LAYER_WIDGET::OnRightDownRender( wxMouseEvent& aEvent, COLOR_SWATCH* aColorSwatch, const wxString& aRenderName )
178 {
179  wxMenu menu;
180 
182  _( "Change Render Color for " ) + aRenderName,
183  KiBitmap( setcolor_board_body_xpm ) );
184 
185  menu.Bind( wxEVT_COMMAND_MENU_SELECTED, [this, aColorSwatch]( wxCommandEvent& event ) {
186  if ( event.GetId() == ID_CHANGE_RENDER_COLOR ) {
187  aColorSwatch->GetNewSwatchColor();
188  } else {
189  event.Skip();
190  }
191  } );
192 
193  PopupMenu( &menu );
194  passOnFocus();
195 }
196 
197 
198 void LAYER_WIDGET::OnRenderSwatchChanged( wxCommandEvent& aEvent )
199 {
200  auto eventSource = static_cast<COLOR_SWATCH*>( aEvent.GetEventObject() );
201 
202  COLOR4D newColor = eventSource->GetSwatchColor();
203 
204  LAYER_NUM id = getDecodedId( eventSource->GetId() );
205 
206  if( id == LAYER_PCB_BACKGROUND )
207  {
208  // Update all swatch backgrounds
209  int count = GetLayerRowCount();
210  int row;
211  int col = 1; // bitmap button is column 1 in layers tab
212  for( row = 0; row < count; ++row )
213  {
214  COLOR_SWATCH* swatch = dynamic_cast<COLOR_SWATCH*>( getLayerComp( row, col ) );
215  if( swatch )
216  swatch->SetSwatchBackground( newColor );
217  }
218 
219  count = GetRenderRowCount();
220  col = 0; // bitmap button is column 0 in render tab
221  for( row = 0; row < count; ++row )
222  {
223  COLOR_SWATCH* swatch = dynamic_cast<COLOR_SWATCH*>( getRenderComp( row, col ) );
224  if( swatch )
225  swatch->SetSwatchBackground( newColor );
226  }
227  }
228 
229  // tell the client code.
230  OnRenderColorChange( id, newColor );
231 
232  passOnFocus();
233 }
234 
235 
236 void LAYER_WIDGET::OnRenderCheckBox( wxCommandEvent& event )
237 {
238  wxCheckBox* eventSource = (wxCheckBox*) event.GetEventObject();
239  LAYER_NUM id = getDecodedId( eventSource->GetId() );
240  OnRenderEnable( id, eventSource->IsChecked() );
241  passOnFocus();
242 }
243 
244 
245 void LAYER_WIDGET::OnTabChange( wxNotebookEvent& event )
246 {
247 // wxFocusEvent event( wxEVT_SET_FOCUS );
248 // m_FocusOwner->AddPendingEvent( event );
249 
250  passOnFocus(); // does not work in this context, probably because we have receive control here too early.
251 }
252 
253 
254 wxWindow* LAYER_WIDGET::getLayerComp( int aRow, int aColumn ) const
255 {
256  unsigned ndx = aRow * LYR_COLUMN_COUNT + aColumn;
257 
258  if( ndx < m_LayersFlexGridSizer->GetChildren().GetCount() )
259  return m_LayersFlexGridSizer->GetChildren()[ndx]->GetWindow();
260 
261  return NULL;
262 }
263 
264 
266 {
267  int count = GetLayerRowCount();
268 
269  for( int row = 0; row < count; ++row )
270  {
271  // column 0 in the layer scroll window has a wxStaticBitmap, get its ID.
272  wxWindow* w = getLayerComp( row, 0 );
273  wxASSERT( w );
274 
275  if( aLayer == getDecodedId( w->GetId() ))
276  return row;
277  }
278 
279  return -1;
280 }
281 
282 
283 wxWindow* LAYER_WIDGET::getRenderComp( int aRow, int aColumn ) const
284 {
285  int ndx = aRow * RND_COLUMN_COUNT + aColumn;
286 
287  if( (unsigned) ndx < m_RenderFlexGridSizer->GetChildren().GetCount() )
288  return m_RenderFlexGridSizer->GetChildren()[ndx]->GetWindow();
289 
290  return NULL;
291 }
292 
293 
294 int LAYER_WIDGET::findRenderRow( int aId ) const
295 {
296  int count = GetRenderRowCount();
297 
298  for( int row = 0; row < count; ++row )
299  {
300  // column 0 in the layer scroll window has a wxStaticBitmap, get its ID.
301  wxWindow* w = getRenderComp( row, 0 );
302  wxASSERT( w );
303 
304  if( aId == getDecodedId( w->GetId() ))
305  return row;
306  }
307 
308  return -1;
309 }
310 
311 
312 void LAYER_WIDGET::insertLayerRow( int aRow, const ROW& aSpec )
313 {
314  wxASSERT( aRow >= 0 );
315 
316  int col;
317  int index = aRow * LYR_COLUMN_COUNT;
318  const int flags = wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT;
319 
320  // column 0
321  col = COLUMN_ICON_ACTIVE;
323  ROW_ICON_PROVIDER::STATE::OFF, encodeId( col, aSpec.id ) );
324  sbm->Bind( wxEVT_LEFT_DOWN, &LAYER_WIDGET::OnLeftDownLayers, this );
325  m_LayersFlexGridSizer->wxSizer::Insert( index+col, sbm, 0, flags );
326 
327  // column 1 (COLUMN_COLORBM)
328  col = COLUMN_COLORBM;
329 
330  auto bmb = new COLOR_SWATCH( m_LayerScrolledWindow, aSpec.color, encodeId( col, aSpec.id ),
332  bmb->Bind( wxEVT_LEFT_DOWN, &LAYER_WIDGET::OnLeftDownLayers, this );
333  bmb->Bind( COLOR_SWATCH_CHANGED, &LAYER_WIDGET::OnLayerSwatchChanged, this );
334  bmb->SetToolTip( _("Left double click or middle click for color change, right click for menu" ) );
335  m_LayersFlexGridSizer->wxSizer::Insert( index+col, bmb, 0, flags );
336 
337  // column 2 (COLUMN_COLOR_LYR_CB)
338  col = COLUMN_COLOR_LYR_CB;
339  wxCheckBox* cb = new wxCheckBox( m_LayerScrolledWindow, encodeId( col, aSpec.id ), wxEmptyString );
340  cb->SetValue( aSpec.state );
341  cb->Bind( wxEVT_COMMAND_CHECKBOX_CLICKED, &LAYER_WIDGET::OnLayerCheckBox, this );
342  cb->SetToolTip( _( "Enable this for visibility" ) );
343  m_LayersFlexGridSizer->wxSizer::Insert( index+col, cb, 0, flags );
344 
345  // column 3 (COLUMN_COLOR_LYRNAME)
346  col = COLUMN_COLOR_LYRNAME;
347  wxStaticText* st = new wxStaticText( m_LayerScrolledWindow, encodeId( col, aSpec.id ), aSpec.rowName );
348  shrinkFont( st, m_PointSize );
349  st->Bind( wxEVT_LEFT_DOWN, &LAYER_WIDGET::OnLeftDownLayers, this );
350  st->SetToolTip( aSpec.tooltip );
351  m_LayersFlexGridSizer->wxSizer::Insert( index+col, st, 0, flags );
352 
353  // column 4 (COLUMN_ALPHA_INDICATOR)
356  ROW_ICON_PROVIDER::STATE::OFF, wxID_ANY );
357  m_LayersFlexGridSizer->wxSizer::Insert( index+col, sbm, 0, flags );
358 
359  // Bind right click eventhandler to all columns
360  wxString layerName( aSpec.rowName );
361 
362  sbm->Bind( wxEVT_RIGHT_DOWN, [this, bmb, layerName] ( wxMouseEvent& aEvt ) {
363  OnRightDownLayer( aEvt, bmb, layerName );
364  } );
365  bmb->Bind( wxEVT_RIGHT_DOWN, [this, bmb, layerName] ( wxMouseEvent& aEvt ) {
366  OnRightDownLayer( aEvt, bmb, layerName );
367  } );
368  cb->Bind( wxEVT_RIGHT_DOWN, [this, bmb, layerName] ( wxMouseEvent& aEvt ) {
369  OnRightDownLayer( aEvt, bmb, layerName );
370  } );
371  st->Bind( wxEVT_RIGHT_DOWN, [this, bmb, layerName] ( wxMouseEvent& aEvt ) {
372  OnRightDownLayer( aEvt, bmb, layerName );
373  } );
374 }
375 
376 
377 void LAYER_WIDGET::insertRenderRow( int aRow, const ROW& aSpec )
378 {
379  wxASSERT( aRow >= 0 );
380 
381  int col;
382  int index = aRow * RND_COLUMN_COUNT;
383  const int flags = wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT;
384 
385  wxString renderName( aSpec.rowName );
386  wxCheckBox* cb = nullptr;
387 
388  // column 1
389  if( !aSpec.spacer )
390  {
391  col = 1;
392  cb = new wxCheckBox( m_RenderScrolledWindow, encodeId( col, aSpec.id ),
393  aSpec.rowName, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT );
394  shrinkFont( cb, m_PointSize );
395  cb->SetValue( aSpec.state );
396  cb->Enable( aSpec.changeable );
397  cb->Bind( wxEVT_COMMAND_CHECKBOX_CLICKED, &LAYER_WIDGET::OnRenderCheckBox, this );
398  cb->SetToolTip( aSpec.tooltip );
399  }
400 
401  // column 0
402  col = 0;
403  if( aSpec.color != COLOR4D::UNSPECIFIED )
404  {
405  auto bmb = new COLOR_SWATCH( m_RenderScrolledWindow, aSpec.color, encodeId( col, aSpec.id ),
407  bmb->Bind( COLOR_SWATCH_CHANGED, &LAYER_WIDGET::OnRenderSwatchChanged, this );
408  bmb->SetToolTip( _( "Left double click or middle click for color change" ) );
409  m_RenderFlexGridSizer->wxSizer::Insert( index+col, bmb, 0, flags );
410 
411  bmb->Bind( wxEVT_RIGHT_DOWN, [this, bmb, renderName] ( wxMouseEvent& aEvt ) {
412  OnRightDownRender( aEvt, bmb, renderName );
413  } );
414  cb->Bind( wxEVT_RIGHT_DOWN, [this, bmb, renderName] ( wxMouseEvent& aEvt ) {
415  OnRightDownRender( aEvt, bmb, renderName );
416  } );
417 
418  // could add a left click handler on the color button that toggles checkbox.
419  }
420  else // == -1, no color selection wanted
421  {
422  // need a place holder within the sizer to keep grid full.
423  wxPanel* invisible = new wxPanel( m_RenderScrolledWindow, encodeId( col, aSpec.id ) );
424  m_RenderFlexGridSizer->wxSizer::Insert( index+col, invisible, 0, flags );
425  }
426 
427  // Items have to be inserted in order
428  col = 1;
429 
430  if( aSpec.spacer )
431  {
432  wxPanel* invisible = new wxPanel( m_RenderScrolledWindow, wxID_ANY );
433  m_RenderFlexGridSizer->wxSizer::Insert( index+col, invisible, 0, flags );
434  }
435  else
436  {
437  m_RenderFlexGridSizer->wxSizer::Insert( index+col, cb, 0, flags );
438  }
439 }
440 
441 
443 {
444  m_FocusOwner->SetFocus();
445 }
446 
447 
448 //-----<public>-------------------------------------------------------
449 
450 LAYER_WIDGET::LAYER_WIDGET( wxWindow* aParent, wxWindow* aFocusOwner, int aPointSize,
451  wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) :
452  wxPanel( aParent, id, pos, size, style )
453 {
454  wxBoxSizer* boxSizer = new wxBoxSizer( wxVERTICAL );
455 
456  m_notebook = new wxAuiNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxAUI_NB_TOP );
457 
458  wxFont font = m_notebook->GetFont();
459 
460  if( aPointSize == -1 )
461  {
462  m_PointSize = font.GetPointSize();
463  }
464  else
465  {
466  m_PointSize = aPointSize;
467 
468  // change the font size on the notebook's tabs to match aPointSize
469  font.SetPointSize( aPointSize );
470  m_notebook->SetFont( font );
471  m_notebook->SetNormalFont( font );
472  m_notebook->SetSelectedFont( font );
473  m_notebook->SetMeasuringFont( font );
474  }
475 
476  int indicatorSize = ConvertDialogToPixels( wxSize( 6, 6 ) ).x;
477  m_IconProvider = new ROW_ICON_PROVIDER( indicatorSize );
478 
479  m_LayerPanel = new wxPanel( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
480 
481  wxBoxSizer* bSizer3;
482  bSizer3 = new wxBoxSizer( wxVERTICAL );
483 
484  m_LayerScrolledWindow = new wxScrolledWindow( m_LayerPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNO_BORDER );
485  m_LayerScrolledWindow->SetScrollRate( 5, 5 );
486  m_LayersFlexGridSizer = new wxFlexGridSizer( 0, LYR_COLUMN_COUNT, 0, 1 );
487  m_LayersFlexGridSizer->SetFlexibleDirection( wxHORIZONTAL );
488  m_LayersFlexGridSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_NONE );
489 
491  m_LayerScrolledWindow->Layout();
493  bSizer3->Add( m_LayerScrolledWindow, 1, wxBOTTOM|wxEXPAND|wxLEFT|wxTOP, 2 );
494 
495  m_LayerPanel->SetSizer( bSizer3 );
496  m_LayerPanel->Layout();
497  bSizer3->Fit( m_LayerPanel );
498  m_notebook->AddPage( m_LayerPanel, _( "Layers" ), true );
499  m_RenderingPanel = new wxPanel( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
500 
501  wxBoxSizer* bSizer4;
502  bSizer4 = new wxBoxSizer( wxVERTICAL );
503 
504  m_RenderScrolledWindow = new wxScrolledWindow( m_RenderingPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNO_BORDER );
505  m_RenderScrolledWindow->SetScrollRate( 5, 5 );
506  m_RenderFlexGridSizer = new wxFlexGridSizer( 0, RND_COLUMN_COUNT, 0, 1 );
507  m_RenderFlexGridSizer->SetFlexibleDirection( wxHORIZONTAL );
508  m_RenderFlexGridSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_NONE );
509 
511  m_RenderScrolledWindow->Layout();
513  bSizer4->Add( m_RenderScrolledWindow, 1, wxALL|wxEXPAND, 5 );
514 
515  m_RenderingPanel->SetSizer( bSizer4 );
516  m_RenderingPanel->Layout();
517  bSizer4->Fit( m_RenderingPanel );
518  m_notebook->AddPage( m_RenderingPanel, _( "Items" ), false );
519 
520  boxSizer->Add( m_notebook, 1, wxEXPAND | wxALL, 5 );
521 
522  SetSizer( boxSizer );
523 
524  m_FocusOwner = aFocusOwner;
525 
526  m_CurrentRow = -1; // hide the arrow initially
527 
528  // trap the tab changes so that we can call passOnFocus().
529  m_notebook->Bind( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, &LAYER_WIDGET::OnTabChange, this );
530 
531  Layout();
532 }
533 
534 
536 {
537  delete m_IconProvider;
538 }
539 
540 
542 {
543  // size of m_LayerScrolledWindow --------------
544  wxArrayInt widths = m_LayersFlexGridSizer->GetColWidths();
545  int totWidth = 0;
546 
547  if( widths.GetCount() )
548  {
549  for( int i = 0; i < LYR_COLUMN_COUNT; ++i )
550  {
551  totWidth += widths[i] + m_LayersFlexGridSizer->GetHGap();
552  // printf("widths[%d]:%d\n", i, widths[i] );
553  }
554  }
555 
556  // Account for the parent's frame:
557  totWidth += 32;
558 
559 
560  /* The minimum height is a small size to properly force computation
561  * of the panel's scrollbars (otherwise it will assume it *has* all
562  * this space) */
563  unsigned totHeight = 32;
564 
565  wxSize layerz( totWidth, totHeight );
566 
567  layerz += m_LayerPanel->GetWindowBorderSize();
568 
569 
570  // size of m_RenderScrolledWindow --------------
571  widths = m_RenderFlexGridSizer->GetColWidths();
572  totWidth = 0;
573 
574  if( widths.GetCount() )
575  {
576  for( int i = 0; i < RND_COLUMN_COUNT; ++i )
577  {
578  totWidth += widths[i] + m_RenderFlexGridSizer->GetHGap();
579  // printf("widths[%d]:%d\n", i, widths[i] );
580  }
581  }
582  // account for the parent's frame, this one has void space of 10 PLUS a border:
583  totWidth += 32;
584 
585  // For totHeight re-use the previous small one
586  wxSize renderz( totWidth, totHeight );
587 
588  renderz += m_RenderingPanel->GetWindowBorderSize();
589 
590  wxSize clientz( std::max(renderz.x,layerz.x), std::max(renderz.y,layerz.y) );
591 
592  return clientz;
593 }
594 
595 
597 {
598  int controlCount = m_LayersFlexGridSizer->GetChildren().GetCount();
599  return controlCount / LYR_COLUMN_COUNT;
600 }
601 
602 
604 {
605  int controlCount = m_RenderFlexGridSizer->GetChildren().GetCount();
606  return controlCount / RND_COLUMN_COUNT;
607 }
608 
609 
611 {
612  int nextRow = GetLayerRowCount();
613  insertLayerRow( nextRow, aRow );
614  UpdateLayouts();
615 }
616 
617 
619 {
620  m_LayersFlexGridSizer->Clear( true );
621 }
622 
623 
625 {
626  int nextRow = GetRenderRowCount();
627  insertRenderRow( nextRow, aRow );
628  UpdateLayouts();
629 }
630 
631 
633 {
634  m_RenderFlexGridSizer->Clear( true );
635 }
636 
637 
639 {
640  // enable the layer tab at index 0
641  m_notebook->SetSelection( 0 );
642 
643  INDICATOR_ICON* oldIndicator = (INDICATOR_ICON*) getLayerComp( m_CurrentRow, 0 );
644  if( oldIndicator )
645  {
647  oldIndicator->SetIndicatorState( ROW_ICON_PROVIDER::STATE::DIMMED );
648  else
650  }
651 
652  INDICATOR_ICON* newIndicator = (INDICATOR_ICON*) getLayerComp( aRow, 0 );
653  if( newIndicator )
654  {
656 
657  // Make sure the desired layer row is visible.
658  // It seems that as of 2.8.2, setting the focus does this.
659  // I don't expect the scrolling to be needed at all because
660  // the minimum window size may end up being established so that the
661  // scroll bars will not be visible.
662  getLayerComp( aRow, 1 )->SetFocus();
663  }
664 
665  m_CurrentRow = aRow;
666 
667  // give the focus back to the app.
668  passOnFocus();
669 }
670 
671 
673 {
674  int row = findLayerRow( aLayer );
675  SelectLayerRow( row );
676 }
677 
678 
680 {
681  wxWindow* w = getLayerComp( m_CurrentRow, 0 );
682  if( w )
683  return getDecodedId( w->GetId() );
684 
685  return UNDEFINED_LAYER;
686 }
687 
688 
689 void LAYER_WIDGET::SetLayerVisible( LAYER_NUM aLayer, bool isVisible )
690 {
691  int row = findLayerRow( aLayer );
692  if( row >= 0 )
693  {
694  wxCheckBox* cb = (wxCheckBox*) getLayerComp( row, COLUMN_COLOR_LYR_CB );
695  wxASSERT( cb );
696  cb->SetValue( isVisible ); // does not fire an event
697  }
698 }
699 
700 
702 {
703  int row = findLayerRow( aLayer );
704  if( row >= 0 )
705  {
706  wxCheckBox* cb = (wxCheckBox*) getLayerComp( row, COLUMN_COLOR_LYR_CB );
707  wxASSERT( cb );
708  return cb->GetValue();
709  }
710  return false;
711 }
712 
713 
715 {
716  int row = findLayerRow( aLayer );
717  if( row >= 0 )
718  {
719  int col = 1; // bitmap button is column 1
720  auto swatch = static_cast<COLOR_SWATCH*>( getLayerComp( row, col ) );
721  wxASSERT( swatch );
722 
723  swatch->SetSwatchColor( aColor, false );
724  }
725 }
726 
727 
729 {
730  int row = findLayerRow( aLayer );
731  if( row >= 0 )
732  {
733  int col = 1; // bitmap button is column 1
734  auto swatch = static_cast<COLOR_SWATCH*>( getLayerComp( row, col ) );
735  wxASSERT( swatch );
736 
737  return swatch->GetSwatchColor();
738  }
739 
740  return COLOR4D::UNSPECIFIED; // it's caller fault, gave me a bad layer
741 }
742 
743 
744 void LAYER_WIDGET::SetRenderState( int aId, bool isSet )
745 {
746  int row = findRenderRow( aId );
747 
748  if( row >= 0 )
749  {
750  int col = 1; // checkbox is column 1
751  wxCheckBox* cb = (wxCheckBox*) getRenderComp( row, col );
752  wxASSERT( cb );
753  cb->SetValue( isSet ); // does not fire an event
754  }
755 }
756 
757 
759 {
760  int row = findRenderRow( aId );
761 
762  if( row >= 0 )
763  {
764  int col = 1; // checkbox is column 1
765  wxCheckBox* cb = (wxCheckBox*) getRenderComp( row, col );
766  wxASSERT( cb );
767  return cb->GetValue();
768  }
769 
770  return false; // the value of a non-existent row
771 }
772 
773 
775 {
776  m_LayersFlexGridSizer->Layout();
777  m_RenderFlexGridSizer->Layout();
778  m_LayerPanel->Layout();
779  m_RenderingPanel->Layout();
780  FitInside();
781 }
782 
783 
785 {
786  int rowCount = GetLayerRowCount();
787 
788  for( int row = 0; row < rowCount ; row++ )
789  {
791 
792  if( indicator )
793  {
795 
796  if( row == m_CurrentRow )
798  else if( useAlternateBitmap( row ) )
799  state = ROW_ICON_PROVIDER::STATE::DIMMED;
800  else
802 
803  indicator->SetIndicatorState( state );
804  }
805  }
806 }
807 
808 
809 #if defined(STAND_ALONE)
810 
811 #include <wx/aui/aui.h>
812 
813 
820 class MYFRAME : public wxFrame
821 {
822  // example of how to derive from LAYER_WIDGET in order to provide the
823  // abstract methods.
824  class MYLAYERS : public LAYER_WIDGET
825  {
826  public:
827  // your constructor could take a BOARD argument. here I leave it
828  // out because this source module wants to know nothing of BOARDs
829  // to maximize re-use.
830  MYLAYERS( wxWindow* aParent ) :
831  LAYER_WIDGET( aParent, aParent )
832  {
833  }
834 
835  void OnLayerColorChange( int aLayer, COLOR4D aColor )
836  {
837  printf( "OnLayerColorChange( aLayer:%d, aColor:%d )\n", aLayer, aColor );
838 
839  /* a test trigger only
840  if( aLayer == 2 )
841  {
842  ClearLayerRows();
843  printf(" GetLayerRowCount(): %d\n", GetLayerRowCount() );
844  }
845  */
846  }
847 
848  bool OnLayerSelect( LAYER_NUM aLayer )
849  {
850  printf( "OnLayerSelect( aLayer:%d )\n", aLayer );
851  return true;
852  }
853 
854  void OnLayerVisible( LAYER_NUM aLayer, bool isVisible, bool isFinal )
855  {
856  printf( "OnLayerVisible( aLayer:%d, isVisible:%d isFinal:%d)\n", aLayer, isVisible, isFinal );
857  }
858 
859  void OnRenderColorChange( int aId, COLOR4D aColor )
860  {
861  printf( "OnRenderColorChange( aId:%d, aColor:%d )\n", aId, aColor );
862  }
863 
864  void OnRenderEnable( int aId, bool isEnabled )
865  {
866  printf( "OnRenderEnable( aId:%d, isEnabled:%d )\n", aId, isEnabled );
867  }
868  };
869 
870 
871 public:
872  MYFRAME( wxWindow * parent ) :
873  wxFrame( parent, -1, wxT( "wxAUI Test" ), wxDefaultPosition,
874  wxSize( 800, 600 ), wxDEFAULT_FRAME_STYLE )
875  {
876  // notify wxAUI which frame to use
877  m_mgr.SetManagedWindow( this );
878 
879  MYLAYERS* lw = new MYLAYERS( this );
880 
881  // add some layer rows
882  static const LAYER_WIDGET::ROW layerRows[] = {
883  LAYER_WIDGET::ROW( wxT("layer 1"), 0, RED, wxT("RED"), false ),
884  LAYER_WIDGET::ROW( wxT("layer 2"), 1, GREEN, wxT("GREEN"), true ),
885  LAYER_WIDGET::ROW( wxT("brown_layer"), 2, BROWN, wxT("BROWN"), true ),
886  LAYER_WIDGET::ROW( wxT("layer_4_you"), 3, BLUE, wxT("BLUE"), false ),
887  };
888 
889  lw->AppendLayerRows( layerRows, DIM(layerRows) );
890 
891  // add some render rows
892  static const LAYER_WIDGET::ROW renderRows[] = {
893  LAYER_WIDGET::ROW( wxT("With Very Large Ears"), 0, COLOR4D::UNSPECIFIED, wxT("Spock here") ),
894  LAYER_WIDGET::ROW( wxT("With Legs"), 1, YELLOW ),
895  LAYER_WIDGET::ROW( wxT("With Oval Eyes"), 1, BROWN, wxT("My eyes are upon you") ),
896  };
897 
898  lw->AppendRenderRows( renderRows, DIM(renderRows) );
899 
900  lw->SelectLayerRow( 1 );
901 
902  wxAuiPaneInfo li;
903  li.MinSize( lw->GetBestSize() );
904  li.BestSize( lw->GetBestSize() );
905  li.Left();
906 // li.MaximizeButton( true );
907 // li.MinimizeButton( true );
908  li.CloseButton( false );
909  li.Caption( wxT( "Layers" ) );
910  m_mgr.AddPane( lw, li );
911 
912 
913  wxTextCtrl* text2 = new wxTextCtrl( this, -1, wxT( "Pane 2 - sample text" ),
914  wxDefaultPosition, wxSize( 200, 150 ),
915  wxNO_BORDER | wxTE_MULTILINE );
916  m_mgr.AddPane( text2, wxBOTTOM, wxT( "Pane Number Two" ) );
917 
918  wxTextCtrl* text3 = new wxTextCtrl( this, -1, wxT( "Main content window" ),
919  wxDefaultPosition, wxSize( 200, 150 ),
920  wxNO_BORDER | wxTE_MULTILINE );
921  m_mgr.AddPane( text3, wxCENTER );
922 
923  // tell the manager to "commit" all the changes just made
924  m_mgr.Update();
925  }
926 
927  ~MYFRAME()
928  {
929  // deinitialize the frame manager
930  m_mgr.UnInit();
931  }
932 
933 private:
934  wxAuiManager m_mgr;
935 };
936 
937 
938 // our normal wxApp-derived class, as usual
939 class MyApp : public wxApp
940 {
941 public:
942 
943  bool OnInit()
944  {
945  wxFrame* frame = new MYFRAME( NULL );
946 
947  SetTopWindow( frame );
948  frame->Show();
949  return true;
950  }
951 };
952 
953 DECLARE_APP( MyApp );
954 IMPLEMENT_APP( MyApp );
955 
956 #endif // STAND_ALONE
Definition: colors.h:57
#define COLUMN_COLOR_LYRNAME
Definition: layer_widget.h:55
#define DIM(x)
of elements in an array
Definition: macros.h:98
void OnLeftDownLayers(wxMouseEvent &event)
void SetIndicatorState(ICON_ID aIconId)
Sets the row indiciator to the given state.
wxAuiNotebook * m_notebook
Definition: layer_widget.h:121
#define LYR_COLUMN_COUNT
Layer tab column count.
Definition: layer_widget.h:49
int m_CurrentRow
selected row of layer list
Definition: layer_widget.h:130
void insertRenderRow(int aRow, const ROW &aSpec)
Icon provider for the "standard" row indicators, for example in layer selection lists.
Struct ROW provides all the data needed to add a row to a LAYER_WIDGET.
Definition: layer_widget.h:87
#define COLUMN_ALPHA_INDICATOR
Definition: layer_widget.h:56
int findRenderRow(int aId) const
bool spacer
if true, this row is a spacer
Definition: layer_widget.h:95
virtual void OnRenderColorChange(int aId, COLOR4D aColor)=0
Function OnRenderColorChange is called to notify client code whenever the user changes a rendering co...
wxMenuItem * AddMenuItem(wxMenu *aMenu, int aId, const wxString &aText, const wxBitmap &aImage, wxItemKind aType=wxITEM_NORMAL)
Function AddMenuItem is an inline helper function to create and insert a menu item with an icon into ...
Definition: bitmap.cpp:174
bool GetRenderState(int aId)
Function GetRenderState returns the state of the checkbox associated with aId.
void UpdateLayouts()
virtual void OnLayerVisible(LAYER_NUM aLayer, bool isVisible, bool isFinal=true)=0
Function OnLayerVisible is called to notify client code about a layer visibility change.
void OnTabChange(wxNotebookEvent &event)
bool changeable
if true, the state can be changed
Definition: layer_widget.h:94
static const wxEventType EVT_LAYER_COLOR_CHANGE
Definition: layer_widget.h:117
COLOR4D GetLayerColor(LAYER_NUM aLayer) const
Function GetLayerColor returns the color of the layer ROW associated with aLayer id.
#define OFF
wxScrolledWindow * m_RenderScrolledWindow
Definition: layer_widget.h:126
wxFlexGridSizer * m_LayersFlexGridSizer
Definition: layer_widget.h:124
virtual bool useAlternateBitmap(int aRow)
Virtual Function useAlternateBitmap.
Definition: layer_widget.h:143
void SetSwatchBackground(KIGFX::COLOR4D aBackground)
Set the swatch background color.
int findLayerRow(LAYER_NUM aLayer) const
Function findLayerRow returns the row index that aLayer resides in, or -1 if not found.
static void shrinkFont(wxWindow *aControl, int aPointSize)
Function shrinkFont reduces the size of the wxFont associated with aControl.
wxSize GetBestSize() const
Function GetBestSize returns the preferred minimum size, taking into consideration the dynamic conten...
void ClearRenderRows()
Function ClearRenderRows empties out the render rows.
#define RND_COLUMN_COUNT
Rendering tab column count.
Definition: layer_widget.h:50
wxFlexGridSizer * m_RenderFlexGridSizer
Definition: layer_widget.h:127
bool state
initial wxCheckBox state
Definition: layer_widget.h:92
void ClearLayerRows()
Function ClearLayerRows empties out the layer rows.
wxString tooltip
if not empty, use this tooltip on row
Definition: layer_widget.h:93
This file contains miscellaneous commonly used macros and functions.
virtual void OnLayerColorChange(int aLayer, COLOR4D aColor)=0
Function OnLayerColorChange is called to notify client code about a layer color change.
void OnRenderCheckBox(wxCommandEvent &event)
void OnLayerCheckBox(wxCommandEvent &event)
Function OnLayerCheckBox handles the "is layer visible" checkbox and propogates the event to the clie...
void AppendRenderRow(const ROW &aRow)
Function AppendRenderRow appends a new row in the render portion of the widget.
wxBitmap KiBitmap(BITMAP_DEF aBitmap)
Function KiBitmap constructs a wxBitmap from a memory record, held in a BITMAP_DEF.
Definition: bitmap.cpp:78
static int encodeId(int aColumn, int aId)
Function encodeId is here to allow saving a layer index within a control as its wxControl id...
COLOR4D color
COLOR4D::UNSPECIFIED if none.
Definition: layer_widget.h:91
void OnRightDownRender(wxMouseEvent &aEvent, COLOR_SWATCH *aColorSwatch, const wxString &aRenderName)
Function OnRightDownRender Called when user right-clicks a render option.
Class representing a row indicator icon for use in places like the layer widget.
#define COLUMN_ICON_ACTIVE
Definition: layer_widget.h:52
int GetRenderRowCount() const
Function GetRenderRowCount returns the number of rows in the render tab.
#define COLUMN_COLORBM
Definition: layer_widget.h:53
void SetLayerColor(LAYER_NUM aLayer, COLOR4D aColor)
Function SetLayerColor changes the color of aLayer.
virtual bool AreArbitraryColorsAllowed()
Subclasses can override this to provide logic for allowing arbitrary color selection via wxColourPick...
Definition: layer_widget.h:149
wxPanel * m_RenderingPanel
Definition: layer_widget.h:125
void AppendLayerRow(const ROW &aRow)
Function AppendLayerRow appends a new row in the layer portion of the widget.
void UpdateLayerIcons()
Function UpdateLayerIcons Update all layer manager icons (layers only) Useful when loading a file or ...
wxScrolledWindow * m_LayerScrolledWindow
Definition: layer_widget.h:123
virtual void OnRenderEnable(int aId, bool isEnabled)=0
Function OnRenderEnable is called to notify client code whenever the user changes an rendering enable...
wxWindow * getLayerComp(int aRow, int aColumn) const
Function getLayerComp returns the component within the m_LayersFlexGridSizer at aRow and aCol or NULL...
Definition: colors.h:60
int GetLayerRowCount() const
Function GetLayerRowCount returns the number of rows in the layer tab.
void SelectLayerRow(int aRow)
Function SelectLayerRow changes the row selection in the layer list to the given row.
void OnRenderSwatchChanged(wxCommandEvent &aEvent)
Function OnRenderSwatchChanged Called when user has changed the swatch color of a render entry...
static LAYER_NUM getDecodedId(int aControlId)
Function getDecodedId decodes aControlId to original un-encoded value.
virtual ~LAYER_WIDGET()
wxWindow * m_FocusOwner
Definition: layer_widget.h:129
int LAYER_NUM
Type LAYER_NUM can be replaced with int and removed.
void passOnFocus()
Function passOnFocus gives away the keyboard focus up to the main parent window.
LAYER_NUM GetSelectedLayer()
Function GetSelectedLayer returns the selected layer or -1 if none.
bool IsLayerVisible(LAYER_NUM aLayer)
Function IsLayerVisible returns the visible state of the layer ROW associated with aLayer id...
Class LAYER_WIDGET is abstract and is used to manage a list of layers, with the notion of a "current"...
Definition: layer_widget.h:79
Definition: colors.h:58
void OnRightDownLayer(wxMouseEvent &event, COLOR_SWATCH *aColorSwatch, const wxString &aLayerName)
Function OnRightDownLayer Called when user right-clicks a layer.
#define COLUMN_COLOR_LYR_CB
Definition: layer_widget.h:54
#define max(a, b)
Definition: auxiliary.h:86
wxString rowName
the prompt or layername
Definition: layer_widget.h:89
virtual COLOR4D getBackgroundLayerColor()
Subclasses can override this to provide accurate representation of transparent colour swatches...
Definition: layer_widget.h:155
Class representing a simple color swatch, of the kind used to set layer colors.
Definition: color_swatch.h:38
The common library.
virtual void OnLayerRightClick(wxMenu &aMenu)=0
Function OnLayerRightClick is called to notify client code about a layer being right-clicked.
STATE
State constants to select the right icons
void GetNewSwatchColor()
Prompt for a new colour, using the colour picker dialog.
void insertLayerRow(int aRow, const ROW &aSpec)
Function insertLayerRow appends or inserts a new row in the layer portion of the widget.
#define ON
void SetLayerVisible(LAYER_NUM aLayer, bool isVisible)
Function SetLayerVisible sets aLayer visible or not.
void OnLayerSwatchChanged(wxCommandEvent &aEvent)
Function OnSwatchChanged() is called when a user changes a swatch color.
virtual bool OnLayerSelect(int aLayer)=0
Function OnLayerSelect is called to notify client code whenever the user selects a different layer...
void SetRenderState(int aId, bool isSet)
Function SetRenderState sets the state of the checkbox associated with aId within the Render tab grou...
Definition: colors.h:68
void SelectLayer(LAYER_NUM aLayer)
Function SelectLayer changes the row selection in the layer list to aLayer provided.
int id
either a layer or "visible element" id
Definition: layer_widget.h:90
ROW_ICON_PROVIDER * m_IconProvider
Definition: layer_widget.h:133
wxPanel * m_LayerPanel
Definition: layer_widget.h:122
LAYER_WIDGET(wxWindow *aParent, wxWindow *aFocusOwner, int aPointSize=-1, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxTAB_TRAVERSAL)
Constructor.
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39
wxWindow * getRenderComp(int aRow, int aColumn) const
Definition: colors.h:62