1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2020 Jon Evans <jon@craftyjon.com>
5  * Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software: you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the
9  * Free Software Foundation, either version 3 of the License, or (at your
10  * option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 #ifndef _APPEARANCE_CONTROLS_H
22 #define _APPEARANCE_CONTROLS_H
23 
24 #include <vector>
25 
26 #include <board.h>
27 #include <gal/color4d.h>
28 #include <layer_ids.h>
29 #include <project/board_project_settings.h>
30 #include <widgets/appearance_controls_base.h>
31 
32 
33 class BITMAP_TOGGLE;
34 class COLOR_SWATCH;
35 class INDICATOR_ICON;
36 class PCB_BASE_FRAME;
37 class ROW_ICON_PROVIDER;
38 class GRID_BITMAP_TOGGLE_RENDERER;
39 class WX_COLLAPSIBLE_PANE;
40 class wxStaticLine;
41 class wxSlider;
42 class wxRadioButton;
43 
44 using KIGFX::COLOR4D;
45 
46 
47 struct NET_GRID_ENTRY
48 {
NET_GRID_ENTRYNET_GRID_ENTRY49     NET_GRID_ENTRY( int aCode, const wxString& aName, const COLOR4D& aColor, bool aVisible )
50     {
51         code    = aCode;
52         name    = aName;
53         color   = aColor;
54         visible = aVisible;
55     }
56 
57     int      code;
58     wxString name;
59     COLOR4D  color;
60     bool     visible;
61 };
62 
63 
64 class NET_GRID_TABLE : public wxGridTableBase
65 {
66 public:
67     enum COLUMNS
68     {
69         COL_COLOR,
70         COL_VISIBILITY,
71         COL_LABEL,
72         COL_SIZE
73     };
74 
ColorToVoid(COLOR4D & aColor)75     static void* ColorToVoid( COLOR4D& aColor )
76     {
77         return static_cast<void*>( &aColor );
78     }
79 
VoidToColor(void * aColor)80     static COLOR4D VoidToColor( void* aColor )
81     {
82         return *static_cast<COLOR4D*>( aColor );
83     }
84 
85 public:
86     NET_GRID_TABLE( PCB_BASE_FRAME* aFrame, wxColor aBackgroundColor );
87     ~NET_GRID_TABLE();
88 
GetNumberRows()89     int GetNumberRows() override
90     {
91         return m_nets.size();
92     }
93 
GetNumberCols()94     int GetNumberCols() override
95     {
96         return COL_SIZE;
97     }
98 
99     wxGridCellAttr* GetAttr( int aRow, int aCol, wxGridCellAttr::wxAttrKind ) override;
100 
101     wxString GetValue( int aRow, int aCol ) override;
102 
103     void SetValue( int aRow, int aCol, const wxString& aValue ) override;
104 
105     wxString GetTypeName( int aRow, int aCol ) override;
106 
107     bool GetValueAsBool( int aRow, int aCol ) override;
108 
109     void SetValueAsBool( int aRow, int aCol, bool aValue ) override;
110 
111     void* GetValueAsCustom( int aRow, int aCol, const wxString& aTypeName ) override;
112 
113     void SetValueAsCustom( int aRow, int aCol, const wxString& aTypeName, void* aValue ) override;
114 
115     NET_GRID_ENTRY& GetEntry( int aRow );
116 
117     int GetRowByNetcode( int aCode ) const;
118 
119     void Rebuild();
120 
121     void ShowAllNets();
122 
123     void HideOtherNets( const NET_GRID_ENTRY& aNet );
124 
125 private:
126     void updateNetVisibility( const NET_GRID_ENTRY& aNet );
127 
128     void updateNetColor( const NET_GRID_ENTRY& aNet );
129 
130 private:
131     PCB_BASE_FRAME* m_frame;
132 
133     std::vector<NET_GRID_ENTRY> m_nets;
134 
135     wxGridCellAttr* m_defaultAttr;
136     wxGridCellAttr* m_labelAttr;
137 };
138 
139 
140 
141 class APPEARANCE_CONTROLS : public APPEARANCE_CONTROLS_BASE, public BOARD_LISTENER
142 {
143 public:
144 
145     /**
146      * Container for an appearance setting (can control a single board layer, or GAL layer, etc)
147      */
148     struct APPEARANCE_SETTING
149     {
150         int      id;
151         wxString label;
152         wxString tooltip;
153         bool     visible;
154         bool     can_control_opacity;
155         bool     spacer;
156 
157         wxPanel*        ctl_panel;
158         INDICATOR_ICON* ctl_indicator;
159         BITMAP_TOGGLE*  ctl_visibility;
160         COLOR_SWATCH*   ctl_color;
161         wxStaticText*   ctl_text;
162         wxSlider*       ctl_opacity;
163 
164         APPEARANCE_SETTING( const wxString& aLabel, int aId,
165                             const wxString& aTooltip = wxEmptyString,
166                             bool aCanControlOpacity = false ) :
idAPPEARANCE_SETTING167                 id( aId ),
168                 label( aLabel ),
169                 tooltip( aTooltip ),
170                 visible( true ),
171                 can_control_opacity( aCanControlOpacity ),
172                 spacer( false ),
173                 ctl_panel( nullptr ),
174                 ctl_indicator( nullptr ),
175                 ctl_visibility( nullptr ),
176                 ctl_color( nullptr ),
177                 ctl_text( nullptr ),
178                 ctl_opacity( nullptr )
179         {
180         }
181 
APPEARANCE_SETTINGAPPEARANCE_SETTING182         APPEARANCE_SETTING() :
183                 id( -1 ),
184                 label( "" ),
185                 tooltip( "" ),
186                 visible( false ),
187                 can_control_opacity( false ),
188                 spacer( true ),
189                 ctl_panel( nullptr ),
190                 ctl_indicator( nullptr ),
191                 ctl_visibility( nullptr ),
192                 ctl_color( nullptr ),
193                 ctl_text( nullptr ),
194                 ctl_opacity( nullptr )
195         {
196         }
197     };
198 
199     APPEARANCE_CONTROLS( PCB_BASE_FRAME* aParent, wxWindow* aFocusOwner, bool aFpEditor = false );
200     ~APPEARANCE_CONTROLS();
201 
202     wxSize GetBestSize() const;
203 
204     ///< Update the panel contents from the application and board models.
205     void OnBoardChanged();
206 
207     void OnBoardNetSettingsChanged( BOARD& aBoard ) override;
208 
209     void OnBoardItemAdded( BOARD& aBoard, BOARD_ITEM* aItem ) override;
210 
211     void OnBoardItemsAdded( BOARD& aBoard, std::vector<BOARD_ITEM*>& aItems ) override;
212 
213     void OnBoardItemRemoved( BOARD& aBoard, BOARD_ITEM* aItem ) override;
214 
215     void OnBoardItemsRemoved( BOARD& aBoard, std::vector<BOARD_ITEM*>& aItems ) override;
216 
217     void OnBoardItemChanged( BOARD& aBoard, BOARD_ITEM* aItem ) override;
218 
219     void OnBoardItemsChanged( BOARD& aBoard, std::vector<BOARD_ITEM*>& aItems ) override;
220 
221     ///< Update the colors on all the widgets from the new chosen color theme.
222     void OnColorThemeChanged();
223 
224     ///< Update the widget when the active board layer is changed.
225     void OnLayerChanged();
226 
227     /// Notifies the panel when a net has been hidden or shown via the external tool.
228     void OnNetVisibilityChanged( int aNetCode, bool aVisibility );
229 
230     ///< Manually update visibility for a given layer
231     void SetLayerVisible( LAYER_NUM aLayer, bool isVisible );
232 
233     void SetObjectVisible( GAL_LAYER_ID aLayer, bool isVisible = true );
234 
235     ///< Update the manual layer alpha overrides.
236     void OnLayerAlphaChanged();
237 
238     void UpdateDisplayOptions();
239 
240     ///< Return a list of the layer presets created by the user.
241     std::vector<LAYER_PRESET> GetUserLayerPresets() const;
242 
243     ///< Update the current layer presets from those saved in the project file.
244     void SetUserLayerPresets( std::vector<LAYER_PRESET>& aPresetList );
245 
246     void ApplyLayerPreset( const wxString& aPresetName );
247 
248     void ApplyLayerPreset( const LAYER_PRESET& aPreset );
249 
GetActiveLayerPreset()250     wxString GetActiveLayerPreset() const
251     {
252         if( m_currentPreset )
253             return m_currentPreset->name;
254         else
255             return wxEmptyString;
256     }
257 
GetLayerPresetsMRU()258     const wxArrayString& GetLayerPresetsMRU()
259     {
260         return m_presetMRU;
261     }
262 
263     void OnColorSwatchChanged( wxCommandEvent& aEvent );
264 
265     void OnLayerContextMenu( wxCommandEvent& aEvent );
266 
267     ///< Return the index of the current tab (0-2).
268     int GetTabIndex() const;
269 
270     ///< Set the current notebook tab.
271     void SetTabIndex( int aTab );
272 
273     /**
274      * Function to force a redraw of the collapsible panes in this control.
275      */
276     void RefreshCollapsiblePanes();
277 
278 protected:
279     void OnNotebookPageChanged( wxNotebookEvent& event ) override;
280 
281     void OnSetFocus( wxFocusEvent& aEvent ) override;
282 
283     void OnSize( wxSizeEvent& aEvent ) override;
284 
285     void OnNetGridClick( wxGridEvent& event ) override;
286 
287     void OnNetGridDoubleClick( wxGridEvent& event ) override;
288 
289     void OnNetGridRightClick( wxGridEvent& event ) override;
290 
291     void OnNetGridMouseEvent( wxMouseEvent& aEvent );
292 
293 private:
294     void createControls();
295 
296     void rebuildLayers();
297 
298     void rebuildLayerContextMenu();
299 
300     void syncColorsAndVisibility();
301 
302     void rebuildObjects();
303 
304     void syncObjectSettings();
305 
306     void rebuildNets();
307 
308     void loadDefaultLayerPresets();
309 
310     void rebuildLayerPresetsWidget();
311 
312     void syncLayerPresetSelection();
313 
314     void onLayerLeftClick( wxMouseEvent& aEvent );
315 
316     void rightClickHandler( wxMouseEvent& aEvent );
317 
318     void onLayerVisibilityChanged( PCB_LAYER_ID aLayer, bool isVisible, bool isFinal );
319 
320     void onObjectVisibilityChanged( GAL_LAYER_ID aLayer, bool isVisible, bool isFinal );
321 
322     void setVisibleLayers( LSET aLayers );
323 
324     void setVisibleObjects( GAL_SET aObjects );
325 
326     LSET getVisibleLayers();
327 
328     GAL_SET getVisibleObjects();
329 
330     void onObjectOpacitySlider( int aLayer, float aOpacity );
331 
332     void updateLayerPresetSelection( const wxString& aName );
333 
334     void onLayerPresetChanged( wxCommandEvent& aEvent ) override;
335 
336     void doApplyLayerPreset( const LAYER_PRESET& aPreset );
337 
338     void onNetclassVisibilityChanged( wxCommandEvent& aEvent );
339 
340     void showNetclass( const wxString& aClassName, bool aShow = true );
341 
342     void onNetContextMenu( wxCommandEvent& aEvent );
343 
344     void onNetclassColorChanged( wxCommandEvent& aEvent );
345 
346     wxString netclassNameFromEvent( wxEvent& aEvent );
347 
348     void onNetColorMode( wxCommandEvent& aEvent );
349 
350     void onRatsnestMode( wxCommandEvent& aEvent );
351 
352     void onNetclassContextMenu( wxCommandEvent& aEvent );
353 
354     void handleBoardItemsChanged();
355 
356     void passOnFocus();
357 
358     void idleFocusHandler( wxIdleEvent& aEvent );
359 
360     void onReadOnlySwatch();
361 
362     bool doesBoardItemNeedRebuild( BOARD_ITEM* aBoardItem );
363 
364     bool doesBoardItemNeedRebuild( std::vector<BOARD_ITEM*>& aBoardItems );
365 
366     PCB_BASE_FRAME* m_frame;
367 
368     wxWindow* m_focusOwner;
369 
370     static const APPEARANCE_SETTING s_objectSettings[];
371 
372     ROW_ICON_PROVIDER* m_iconProvider;
373 
374     BOARD* m_board;
375 
376     bool m_isFpEditor;
377 
378     // Nets grid view
379     NET_GRID_TABLE* m_netsTable;
380 
381     GRID_BITMAP_TOGGLE_RENDERER* m_toggleGridRenderer;
382 
383     /// Grid cell that is being hovered over, for tooltips
384     wxGridCellCoords m_hoveredCell;
385 
386     std::vector<std::unique_ptr<APPEARANCE_SETTING>> m_layerSettings;
387 
388     std::map<PCB_LAYER_ID, APPEARANCE_SETTING*> m_layerSettingsMap;
389 
390     std::vector<std::unique_ptr<APPEARANCE_SETTING>> m_objectSettings;
391 
392     std::map<GAL_LAYER_ID, APPEARANCE_SETTING*> m_objectSettingsMap;
393 
394     std::vector<std::unique_ptr<APPEARANCE_SETTING>> m_netclassSettings;
395 
396     std::map<wxString, APPEARANCE_SETTING*> m_netclassSettingsMap;
397 
398     // TODO(JE) Move preset storage to the PCB_CONTROL tool
399 
400     // Storage for all layer presets
401     std::map<wxString, LAYER_PRESET> m_layerPresets;
402 
403     LAYER_PRESET* m_currentPreset;
404 
405     /// The last user (non-read-only) preset selected by the user
406     LAYER_PRESET* m_lastSelectedUserPreset;
407 
408     wxArrayString m_presetMRU;
409 
410     wxMenu* m_layerContextMenu;
411 
412     /// Stores wxIDs for each netclass for control event mapping
413     std::map<int, wxString> m_netclassIdMap;
414 
415     /// The name of the netclass that was right-clicked
416     wxString m_contextMenuNetclass;
417 
418     wxBoxSizer* m_layersOuterSizer;
419     wxBoxSizer* m_objectsOuterSizer;
420 
421     // The built-in layer presets
422     static LAYER_PRESET presetNoLayers;
423     static LAYER_PRESET presetAllLayers;
424     static LAYER_PRESET presetAllCopper;
425     static LAYER_PRESET presetInnerCopper;
426     static LAYER_PRESET presetFront;
427     static LAYER_PRESET presetFrontAssembly;
428     static LAYER_PRESET presetBack;
429     static LAYER_PRESET presetBackAssembly;
430 
431     int m_pointSize;
432 
433     wxColour m_layerPanelColour;
434 
435     // Layer display options controls
436     WX_COLLAPSIBLE_PANE* m_paneLayerDisplayOptions;
437     wxStaticText*        m_inactiveLayersLabel;
438     wxRadioButton*       m_rbHighContrastNormal;
439     wxRadioButton*       m_rbHighContrastDim;
440     wxRadioButton*       m_rbHighContrastOff;
441     wxStaticLine*        m_layerDisplaySeparator;
442     wxCheckBox*          m_cbFlipBoard;
443 
444     // Net display options controls
445     WX_COLLAPSIBLE_PANE* m_paneNetDisplayOptions;
446     wxStaticText*        m_txtNetDisplayTitle;
447     wxRadioButton*       m_rbNetColorAll;
448     wxRadioButton*       m_rbNetColorRatsnest;
449     wxRadioButton*       m_rbNetColorOff;
450     wxStaticText*        m_txtRatsnestVisibility;
451     wxRadioButton*       m_rbRatsnestAllLayers;
452     wxRadioButton*       m_rbRatsnestVisLayers;
453     wxRadioButton*       m_rbRatsnestNone;
454 
455     enum POPUP_ID
456     {
457         ID_CHANGE_COLOR = wxID_HIGHEST,
458         ID_SET_NET_COLOR,
459         ID_CLEAR_NET_COLOR,
460         ID_SHOW_ALL_NETS,
461         ID_HIDE_OTHER_NETS,
462         ID_HIGHLIGHT_NET,
463         ID_SELECT_NET,
464         ID_DESELECT_NET,
465         ID_SHOW_ALL_COPPER_LAYERS,
466         ID_HIDE_ALL_COPPER_LAYERS,
467         ID_HIDE_ALL_BUT_ACTIVE,
468         ID_PRESET_NO_LAYERS,
469         ID_PRESET_ALL_LAYERS,
470         ID_PRESET_FRONT,
471         ID_PRESET_FRONT_ASSEMBLY,
472         ID_PRESET_INNER_COPPER,
473         ID_PRESET_BACK,
474         ID_PRESET_BACK_ASSEMBLY,
475         ID_HIDE_ALL_NON_COPPER,
476         ID_SHOW_ALL_NON_COPPER,
477         ID_LAST_VALUE
478     };
479 };
480 
481 #endif
482