KiCad PCB EDA Suite
zone_filler_tool.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2014-2017 CERN
5  * Copyright (C) 2014-2018 KiCad Developers, see AUTHORS.txt for contributors.
6  * @author Maciej Suminski <[email protected]>
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 #include <cstdint>
26 #include <thread>
27 #include <zone.h>
29 #include <board_commit.h>
30 #include <board_design_settings.h>
31 #include <progress_reporter.h>
32 #include <widgets/infobar.h>
34 #include <wx/event.h>
35 #include <wx/hyperlink.h>
36 #include <tool/tool_manager.h>
37 #include "pcb_actions.h"
38 #include "zone_filler_tool.h"
39 #include "zone_filler.h"
40 
41 
43  PCB_TOOL_BASE( "pcbnew.ZoneFiller" ),
44  m_fillInProgress( false )
45 {
46 }
47 
48 
50 {
51 }
52 
53 
55 {
56 }
57 
58 
59 void ZONE_FILLER_TOOL::CheckAllZones( wxWindow* aCaller, PROGRESS_REPORTER* aReporter )
60 {
61  if( !getEditFrame<PCB_EDIT_FRAME>()->m_ZoneFillsDirty || m_fillInProgress )
62  return;
63 
64  m_fillInProgress = true;
65 
66  std::vector<ZONE*> toFill;
67 
68  for( ZONE* zone : board()->Zones() )
69  toFill.push_back(zone);
70 
71  BOARD_COMMIT commit( this );
72  std::unique_ptr<WX_PROGRESS_REPORTER> reporter;
73  ZONE_FILLER filler( frame()->GetBoard(), &commit );
74 
75  if( aReporter )
76  {
77  filler.SetProgressReporter( aReporter );
78  }
79  else
80  {
81  reporter = std::make_unique<WX_PROGRESS_REPORTER>( aCaller, _( "Checking Zones" ), 4 );
82  filler.SetProgressReporter( reporter.get() );
83  }
84 
85  if( filler.Fill( toFill, true, aCaller ) )
86  {
87  board()->GetConnectivity()->Build( board() );
88  commit.Push( _( "Fill Zone(s)" ) );
89  getEditFrame<PCB_EDIT_FRAME>()->m_ZoneFillsDirty = false;
90  }
91  else
92  {
93  commit.Revert();
94  }
95 
96  canvas()->Refresh();
97  m_fillInProgress = false;
98 }
99 
100 
102 {
103  canvas()->SetFocus();
104  canvas()->Unbind( wxEVT_IDLE, &ZONE_FILLER_TOOL::singleShotRefocus, this );
105 }
106 
107 
108 void ZONE_FILLER_TOOL::FillAllZones( wxWindow* aCaller, PROGRESS_REPORTER* aReporter )
109 {
110  PCB_EDIT_FRAME* frame = getEditFrame<PCB_EDIT_FRAME>();
111  std::vector<ZONE*> toFill;
112 
113  if( m_fillInProgress )
114  return;
115 
116  m_fillInProgress = true;
117 
118  for( ZONE* zone : board()->Zones() )
119  toFill.push_back( zone );
120 
121  board()->IncrementTimeStamp(); // Clear caches
122 
123  BOARD_COMMIT commit( this );
124  std::unique_ptr<WX_PROGRESS_REPORTER> reporter;
125  ZONE_FILLER filler( board(), &commit );
126 
127  if( !board()->GetDesignSettings().m_DRCEngine->RulesValid() )
128  {
129  WX_INFOBAR* infobar = frame->GetInfoBar();
130  wxHyperlinkCtrl* button = new wxHyperlinkCtrl( infobar, wxID_ANY, _("Show DRC rules"),
131  wxEmptyString );
132 
133  button->Bind( wxEVT_COMMAND_HYPERLINK,
134  std::function<void( wxHyperlinkEvent& aEvent )>(
135  [frame]( wxHyperlinkEvent& aEvent )
136  {
137  frame->ShowBoardSetupDialog( _( "Rules" ) );
138  } ) );
139 
140  infobar->RemoveAllButtons();
141  infobar->AddButton( button );
142 
143  infobar->ShowMessageFor( _( "Zone fills may be inaccurate. DRC rules contain errors." ),
144  10000, wxICON_WARNING );
145  }
146 
147  if( aReporter )
148  {
149  filler.SetProgressReporter( aReporter );
150  }
151  else
152  {
153  reporter = std::make_unique<WX_PROGRESS_REPORTER>( aCaller, _( "Fill All Zones" ), 3 );
154  filler.SetProgressReporter( reporter.get() );
155  }
156 
157  {
158  if( filler.Fill( toFill ) )
159  {
160  board()->GetConnectivity()->Build( board() );
161  commit.Push( _( "Fill Zone(s)" ), true ); // Allow undoing zone fill
162  frame->m_ZoneFillsDirty = false;
163  }
164  else
165  {
166  commit.Revert();
167  }
168 
169  if( filler.IsDebug() )
170  frame->UpdateUserInterface();
171  }
172 
173  canvas()->Refresh();
174  m_fillInProgress = false;
175 
176  // wxWidgets has keyboard focus issues after the progress reporter. Re-setting the focus
177  // here doesn't work, so we delay it to an idle event.
178  canvas()->Bind( wxEVT_IDLE, &ZONE_FILLER_TOOL::singleShotRefocus, this );
179 }
180 
181 
183 {
184  if( m_fillInProgress )
185  {
186  wxBell();
187  return -1;
188  }
189 
190  m_fillInProgress = true;
191 
192  std::vector<ZONE*> toFill;
193 
194  if( ZONE* passedZone = aEvent.Parameter<ZONE*>() )
195  {
196  toFill.push_back( passedZone );
197  }
198  else
199  {
200  for( EDA_ITEM* item : selection() )
201  {
202  if( ZONE* zone = dynamic_cast<ZONE*>( item ) )
203  toFill.push_back( zone );
204  }
205  }
206 
207  BOARD_COMMIT commit( this );
208  std::unique_ptr<WX_PROGRESS_REPORTER> reporter;
209  ZONE_FILLER filler( board(), &commit );
210 
211  reporter = std::make_unique<WX_PROGRESS_REPORTER>( frame(), _( "Fill Zone" ), 4 );
212  filler.SetProgressReporter( reporter.get() );
213 
214  if( filler.Fill( toFill ) )
215  {
216  board()->GetConnectivity()->Build( board() );
217  commit.Push( _( "Fill Zone(s)" ), true ); // Allow undoing zone fill
218  }
219  else
220  commit.Revert();
221 
222  canvas()->Refresh();
223  m_fillInProgress = false;
224  return 0;
225 }
226 
227 
229 {
230  FillAllZones( frame() );
231  return 0;
232 }
233 
234 
236 {
237  BOARD_COMMIT commit( this );
238 
239  for( EDA_ITEM* item : selection() )
240  {
241  assert( item->Type() == PCB_ZONE_T || item->Type() == PCB_FP_ZONE_T );
242 
243  ZONE* zone = static_cast<ZONE*>( item );
244 
245  commit.Modify( zone );
246 
247  zone->UnFill();
248  }
249 
250  commit.Push( _( "Unfill Zone" ) );
251  canvas()->Refresh();
252 
253  return 0;
254 }
255 
256 
258 {
259  BOARD_COMMIT commit( this );
260 
261  for( ZONE* zone : board()->Zones() )
262  {
263  commit.Modify( zone );
264 
265  zone->UnFill();
266  }
267 
268  commit.Push( _( "Unfill All Zones" ) );
269  canvas()->Refresh();
270 
271  return 0;
272 }
273 
274 
276 {
277  // Zone actions
282 }
COMMIT & Modify(EDA_ITEM *aItem)
Create an undo entry for an item that has been already modified.
Definition: commit.h:103
void AddButton(wxButton *aButton)
Add an already created button to the infobar.
Definition: infobar.cpp:245
BOARD * board() const
int ZoneUnfill(const TOOL_EVENT &aEvent)
static TOOL_ACTION zoneFillAll
Definition: pcb_actions.h:303
A progress reporter interface for use in multi-threaded environments.
virtual void Revert() override
int ZoneUnfillAll(const TOOL_EVENT &aEvent)
void singleShotRefocus(wxIdleEvent &)
< Refocus on an idle event (used after the Progress Reporter messes up the focus).
void ShowMessageFor(const wxString &aMessage, int aTime, int aFlags=wxICON_INFORMATION, MESSAGE_TYPE aType=WX_INFOBAR::MESSAGE_TYPE::GENERIC)
Show the infobar with the provided message and icon for a specific period of time.
Definition: infobar.cpp:128
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Define which state (aStateFunc) to go when a certain event arrives (aConditions).
static TOOL_ACTION zoneFill
Definition: pcb_actions.h:302
PCB_BASE_EDIT_FRAME * frame() const
bool Fill(std::vector< ZONE * > &aZones, bool aCheck=false, wxWindow *aParent=nullptr)
Fills the given list of zones.
Definition: zone_filler.cpp:79
void FillAllZones(wxWindow *aCaller, PROGRESS_REPORTER *aReporter=nullptr)
void CheckAllZones(wxWindow *aCaller, PROGRESS_REPORTER *aReporter=nullptr)
int ZoneFill(const TOOL_EVENT &aEvent)
const PCB_SELECTION & selection() const
void SetProgressReporter(PROGRESS_REPORTER *aReporter)
Definition: zone_filler.cpp:71
T Parameter() const
Return a non-standard parameter assigned to the event.
Definition: tool_event.h:432
Generic, UI-independent tool event.
Definition: tool_event.h:152
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:345
#define _(s)
virtual void SetFocus() override
Handle a list of polygons defining a copper zone.
Definition: zone.h:56
class ZONE, a copper pour area
Definition: typeinfo.h:105
void IncrementTimeStamp()
Definition: board.cpp:192
bool IsDebug() const
Definition: zone_filler.h:55
static TOOL_ACTION zoneUnfillAll
Definition: pcb_actions.h:305
void RemoveAllButtons()
Remove all the buttons that have been added by the user.
Definition: infobar.cpp:286
static TOOL_ACTION zoneUnfill
Definition: pcb_actions.h:304
BOARD * GetBoard()
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
A modified version of the wxInfoBar class that allows us to:
Definition: infobar.h:73
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
class ZONE, managed by a footprint
Definition: typeinfo.h:94
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
The main frame for Pcbnew.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:99
virtual void Push(const wxString &aMessage=wxT("A commit"), bool aCreateUndoEntry=true, bool aSetDirtyBit=true) override
Revert the commit by restoring the modified items state.
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:77
WX_INFOBAR * GetInfoBar()
PCB_DRAW_PANEL_GAL * canvas() const
int ZoneFillAll(const TOOL_EVENT &aEvent)