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 <maciej.suminski@cern.ch>
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>
31 #include <widgets/infobar.h>
32 #include <wx/event.h>
33 #include <wx/hyperlink.h>
34 #include <tool/tool_manager.h>
35 #include "pcb_actions.h"
36 #include "zone_filler_tool.h"
37 #include "zone_filler.h"
38 
39 
41  PCB_TOOL_BASE( "pcbnew.ZoneFiller" )
42 {
43 }
44 
45 
47 {
48 }
49 
50 
52 {
53 }
54 
55 
56 void ZONE_FILLER_TOOL::CheckAllZones( wxWindow* aCaller, PROGRESS_REPORTER* aReporter )
57 {
58  if( !getEditFrame<PCB_EDIT_FRAME>()->m_ZoneFillsDirty )
59  return;
60 
61  std::vector<ZONE*> toFill;
62 
63  for( auto zone : board()->Zones() )
64  toFill.push_back(zone);
65 
66  BOARD_COMMIT commit( this );
67 
68  ZONE_FILLER filler( frame()->GetBoard(), &commit );
69 
70  if( aReporter )
71  filler.SetProgressReporter( aReporter );
72  else
73  filler.InstallNewProgressReporter( aCaller, _( "Checking Zones" ), 4 );
74 
75  if( filler.Fill( toFill, true, aCaller ) )
76  {
77  commit.Push( _( "Fill Zone(s)" ), false );
78  getEditFrame<PCB_EDIT_FRAME>()->m_ZoneFillsDirty = false;
79  }
80  else
81  {
82  commit.Revert();
83  }
84 
85  canvas()->Refresh();
86 }
87 
88 
90 {
91  canvas()->SetFocus();
92  canvas()->Unbind( wxEVT_IDLE, &ZONE_FILLER_TOOL::singleShotRefocus, this );
93 }
94 
95 
96 void ZONE_FILLER_TOOL::FillAllZones( wxWindow* aCaller, PROGRESS_REPORTER* aReporter )
97 {
98  std::vector<ZONE*> toFill;
99 
100  BOARD_COMMIT commit( this );
101 
102  for( ZONE* zone : board()->Zones() )
103  toFill.push_back( zone );
104 
105  ZONE_FILLER filler( board(), &commit );
106 
107  if( !board()->GetDesignSettings().m_DRCEngine->RulesValid() )
108  {
109  WX_INFOBAR* infobar = frame()->GetInfoBar();
110  wxHyperlinkCtrl* button = new wxHyperlinkCtrl( infobar, wxID_ANY, _("Show DRC rules"),
111  wxEmptyString );
112 
113  button->Bind( wxEVT_COMMAND_HYPERLINK, std::function<void( wxHyperlinkEvent& aEvent )>(
114  [&]( wxHyperlinkEvent& aEvent )
115  {
116  getEditFrame<PCB_EDIT_FRAME>()->ShowBoardSetupDialog( _( "Rules" ) );
117  } ) );
118 
119  infobar->RemoveAllButtons();
120  infobar->AddButton( button );
121 
122  infobar->ShowMessageFor( _( "Zone fills may be inaccurate. DRC rules contain errors." ),
123  10000, wxICON_WARNING );
124  }
125 
126  if( aReporter )
127  filler.SetProgressReporter( aReporter );
128  else
129  filler.InstallNewProgressReporter( aCaller, _( "Fill All Zones" ), 3 );
130 
131  if( filler.Fill( toFill ) )
132  {
133  commit.Push( _( "Fill Zone(s)" ), false );
134  getEditFrame<PCB_EDIT_FRAME>()->m_ZoneFillsDirty = false;
135  }
136  else
137  {
138  commit.Revert();
139  }
140 
141  if( filler.IsDebug() )
142  getEditFrame<PCB_EDIT_FRAME>()->UpdateUserInterface();
143 
144  canvas()->Refresh();
145 
146  // wxWidgets has keyboard focus issues after the progress reporter. Re-setting the focus
147  // here doesn't work, so we delay it to an idle event.
148  canvas()->Bind( wxEVT_IDLE, &ZONE_FILLER_TOOL::singleShotRefocus, this );
149 }
150 
151 
153 {
154  std::vector<ZONE*> toFill;
155 
156  BOARD_COMMIT commit( this );
157 
158  if( ZONE* passedZone = aEvent.Parameter<ZONE*>() )
159  {
160  toFill.push_back( passedZone );
161  }
162  else
163  {
164  for( EDA_ITEM* item : selection() )
165  {
166  if( ZONE* zone = dynamic_cast<ZONE*>( item ) )
167  toFill.push_back( zone );
168  }
169  }
170 
171  ZONE_FILLER filler( board(), &commit );
172  filler.InstallNewProgressReporter( frame(), _( "Fill Zone" ), 4 );
173 
174  if( filler.Fill( toFill ) )
175  commit.Push( _( "Fill Zone(s)" ), false );
176  else
177  commit.Revert();
178 
179  canvas()->Refresh();
180  return 0;
181 }
182 
183 
185 {
186  FillAllZones( frame() );
187  return 0;
188 }
189 
190 
192 {
193  BOARD_COMMIT commit( this );
194 
195  for( EDA_ITEM* item : selection() )
196  {
197  assert( item->Type() == PCB_ZONE_T );
198 
199  ZONE* zone = static_cast<ZONE*>( item );
200 
201  commit.Modify( zone );
202 
203  zone->SetIsFilled( false );
204  zone->ClearFilledPolysList();
205  }
206 
207  commit.Push( _( "Unfill Zone" ) );
208  canvas()->Refresh();
209 
210  return 0;
211 }
212 
213 
215 {
216  BOARD_COMMIT commit( this );
217 
218  for( ZONE* zone : board()->Zones() )
219  {
220  commit.Modify( zone );
221 
222  zone->SetIsFilled( false );
223  zone->ClearFilledPolysList();
224  }
225 
226  commit.Push( _( "Unfill All Zones" ) );
227  canvas()->Refresh();
228 
229  return 0;
230 }
231 
232 
234 {
235  // Zone actions
240 }
void ShowMessageFor(const wxString &aMessage, int aTime, int aFlags=wxICON_INFORMATION)
Show the infobar with the provided message and icon for a specific period of time.
Definition: infobar.cpp:109
COMMIT & Modify(EDA_ITEM *aItem)
Modifies a given item in the model.
Definition: commit.h:103
void AddButton(wxButton *aButton)
Add an already created button to the infobar.
Definition: infobar.cpp:185
BOARD * board() const
int ZoneUnfill(const TOOL_EVENT &aEvent)
static TOOL_ACTION zoneFillAll
Definition: pcb_actions.h:303
A progress reporter for use in multi-threaded environments.
virtual void Revert() override
Revertes the commit by restoring the modifed items state.
int ZoneUnfillAll(const TOOL_EVENT &aEvent)
void singleShotRefocus(wxIdleEvent &)
Refocuses on an idle event (used after the Progress Reporter messes up the focus)
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Function Go()
static TOOL_ACTION zoneFill
Definition: pcb_actions.h:302
void InstallNewProgressReporter(wxWindow *aParent, const wxString &aTitle, int aNumPhases)
Definition: zone_filler.cpp:72
PCB_BASE_EDIT_FRAME * frame() const
bool Fill(std::vector< ZONE * > &aZones, bool aCheck=false, wxWindow *aParent=nullptr)
Definition: zone_filler.cpp:87
void FillAllZones(wxWindow *aCaller, PROGRESS_REPORTER *aReporter=nullptr)
void CheckAllZones(wxWindow *aCaller, PROGRESS_REPORTER *aReporter=nullptr)
const PCBNEW_SELECTION & selection() const
int ZoneFill(const TOOL_EVENT &aEvent)
void SetProgressReporter(PROGRESS_REPORTER *aReporter)
Definition: zone_filler.cpp:80
T Parameter() const
Function Parameter() Returns a non-standard parameter assigned to the event.
Definition: tool_event.h:435
TOOL_EVENT.
Definition: tool_event.h:171
virtual void SetFocus() override
ZONE handles a list of polygons defining a copper zone.
Definition: zone.h:57
class ZONE, a copper pour area
Definition: typeinfo.h:106
bool IsDebug() const
Definition: zone_filler.h:49
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:226
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=NULL) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
static TOOL_ACTION zoneUnfill
Definition: pcb_actions.h:304
BOARD * GetBoard()
void Reset(RESET_REASON aReason) override
Function Reset() Brings the tool to a known, initial state.
A modified version of the wxInfoBar class that allows us to:
Definition: infobar.h:70
void setTransitions() override
Sets up handlers for various events.
#define _(s)
Definition: 3d_actions.cpp:33
EDA_ITEM is a base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:148
virtual void Push(const wxString &aMessage=wxT("A commit"), bool aCreateUndoEntry=true, bool aSetDirtyBit=true) override
Executes the changes.
RESET_REASON
Determines the reason of reset for a tool
Definition: tool_base.h:79
WX_INFOBAR * GetInfoBar()
PCB_DRAW_PANEL_GAL * canvas() const
int ZoneFillAll(const TOOL_EVENT &aEvent)