1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
23  */
24 
25 #ifndef _CVPCB_MAINFRAME_H_
26 #define _CVPCB_MAINFRAME_H_
27 
28 #include <config_params.h>
29 #include <kiway_player.h>
30 #include <netlist_reader/pcb_netlist.h>
31 
32 #include <auto_associate.h>
33 #include <cvpcb_association.h>
34 #include <listboxes.h>
35 
36 /*  Forward declarations */
37 class ACTION_TOOLBAR;
38 class ACTION_MENU;
39 class TOOL_DISPATCHER;
40 class wxAuiToolBar;
41 class wxStaticText;
42 class DISPLAY_FOOTPRINTS_FRAME;
43 
44 namespace CV { struct IFACE; }
45 
46 // The undo/redo list is composed of vectors of associations
47 typedef std::vector< CVPCB_ASSOCIATION >       CVPCB_UNDO_REDO_ENTRIES;
48 
49 // The undo list is a vector of undo entries
50 typedef std::vector< CVPCB_UNDO_REDO_ENTRIES > CVPCB_UNDO_REDO_LIST;
51 
52 
53 /**
54  * The CvPcb application main window.
55  */
56 class CVPCB_MAINFRAME : public KIWAY_PLAYER
57 {
58 public:
59     ~CVPCB_MAINFRAME();
60 
61     bool OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl=0 ) override;
62 
63     void KiwayMailIn( KIWAY_EXPRESS& aEvent ) override;
64 
65     /**
66      * The action to apply to a footprint filter when it is modified.
67      */
68     enum CVPCB_FILTER_ACTION
69     {
70         FILTER_DISABLE,     ///< Turn off the filter
71         FILTER_ENABLE,      ///< Turn on the filter
72         FILTER_TOGGLE       ///< Toggle the filter state
73     };
74 
75     /**
76      * The type of the controls present in the application.
77      */
78     enum CONTROL_TYPE
79     {
80         CONTROL_NONE,            ///< No controls have focus
81         CONTROL_LIBRARY,         ///< Library listbox
82         CONTROL_COMPONENT,       ///< Component listbox
83         CONTROL_FOOTPRINT        ///< Footprint listbox
84     };
85 
86     /**
87      * Directions to rotate the focus through the listboxes is.
88      */
89     enum FOCUS_DIR
90     {
91         CHANGE_FOCUS_RIGHT,
92         CHANGE_FOCUS_LEFT
93     };
94 
95     /**
96      * Directions to move when selecting items.
97      */
98     enum ITEM_DIR
99     {
100         ITEM_NEXT,  ///< The next item
101         ITEM_PREV   ///< The previous item
102     };
103 
104     /**
105      * Get if the current associations have been modified but not saved.
106      *
107      * @return true if the any changes have not been saved
108      */
IsContentModified()109     bool IsContentModified() const override
110     {
111         return m_modified;
112     }
113 
114     /**
115      * @return a pointer on the Footprint Viewer frame, if exists, or NULL
116      */
117     DISPLAY_FOOTPRINTS_FRAME* GetFootprintViewerFrame() const;
118 
119     wxWindow* GetToolCanvas() const override;
120 
121     /**
122      * Find out which control currently has focus.
123      *
124      * @return the control that currently has focus
125      */
126     CVPCB_MAINFRAME::CONTROL_TYPE GetFocusedControl() const;
127 
128     /**
129      * Get a pointer to the currently focused control
130      *
131      * @return the control that currently has focus
132      */
133     wxControl* GetFocusedControlObject() const;
134 
135     /**
136      * Set the focus to a specific control.
137      *
138      * @param aControl the control to set focus to
139      */
140     void SetFocusedControl( CVPCB_MAINFRAME::CONTROL_TYPE aControl );
141 
142     /**
143      * Called when clicking on a component in component list window:
144      * * Updates the filtered footprint list, if the filtered list option is selected
145      * * Updates the current selected footprint in footprint list
146      * * Updates the footprint shown in footprint display window (if opened)
147      */
148     void OnSelectComponent( wxListEvent& event );
149 
150     bool canCloseWindow( wxCloseEvent& aCloseEvent ) override;
151     void doCloseWindow() override;
152 
153     /*
154      * Functions to rebuild the toolbars and menubars
155      */
156     void ReCreateHToolbar();
157     void ReCreateMenuBar() override;
158 
159     void ShowChangedLanguage() override;
160 
161     /**
162      * Called by the automatic association button
163      * Read *.equ files to try to find corresponding footprint
164      * for each component that is not already linked to a footprint ( a "free"
165      * component )
166      * format of a line:
167      * 'cmp_ref' 'footprint_name'
168      */
169     void AutomaticFootprintMatching();
170 
171     /**
172      * Set a filter criteria to either on/off or toggle the criteria.
173      *
174      * @param aFilter The filter to modify
175      * @param aAction What action (on, off or toggle) to take
176      */
177     void SetFootprintFilter( FOOTPRINTS_LISTBOX::FP_FILTER_T aFilter,
178                              CVPCB_MAINFRAME::CVPCB_FILTER_ACTION aAction );
179 
180     /**
181      * Called each time the text of m_tcFilterString is changed.
182      */
183     void OnEnterFilteringText( wxCommandEvent& event );
184 
185     /**
186      * Undo the most recent associations that were performed.
187      */
188     void UndoAssociation();
189 
190     /**
191      * Redo the most recently undone association.
192      */
193     void RedoAssociation();
194 
GetUndoCommandCount()195     int GetUndoCommandCount() const override
196     {
197         return m_undoList.size();
198     }
199 
GetRedoCommandCount()200     int GetRedoCommandCount() const override
201     {
202         return m_redoList.size();
203     }
204 
205     /**
206      * Associate a footprint with a specific component in the list.
207      *
208      * Associations can be chained into a single undo/redo step by setting aNewEntry to false
209      * for every association other than the first one. This will create a new list entry for
210      * the first association, and add the subsequent associations to that list.
211      *
212      * @param aAssociation is the association to perform
213      * @param aNewEntry specifies if this association should be a new entry in the undo list
214      * @param aAddUndoItem specifies if an undo item should be created for this association
215      */
216     void AssociateFootprint( const CVPCB_ASSOCIATION& aAssociation, bool aNewEntry = true,
217                              bool aAddUndoItem = true );
218 
219     /*
220      * Functions to build the listboxes and their contents
221      */
222     void BuildSymbolsListBox();
223     void BuildFootprintsListBox();
224     void BuildLibrariesListBox();
225 
226     /**
227      * Save the edits that the user has done by sending them back to Eeschema via the kiway.
228      *
229      * Optionally saves the schematic to disk as well.
230      */
231     bool SaveFootprintAssociation( bool doSaveSchematic );
232 
233     /**
234      * Load the netlist file built on the fly by Eeschema and loads footprint libraries from
235      * fp lib tables.
236      *
237      * @param aNetlist is the netlist from Eeschema in KiCad s-expr format.
238      * (see CVPCB_MAINFRAME::KiwayMailIn() to know how to get this netlist)
239      */
240     bool ReadNetListAndFpFiles( const std::string& aNetlist );
241 
242     /**
243      * Read the netlist (.net) file built on the fly by Eeschema.
244      *
245      * @param aNetlist is the netlist buffer filled by Eeschema, in KiCad s-expr format.
246      * It is the same netlist as the .net file created by Eeschema.
247      * (This method is called by ReadNetListAndFpFiles)
248      */
249     int ReadSchematicNetlist( const std::string& aNetlist );
250 
251     void LoadSettings( APP_SETTINGS_BASE* aCfg ) override;
252 
253     void SaveSettings( APP_SETTINGS_BASE* aCfg ) override;
254 
255     /**
256      * Update the information displayed on the status bar at bottom of the main frame.
257      *
258      * When the library or component list controls have the focus, the footprint assignment
259      * status of the components is displayed in the first status bar pane and the list of
260      * filters for the selected component is displayed in the second status bar pane.  When
261      * the footprint list control has the focus, the description of the selected footprint is
262      * displayed in the first status bar pane and the key words for the selected footprint are
263      * displayed in the second status bar pane.  The third status bar pane always displays the
264      * current footprint list filtering.
265      */
266     void DisplayStatus();
267 
268     /**
269      * Read the list of footprint (*.mod files) and generate the list of footprints.
270      *
271      * For each footprint the following items are stored:
272      *  - the footprint name
273      *  - documentation string
274      *  - associated keywords
275      *
276      * @return true if libraries are found, false otherwise.
277      */
278     bool LoadFootprintFiles();
279 
280     /**
281      * Send a remote command to Eeschema via a socket,
282      *
283      * Commands are:
284      * $PART: "reference" put cursor on component anchor
285      *
286      * @param aClearHighligntOnly use true if the message to send is only "clear highlight"
287      *                            (used when exiting CvPcb)
288      */
289     void SendMessageToEESCHEMA( bool aClearHighligntOnly = false );
290 
291     /**
292      * Get the selected component from the component listbox.
293      *
294      * @return the selected component
295      */
296     COMPONENT* GetSelectedComponent();
297 
298     /**
299      * Set the currently selected component in the components listbox
300      *
301      * @param aIndex the index of the component to select, -1 to clear selection
302      * @param aSkipUpdate skips running the OnSelectComponent event to update the other windows
303      */
304     void SetSelectedComponent( int aIndex, bool aSkipUpdate = false );
305 
306     /**
307      * Criteria to use to identify sets of components
308      */
309     enum CRITERIA
310     {
311         ALL_COMPONENTS,     ///< All components
312         SEL_COMPONENTS,     ///< Selected components
313         NA_COMPONENTS,      ///< Not associated components
314         ASSOC_COMPONENTS    ///< Associated components
315     };
316 
317     /**
318      * Get the indices for all the components meeting the specified criteria in the components
319      * listbox.
320      *
321      * @param aCriteria is the criteria to use for finding the indices
322      * @return a vector containing all the indices
323      */
324     std::vector<unsigned int> GetComponentIndices(
325             CVPCB_MAINFRAME::CRITERIA aCriteria = CVPCB_MAINFRAME::ALL_COMPONENTS );
326 
327     /**
328      * @return the LIB_ID of the selected footprint in footprint listview
329      * or a empty string if no selection
330      */
331     wxString GetSelectedFootprint();
332 
333     void SetStatusText( const wxString& aText, int aNumber = 0 ) override;
334 
335 protected:
336     CVPCB_MAINFRAME( KIWAY* aKiway, wxWindow* aParent );
337 
338     void setupUIConditions() override;
339 
340 private:
341     wxString formatSymbolDesc( int idx, const wxString& aReference, const wxString& aValue,
342                                const wxString& aFootprint );
343 
344     /**
345      * Setup the tool system for the CVPCB main frame.
346      */
347     void setupTools();
348 
349     /**
350      * Setup event handlers
351      */
352     void setupEventHandlers();
353 
354     /**
355      * Read the .equ files and populate the list of equivalents.
356      *
357      * @param aList the list to populate
358      * @param aErrorMessages is a pointer to a wxString to store error messages
359      *  (can be NULL)
360      * @return the error count ( 0 = no error)
361      */
362     int buildEquivalenceList( FOOTPRINT_EQUIVALENCE_LIST& aList,
363                               wxString* aErrorMessages = nullptr );
364 
365     void refreshAfterSymbolSearch( COMPONENT* aSymbol );
366 
367 public:
368     FOOTPRINT_LIST* m_FootprintsList;
369 
370 protected:
371     bool            m_modified;
372     bool            m_skipComponentSelect;  // skip component selection event during
373                                             // automatic selection/deletion of associations
374 
375     bool            m_initialized;          // true after creating widgets.
376     bool            m_cannotClose;          // true when the cvpcb frame cannot be closed
377                                             // (mainly during reading a netlist sent by Eeschema)
378 
379 private:
380     friend struct CV::IFACE;
381 
382     NETLIST                   m_netlist;
383     int                       m_filteringOptions;
384     ACTION_TOOLBAR*           m_mainToolBar;
385     FOOTPRINTS_LISTBOX*       m_footprintListBox;
386     LIBRARY_LISTBOX*          m_librariesListBox;
387     SYMBOLS_LISTBOX*       m_symbolsListBox;
388     wxTextCtrl*               m_tcFilterString;
389     wxStaticText*             m_statusLine1;
390     wxStaticText*             m_statusLine2;
391     wxStaticText*             m_statusLine3;
392     wxButton*                 m_saveAndContinue;
393 
394     // Tool dispatcher
395     TOOL_DISPATCHER* m_toolDispatcher;
396 
397     // Context menus for the list boxes
398     ACTION_MENU* m_footprintContextMenu;
399     ACTION_MENU* m_symbolsContextMenu;
400 
401     // Undo/Redo item lists
402     CVPCB_UNDO_REDO_LIST    m_undoList;
403     CVPCB_UNDO_REDO_LIST    m_redoList;
404 };
405 
406 #endif  //#ifndef _CVPCB_MAINFRAME_H_
407