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 <[email protected]>
6 * Copyright (C) 2010-2022 KiCad Developers, see AUTHORS.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 <bitmaps.h>
39#include <macros.h>
40#include <menus_helpers.h>
43#include <wx/checkbox.h>
44
45#include <algorithm>
46
47
48const wxEventType LAYER_WIDGET::EVT_LAYER_COLOR_CHANGE = wxNewEventType();
49
50
54static void shrinkFont( wxWindow* aControl, int aPointSize )
55{
56 wxFont font = aControl->GetFont();
57 font.SetPointSize( aPointSize );
58 aControl->SetFont( font ); // need this?
59}
60
61
62int LAYER_WIDGET::encodeId( int aColumn, int aId )
63{
64 int id = aId * LYR_COLUMN_COUNT + aColumn;
65 return id;
66}
67
68
69int LAYER_WIDGET::getDecodedId( int aControlId )
70{
71 int id = aControlId / LYR_COLUMN_COUNT; // rounding is OK.
72 return id;
73}
74
75
76void LAYER_WIDGET::OnLeftDownLayers( wxMouseEvent& event )
77{
78 int row;
79 int layer;
80
81 wxWindow* eventSource = (wxWindow*) event.GetEventObject();
82
83 // if mouse event is coming from the m_LayerScrolledWindow and not one
84 // of its children, we have to find the row manually based on y coord.
85 if( eventSource == m_LayerScrolledWindow )
86 {
87 int y = event.GetY();
88
89 wxArrayInt heights = m_LayersFlexGridSizer->GetRowHeights();
90
91 int height = 0;
92
93 int rowCount = GetLayerRowCount();
94
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 else
109 {
110 // all nested controls on a given row will have their ID encoded with
111 // encodeId(), and the corresponding decoding is getDecodedId()
112 int id = eventSource->GetId();
113 layer = getDecodedId( id );
114 row = findLayerRow( layer );
115 }
116
117 if( OnLayerSelect( layer ) ) // if client allows this change.
118 SelectLayerRow( row );
119
120 passOnFocus();
121}
122
123
124void LAYER_WIDGET::OnRightDownLayer( wxMouseEvent& aEvent, COLOR_SWATCH* aColorSwatch,
125 const wxString& aLayerName )
126{
127 wxMenu menu;
128
130 _( "Change Layer Color for" ) + wxS( " " ) + aLayerName,
132 menu.AppendSeparator();
133
134 OnLayerRightClick( menu );
135
136 menu.Bind( wxEVT_COMMAND_MENU_SELECTED, [aColorSwatch]( wxCommandEvent& event )
137 {
138 if( event.GetId() == ID_CHANGE_LAYER_COLOR )
139 {
140 aColorSwatch->GetNewSwatchColor();
141 }
142 else
143 {
144 event.Skip();
145 }
146 } );
147
148 PopupMenu( &menu );
149 passOnFocus();
150}
151
152
153void LAYER_WIDGET::OnLayerSwatchChanged( wxCommandEvent& aEvent )
154{
155 COLOR_SWATCH* eventSource = static_cast<COLOR_SWATCH*>( aEvent.GetEventObject() );
156 COLOR4D newColor = eventSource->GetSwatchColor();
157 int layer = getDecodedId( eventSource->GetId() );
158
159 // tell the client code.
160 OnLayerColorChange( layer, newColor );
161
162 // notify others
163 wxCommandEvent event( EVT_LAYER_COLOR_CHANGE );
164 wxPostEvent( this, event );
165
166 passOnFocus();
167}
168
169
170void LAYER_WIDGET::OnLayerCheckBox( wxCommandEvent& event )
171{
172 wxCheckBox* eventSource = (wxCheckBox*) event.GetEventObject();
173 int layer = getDecodedId( eventSource->GetId() );
174
175 OnLayerVisible( layer, eventSource->IsChecked() );
176 passOnFocus();
177}
178
179
180void LAYER_WIDGET::OnRightDownRender( wxMouseEvent& aEvent, COLOR_SWATCH* aColorSwatch,
181 const wxString& aRenderName )
182{
183 wxMenu menu;
184
186 _( "Change Render Color for" ) + wxS( " " )+ aRenderName,
188
189 menu.Bind( wxEVT_COMMAND_MENU_SELECTED,
190 [aColorSwatch]( wxCommandEvent& event )
191 {
192 if( event.GetId() == ID_CHANGE_RENDER_COLOR )
193 aColorSwatch->GetNewSwatchColor();
194 else
195 event.Skip();
196 } );
197
198 PopupMenu( &menu );
199 passOnFocus();
200}
201
202
203void LAYER_WIDGET::OnRenderSwatchChanged( wxCommandEvent& aEvent )
204{
205 COLOR_SWATCH* eventSource = static_cast<COLOR_SWATCH*>( aEvent.GetEventObject() );
206 COLOR4D newColor = eventSource->GetSwatchColor();
207 int id = getDecodedId( eventSource->GetId() );
208
209 if( id == LAYER_PCB_BACKGROUND )
210 {
211 // Update all swatch backgrounds
212 int col = 1; // bitmap button is column 1 in layers tab
213
214 for( int row = 0; row < GetLayerRowCount(); ++row )
215 {
216 COLOR_SWATCH* swatch = dynamic_cast<COLOR_SWATCH*>( getLayerComp( row, col ) );
217
218 if( swatch )
219 swatch->SetSwatchBackground( newColor );
220 }
221
222 col = 0; // bitmap button is column 0 in render tab
223
224 for( int row = 0; row < GetRenderRowCount(); ++row )
225 {
226 COLOR_SWATCH* swatch = dynamic_cast<COLOR_SWATCH*>( getRenderComp( row, col ) );
227
228 if( swatch )
229 swatch->SetSwatchBackground( newColor );
230 }
231 }
232
233 // tell the client code.
234 OnRenderColorChange( id, newColor );
235
236 passOnFocus();
237}
238
239
240void LAYER_WIDGET::OnRenderCheckBox( wxCommandEvent& event )
241{
242 wxCheckBox* eventSource = (wxCheckBox*) event.GetEventObject();
243 int id = getDecodedId( eventSource->GetId() );
244
245 OnRenderEnable( id, eventSource->IsChecked() );
246 passOnFocus();
247}
248
249
250void LAYER_WIDGET::OnTabChange( wxNotebookEvent& event )
251{
252// wxFocusEvent event( wxEVT_SET_FOCUS );
253// m_FocusOwner->AddPendingEvent( event );
254
255 // Does not work in this context, probably because we have receive control here too early.
256 passOnFocus();
257}
258
259
260wxWindow* LAYER_WIDGET::getLayerComp( int aRow, int aColumn ) const
261{
262 unsigned ndx = aRow * LYR_COLUMN_COUNT + aColumn;
263
264 if( ndx < m_LayersFlexGridSizer->GetChildren().GetCount() )
265 return m_LayersFlexGridSizer->GetChildren()[ndx]->GetWindow();
266
267 return nullptr;
268}
269
270
271int LAYER_WIDGET::findLayerRow( int aLayer ) const
272{
273 int count = GetLayerRowCount();
274
275 for( int row = 0; row < count; ++row )
276 {
277 // column 0 in the layer scroll window has a wxStaticBitmap, get its ID.
278 wxWindow* w = getLayerComp( row, 0 );
279 wxASSERT( w );
280
281 if( aLayer == getDecodedId( w->GetId() ) )
282 return row;
283 }
284
285 return -1;
286}
287
288
289wxWindow* LAYER_WIDGET::getRenderComp( int aRow, int aColumn ) const
290{
291 int ndx = aRow * RND_COLUMN_COUNT + aColumn;
292
293 if( (unsigned) ndx < m_RenderFlexGridSizer->GetChildren().GetCount() )
294 return m_RenderFlexGridSizer->GetChildren()[ndx]->GetWindow();
295
296 return nullptr;
297}
298
299
300int LAYER_WIDGET::findRenderRow( int aId ) const
301{
302 int count = GetRenderRowCount();
303
304 for( int row = 0; row < count; ++row )
305 {
306 // column 0 in the layer scroll window has a wxStaticBitmap, get its ID.
307 wxWindow* w = getRenderComp( row, 0 );
308 wxASSERT( w );
309
310 if( aId == getDecodedId( w->GetId() ) )
311 return row;
312 }
313
314 return -1;
315}
316
317
318void LAYER_WIDGET::insertLayerRow( int aRow, const ROW& aSpec )
319{
320 wxASSERT( aRow >= 0 );
321
322 int col;
323 int index = aRow * LYR_COLUMN_COUNT;
324 const int flags = wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT;
325
326 // column 0
327 col = COLUMN_ICON_ACTIVE;
329 ROW_ICON_PROVIDER::STATE::OFF, encodeId( col, aSpec.id ) );
330 sbm->Bind( wxEVT_LEFT_DOWN, &LAYER_WIDGET::OnLeftDownLayers, this );
331 m_LayersFlexGridSizer->wxSizer::Insert( index+col, sbm, 0, flags );
332
333 // column 1 (COLUMN_COLORBM)
334 col = COLUMN_COLORBM;
335
336 auto bmb = new COLOR_SWATCH( m_LayerScrolledWindow, aSpec.color, encodeId( col, aSpec.id ),
338 bmb->Bind( wxEVT_LEFT_DOWN, &LAYER_WIDGET::OnLeftDownLayers, this );
339 bmb->Bind( COLOR_SWATCH_CHANGED, &LAYER_WIDGET::OnLayerSwatchChanged, this );
340 bmb->SetToolTip( _( "Left double click or middle click for color change, right click for "
341 "menu" ) );
342 m_LayersFlexGridSizer->wxSizer::Insert( index+col, bmb, 0, flags );
343
344 // column 2 (COLUMN_COLOR_LYR_CB)
346 wxCheckBox* cb = new wxCheckBox( m_LayerScrolledWindow, encodeId( col, aSpec.id ),
347 wxEmptyString );
348 cb->SetValue( aSpec.state );
349 cb->Bind( wxEVT_COMMAND_CHECKBOX_CLICKED, &LAYER_WIDGET::OnLayerCheckBox, this );
350 cb->SetToolTip( _( "Enable this for visibility" ) );
351 m_LayersFlexGridSizer->wxSizer::Insert( index+col, cb, 0, flags );
352
353 // column 3 (COLUMN_COLOR_LYRNAME)
356 encodeId( col, aSpec.id ),
357 aSpec.rowName, wxDefaultPosition,
358 wxDefaultSize,
359 wxST_ELLIPSIZE_MIDDLE );
360 shrinkFont( st, m_PointSize );
361 st->Bind( wxEVT_LEFT_DOWN, &LAYER_WIDGET::OnLeftDownLayers, this );
362 st->SetToolTip( aSpec.tooltip );
364 m_LayersFlexGridSizer->wxSizer::Insert( index+col, st, 0, flags | wxEXPAND );
365
366 // column 4 (COLUMN_ALPHA_INDICATOR)
369 ROW_ICON_PROVIDER::STATE::OFF, wxID_ANY );
370 m_LayersFlexGridSizer->wxSizer::Insert( index+col, sbm, 0, flags );
371
372 // Bind right click eventhandler to all columns
373 wxString layerName( aSpec.rowName );
374
375 sbm->Bind( wxEVT_RIGHT_DOWN, [this, bmb, layerName] ( wxMouseEvent& aEvt )
376 {
377 OnRightDownLayer( aEvt, bmb, layerName );
378 } );
379 bmb->Bind( wxEVT_RIGHT_DOWN, [this, bmb, layerName] ( wxMouseEvent& aEvt )
380 {
381 OnRightDownLayer( aEvt, bmb, layerName );
382 } );
383 cb->Bind( wxEVT_RIGHT_DOWN, [this, bmb, layerName] ( wxMouseEvent& aEvt )
384 {
385 OnRightDownLayer( aEvt, bmb, layerName );
386 } );
387 st->Bind( wxEVT_RIGHT_DOWN, [this, bmb, layerName] ( wxMouseEvent& aEvt )
388 {
389 OnRightDownLayer( aEvt, bmb, layerName );
390 } );
391}
392
393
394void LAYER_WIDGET::updateLayerRow( int aRow, const wxString& aName )
395{
396 wxStaticText* label = dynamic_cast<wxStaticText*>( getLayerComp( aRow, COLUMN_COLOR_LYRNAME ) );
397
398 if( label )
399 label->SetLabel( aName );
400
401 INDICATOR_ICON* indicator = (INDICATOR_ICON*) getLayerComp( aRow, 0 );
402
403 if( indicator )
404 {
405 if( aRow == m_CurrentRow )
407 else
408 indicator->SetIndicatorState( ROW_ICON_PROVIDER::STATE::OFF );
409 }
410}
411
412
413void LAYER_WIDGET::insertRenderRow( int aRow, const ROW& aSpec )
414{
415 wxASSERT( aRow >= 0 );
416
417 int col;
418 int index = aRow * RND_COLUMN_COUNT;
419 const int flags = wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT;
420
421 wxString renderName( aSpec.rowName );
422 wxCheckBox* cb = nullptr;
423
424 // column 1
425 if( !aSpec.spacer )
426 {
427 col = 1;
428 cb = new wxCheckBox( m_RenderScrolledWindow, encodeId( col, aSpec.id ),
429 aSpec.rowName, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT );
430 shrinkFont( cb, m_PointSize );
431 cb->SetValue( aSpec.state );
432 cb->Enable( aSpec.changeable );
433 cb->Bind( wxEVT_COMMAND_CHECKBOX_CLICKED, &LAYER_WIDGET::OnRenderCheckBox, this );
434 cb->SetToolTip( aSpec.tooltip );
435 }
436
437 // column 0
438 col = 0;
439
440 if( aSpec.color != COLOR4D::UNSPECIFIED )
441 {
442 auto bmb = new COLOR_SWATCH( m_RenderScrolledWindow, aSpec.color, encodeId( col, aSpec.id ),
444 bmb->Bind( COLOR_SWATCH_CHANGED, &LAYER_WIDGET::OnRenderSwatchChanged, this );
445 bmb->SetToolTip( _( "Left double click or middle click for color change" ) );
446 m_RenderFlexGridSizer->wxSizer::Insert( index+col, bmb, 0, flags );
447
448 bmb->Bind( wxEVT_RIGHT_DOWN, [this, bmb, renderName] ( wxMouseEvent& aEvt ) {
449 OnRightDownRender( aEvt, bmb, renderName );
450 } );
451 cb->Bind( wxEVT_RIGHT_DOWN, [this, bmb, renderName] ( wxMouseEvent& aEvt ) {
452 OnRightDownRender( aEvt, bmb, renderName );
453 } );
454
455 // could add a left click handler on the color button that toggles checkbox.
456 }
457 else // == -1, no color selection wanted
458 {
459 // need a place holder within the sizer to keep grid full.
460 wxPanel* invisible = new wxPanel( m_RenderScrolledWindow, encodeId( col, aSpec.id ) );
461 m_RenderFlexGridSizer->wxSizer::Insert( index+col, invisible, 0, flags );
462 }
463
464 // Items have to be inserted in order
465 col = 1;
466
467 if( aSpec.spacer )
468 {
469 wxPanel* invisible = new wxPanel( m_RenderScrolledWindow, wxID_ANY );
470 m_RenderFlexGridSizer->wxSizer::Insert( index+col, invisible, 0, flags );
471 }
472 else
473 {
474 m_RenderFlexGridSizer->wxSizer::Insert( index+col, cb, 0, flags );
475 }
476}
477
478
480{
481 m_FocusOwner->SetFocus();
482}
483
484
485LAYER_WIDGET::LAYER_WIDGET( wxWindow* aParent, wxWindow* aFocusOwner, wxWindowID id,
486 const wxPoint& pos, const wxSize& size, long style ) :
487 wxPanel( aParent, id, pos, size, style ),
488 m_smallestLayerString( wxT( "M...M" ) )
489{
490 int indicatorSize = ConvertDialogToPixels( wxSize( 6, 6 ) ).x;
491 m_IconProvider = new ROW_ICON_PROVIDER( indicatorSize );
492
493 int pointSize = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT ).GetPointSize();
494 int screenHeight = wxSystemSettings::GetMetric( wxSYS_SCREEN_Y );
495
496 if( screenHeight <= 900 && pointSize >= indicatorSize )
497 pointSize = pointSize * 8 / 10;
498
499 m_PointSize = pointSize;
500
501 wxBoxSizer* mainSizer = new wxBoxSizer( wxVERTICAL );
502
503 m_notebook = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP );
504
505 wxFont font = m_notebook->GetFont();
506
507 // change the font size on the notebook's tabs to match aPointSize
508 font.SetPointSize( pointSize );
509 m_notebook->SetFont( font );
510
511 m_LayerPanel = new wxPanel( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize,
512 wxTAB_TRAVERSAL );
513
514 wxBoxSizer* layerPanelSizer;
515 layerPanelSizer = new wxBoxSizer( wxVERTICAL );
516
517 m_LayerScrolledWindow = new wxScrolledWindow( m_LayerPanel, wxID_ANY, wxDefaultPosition,
518 wxDefaultSize, wxNO_BORDER );
519 m_LayerScrolledWindow->SetScrollRate( 5, 5 );
520 m_LayersFlexGridSizer = new wxFlexGridSizer( 0, LYR_COLUMN_COUNT, 0, 1 );
521 m_LayersFlexGridSizer->SetFlexibleDirection( wxHORIZONTAL );
522 m_LayersFlexGridSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_NONE );
523
524 // Make column 3 growable/stretchable
525 m_LayersFlexGridSizer->AddGrowableCol( 3, 1 );
526
528 m_LayerScrolledWindow->Layout();
530 layerPanelSizer->Add( m_LayerScrolledWindow, 1, wxBOTTOM | wxEXPAND | wxLEFT | wxTOP, 2 );
531
532 m_LayerPanel->SetSizer( layerPanelSizer );
533 m_LayerPanel->Layout();
534 layerPanelSizer->Fit( m_LayerPanel );
535 m_notebook->AddPage( m_LayerPanel, _( "Layers" ), true );
536 m_RenderingPanel = new wxPanel( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize,
537 wxTAB_TRAVERSAL );
538
539 wxBoxSizer* renderPanelSizer;
540 renderPanelSizer = new wxBoxSizer( wxVERTICAL );
541
542 m_RenderScrolledWindow = new wxScrolledWindow( m_RenderingPanel, wxID_ANY, wxDefaultPosition,
543 wxDefaultSize, wxNO_BORDER );
544 m_RenderScrolledWindow->SetScrollRate( 5, 5 );
545 m_RenderFlexGridSizer = new wxFlexGridSizer( 0, RND_COLUMN_COUNT, 0, 1 );
546 m_RenderFlexGridSizer->SetFlexibleDirection( wxHORIZONTAL );
547 m_RenderFlexGridSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_NONE );
548
550 m_RenderScrolledWindow->Layout();
552 renderPanelSizer->Add( m_RenderScrolledWindow, 1, wxALL | wxEXPAND, 5 );
553
554 m_RenderingPanel->SetSizer( renderPanelSizer );
555 m_RenderingPanel->Layout();
556 renderPanelSizer->Fit( m_RenderingPanel );
557 m_notebook->AddPage( m_RenderingPanel, _( "Items" ), false );
558
559 mainSizer->Add( m_notebook, 1, wxEXPAND, 5 );
560
561 SetSizer( mainSizer );
562
563 m_FocusOwner = aFocusOwner;
564
565 m_CurrentRow = -1; // hide the arrow initially
566
567 // trap the tab changes so that we can call passOnFocus().
568 m_notebook->Bind( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, &LAYER_WIDGET::OnTabChange, this );
569
570 Layout();
571}
572
573
575{
576 delete m_IconProvider;
577}
578
579
581{
582 // size of m_LayerScrolledWindow --------------
583 wxArrayInt widths = m_LayersFlexGridSizer->GetColWidths();
584 int totWidth = 0;
585
586 if( widths.GetCount() )
587 {
588 for( int i = 0; i < LYR_COLUMN_COUNT; ++i )
589 {
590 totWidth += widths[i] + m_LayersFlexGridSizer->GetHGap();
591 }
592 }
593
594 // Account for the parent's frame:
595 totWidth += 15;
596
597 /* The minimum height is a small size to properly force computation
598 * of the panel's scrollbars (otherwise it will assume it *has* all
599 * this space) */
600 unsigned totHeight = 32;
601
602 wxSize layerz( totWidth, totHeight );
603
604 layerz += m_LayerPanel->GetWindowBorderSize();
605
606 // size of m_RenderScrolledWindow --------------
607 widths = m_RenderFlexGridSizer->GetColWidths();
608 totWidth = 0;
609
610 if( widths.GetCount() )
611 {
612 for( int i = 0; i < RND_COLUMN_COUNT; ++i )
613 {
614 totWidth += widths[i] + m_RenderFlexGridSizer->GetHGap();
615 }
616 }
617
618 // account for the parent's frame, this one has void space of 10 PLUS a border:
619 totWidth += 15;
620
621 // For totHeight re-use the previous small one
622 wxSize renderz( totWidth, totHeight );
623
624 renderz += m_RenderingPanel->GetWindowBorderSize();
625
626 wxSize clientz( std::max(renderz.x,layerz.x), std::max(renderz.y,layerz.y) );
627
628 return clientz;
629}
630
631
633{
634 int controlCount = m_LayersFlexGridSizer->GetChildren().GetCount();
635 return controlCount / LYR_COLUMN_COUNT;
636}
637
638
640{
641 int controlCount = m_RenderFlexGridSizer->GetChildren().GetCount();
642 return controlCount / RND_COLUMN_COUNT;
643}
644
645
647{
648 int nextRow = GetLayerRowCount();
649 insertLayerRow( nextRow, aRow );
650}
651
652
654{
655 m_LayersFlexGridSizer->Clear( true );
656}
657
658
660{
661 int nextRow = GetRenderRowCount();
662 insertRenderRow( nextRow, aRow );
663}
664
665
667{
668 m_RenderFlexGridSizer->Clear( true );
669}
670
671
673{
675
676 if( oldIndicator )
677 oldIndicator->SetIndicatorState( ROW_ICON_PROVIDER::STATE::OFF );
678
679 INDICATOR_ICON* newIndicator = (INDICATOR_ICON*) getLayerComp( aRow, 0 );
680
681 if( newIndicator )
682 {
684 }
685
686 m_CurrentRow = aRow;
687
688 // give the focus back to the app.
689 passOnFocus();
690}
691
692
694{
695 int row = findLayerRow( aLayer );
696 SelectLayerRow( row );
697}
698
699
701{
702 wxWindow* w = getLayerComp( m_CurrentRow, 0 );
703
704 if( w )
705 return getDecodedId( w->GetId() );
706
707 return UNDEFINED_LAYER;
708}
709
710
711void LAYER_WIDGET::SetLayerVisible( int aLayer, bool isVisible )
712{
713 setLayerCheckbox( aLayer, isVisible );
714 OnLayerVisible( aLayer, isVisible );
715}
716
717
718void LAYER_WIDGET::setLayerCheckbox( int aLayer, bool isVisible )
719{
720 int row = findLayerRow( aLayer );
721
722 if( row >= 0 )
723 {
724 wxCheckBox* cb = (wxCheckBox*) getLayerComp( row, COLUMN_COLOR_LYR_CB );
725 wxASSERT( cb );
726 cb->SetValue( isVisible ); // does not fire an event
727 }
728}
729
730
732{
733 int row = findLayerRow( aLayer );
734
735 if( row >= 0 )
736 {
737 wxCheckBox* cb = (wxCheckBox*) getLayerComp( row, COLUMN_COLOR_LYR_CB );
738 wxASSERT( cb );
739 return cb->GetValue();
740 }
741
742 return false;
743}
744
745
746void LAYER_WIDGET::SetLayerColor( int aLayer, const COLOR4D& aColor )
747{
748 int row = findLayerRow( aLayer );
749
750 if( row >= 0 )
751 {
752 int col = 1; // bitmap button is column 1
753 auto swatch = static_cast<COLOR_SWATCH*>( getLayerComp( row, col ) );
754 wxASSERT( swatch );
755
756 swatch->SetSwatchColor( aColor, false );
757 }
758}
759
760
762{
763 int row = findLayerRow( aLayer );
764
765 if( row >= 0 )
766 {
767 const int col = 1; // bitmap button is column 1
768 auto swatch = static_cast<COLOR_SWATCH*>( getLayerComp( row, col ) );
769 wxASSERT( swatch );
770
771 return swatch->GetSwatchColor();
772 }
773
774 return COLOR4D::UNSPECIFIED; // it's caller fault, gave me a bad layer
775}
776
777
779{
780 int row = aRow;
781
782 if( row >= 0 )
783 {
784 const int col = 0; // bitmap button (swatch) is column 0
785 auto swatch = static_cast<COLOR_SWATCH*>( getRenderComp( row, col ) );
786 wxASSERT( swatch );
787
788 return swatch->GetSwatchColor();
789 }
790
791 return COLOR4D::UNSPECIFIED; // it's caller fault, gave me a bad layer
792}
793
794
795void LAYER_WIDGET::SetRenderState( int aId, bool isSet )
796{
797 int row = findRenderRow( aId );
798
799 if( row >= 0 )
800 {
801 int col = 1; // checkbox is column 1
802 wxCheckBox* cb = (wxCheckBox*) getRenderComp( row, col );
803 wxASSERT( cb );
804 cb->SetValue( isSet ); // does not fire an event
805 }
806}
807
808
810{
811 int row = findRenderRow( aId );
812
813 if( row >= 0 )
814 {
815 int col = 1; // checkbox is column 1
816 wxCheckBox* cb = (wxCheckBox*) getRenderComp( row, col );
817 wxASSERT( cb );
818 return cb->GetValue();
819 }
820
821 return false; // the value of a non-existent row
822}
823
824
826{
827 m_LayersFlexGridSizer->Layout();
828 m_RenderFlexGridSizer->Layout();
829 m_LayerPanel->Layout();
830 m_RenderingPanel->Layout();
831 FitInside();
832}
833
834
836{
837 int rowCount = GetLayerRowCount();
838
839 for( int row = 0; row < rowCount ; row++ )
840 {
842
843 if( indicator )
844 {
846
847 if( row == m_CurrentRow )
849 else
850 state = ROW_ICON_PROVIDER::STATE::OFF;
851
852 indicator->SetIndicatorState( state );
853 }
854 }
855}
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:105
wxMenuItem * AddMenuItem(wxMenu *aMenu, int aId, const wxString &aText, const wxBitmap &aImage, wxItemKind aType=wxITEM_NORMAL)
Create and insert a menu item with an icon into aMenu.
Definition: bitmap.cpp:257
@ color_materials
#define ON
A simple color swatch of the kind used to set layer colors.
Definition: color_swatch.h:57
void GetNewSwatchColor()
Prompt for a new colour, using the colour picker dialog.
KIGFX::COLOR4D GetSwatchColor() const
void SetSwatchBackground(const KIGFX::COLOR4D &aBackground)
Set the swatch background color.
representing a row indicator icon for use in places like the layer widget
void SetIndicatorState(ICON_ID aIconId)
Set the row indicator to the given state.
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
static int getDecodedId(int aControlId)
Decode aControlId to original un-encoded value.
void SelectLayerRow(int aRow)
Change the row selection in the layer list to the given row.
wxWindow * m_FocusOwner
Definition: layer_widget.h:473
static int encodeId(int aColumn, int aId)
Allow saving a layer index within a control as its wxControl id.
void SetRenderState(int aId, bool isSet)
Set the state of the checkbox associated with aId within the Render tab group of the widget.
virtual void OnRenderEnable(int aId, bool isEnabled)=0
Notify client code whenever the user changes an rendering enable in one of the rendering checkboxes.
void insertRenderRow(int aRow, const ROW &aSpec)
void insertLayerRow(int aRow, const ROW &aSpec)
Append or insert a new row in the layer portion of the widget.
wxScrolledWindow * m_RenderScrolledWindow
Definition: layer_widget.h:470
void SetLayerColor(int aLayer, const COLOR4D &aColor)
Change the color of aLayer.
ROW_ICON_PROVIDER * m_IconProvider
Definition: layer_widget.h:477
bool GetRenderState(int aId)
Return the state of the checkbox associated with aId.
void OnLeftDownLayers(wxMouseEvent &event)
void setLayerCheckbox(int aLayer, bool isVisible)
int GetRenderRowCount() const
Return the number of rows in the render tab.
LAYER_WIDGET(wxWindow *aParent, wxWindow *aFocusOwner, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxTAB_TRAVERSAL)
wxPanel * m_RenderingPanel
Definition: layer_widget.h:469
virtual void OnLayerVisible(int aLayer, bool isVisible, bool isFinal=true)=0
Notify client code about a layer visibility change.
wxFlexGridSizer * m_LayersFlexGridSizer
Definition: layer_widget.h:468
void SelectLayer(int aLayer)
Change the row selection in the layer list to aLayer provided.
void OnRenderSwatchChanged(wxCommandEvent &aEvent)
Called when user has changed the swatch color of a render entry.
int GetLayerRowCount() const
Return the number of rows in the layer tab.
virtual ~LAYER_WIDGET()
void UpdateLayouts()
void passOnFocus()
Give away the keyboard focus up to the main parent window.
COLOR4D GetRenderColor(int aRow) const
Return the color of the Render ROW in position aRow.
void updateLayerRow(int aRow, const wxString &aName)
void OnTabChange(wxNotebookEvent &event)
int findLayerRow(int aLayer) const
Return the row index that aLayer resides in, or -1 if not found.
static const wxEventType EVT_LAYER_COLOR_CHANGE
Definition: layer_widget.h:120
int findRenderRow(int aId) const
int GetSelectedLayer()
Return the selected layer or -1 if none.
virtual void OnLayerRightClick(wxMenu &aMenu)=0
Notify client code about a layer being right-clicked.
void AppendRenderRow(const ROW &aRow)
Append a new row in the render portion of the widget.
bool IsLayerVisible(int aLayer)
Return the visible state of the layer ROW associated with aLayer id.
int m_CurrentRow
selected row of layer list
Definition: layer_widget.h:474
@ ID_CHANGE_RENDER_COLOR
Definition: layer_widget.h:461
virtual COLOR4D getBackgroundLayerColor()
Subclasses can override this to provide accurate representation of transparent color swatches.
Definition: layer_widget.h:369
void SetLayerVisible(int aLayer, bool isVisible)
Set aLayer visible or not.
void ClearLayerRows()
Empty out the layer rows.
void OnLayerSwatchChanged(wxCommandEvent &aEvent)
Called when a user changes a swatch color.
wxWindow * getLayerComp(int aRow, int aColumn) const
Return the component within the m_LayersFlexGridSizer at aRow and aCol or NULL if these parameters ar...
void UpdateLayerIcons()
Update all layer manager icons (layers only).
void AppendLayerRow(const ROW &aRow)
Append a new row in the layer portion of the widget.
wxString m_smallestLayerString
Definition: layer_widget.h:479
void ClearRenderRows()
Empty out the render rows.
virtual void OnRenderColorChange(int aId, const COLOR4D &aColor)=0
Notify client code whenever the user changes a rendering color.
virtual void OnLayerColorChange(int aLayer, const COLOR4D &aColor)=0
Notify client code about a layer color change.
COLOR4D GetLayerColor(int aLayer) const
Return the color of the layer ROW associated with aLayer id.
void OnLayerCheckBox(wxCommandEvent &event)
Handle the "is layer visible" checkbox and propagates the event to the client's notification function...
void OnRenderCheckBox(wxCommandEvent &event)
void OnRightDownLayer(wxMouseEvent &event, COLOR_SWATCH *aColorSwatch, const wxString &aLayerName)
Called when user right-clicks a layer.
wxWindow * getRenderComp(int aRow, int aColumn) const
void OnRightDownRender(wxMouseEvent &aEvent, COLOR_SWATCH *aColorSwatch, const wxString &aRenderName)
Notify when user right-clicks a render option.
virtual bool OnLayerSelect(int aLayer)=0
Notify client code whenever the user selects a different layer.
wxFlexGridSizer * m_RenderFlexGridSizer
Definition: layer_widget.h:471
wxPanel * m_LayerPanel
Definition: layer_widget.h:466
wxSize GetBestSize() const
Return the preferred minimum size, taking into consideration the dynamic content.
wxNotebook * m_notebook
Definition: layer_widget.h:465
wxScrolledWindow * m_LayerScrolledWindow
Definition: layer_widget.h:467
Icon provider for the "standard" row indicators, for example in layer selection lists.
STATE
< State constants to select the right icons
A version of a wxStaticText control that will request a smaller size than the full string.
void SetMinimumStringLength(const wxString &aString)
Set the string that is used for determining the requested size of the control.
@ SWATCH_SMALL
Definition: color_swatch.h:40
#define _(s)
@ LAYER_PCB_BACKGROUND
PCB background color.
Definition: layer_ids.h:220
@ UNDEFINED_LAYER
Definition: layer_ids.h:60
static void shrinkFont(wxWindow *aControl, int aPointSize)
Reduce the size of the wxFont associated with aControl.
#define LYR_COLUMN_COUNT
Layer tab column count.
Definition: layer_widget.h:48
#define COLUMN_COLOR_LYRNAME
Definition: layer_widget.h:54
#define COLUMN_ALPHA_INDICATOR
Definition: layer_widget.h:55
#define COLUMN_COLOR_LYR_CB
Definition: layer_widget.h:53
#define COLUMN_ICON_ACTIVE
Definition: layer_widget.h:51
#define COLUMN_COLORBM
Definition: layer_widget.h:52
#define RND_COLUMN_COUNT
Rendering tab column count.
Definition: layer_widget.h:49
This file contains miscellaneous commonly used macros and functions.
Macros and inline functions to create menus items in menubars or popup menus.
Provide all the data needed to add a row to a LAYER_WIDGET.
Definition: layer_widget.h:85
COLOR4D color
COLOR4D::UNSPECIFIED if none.
Definition: layer_widget.h:88
bool spacer
if true, this row is a spacer
Definition: layer_widget.h:92
wxString tooltip
if not empty, use this tooltip on row
Definition: layer_widget.h:90
int id
either a layer or "visible element" id
Definition: layer_widget.h:87
bool state
initial wxCheckBox state
Definition: layer_widget.h:89
wxString rowName
the prompt or layername
Definition: layer_widget.h:86
bool changeable
if true, the state can be changed
Definition: layer_widget.h:91
COLOR4D defaultColor
The default color for the row.
Definition: layer_widget.h:93