KiCad PCB EDA Suite
sch_bus_entry.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) 2004 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2004-2019 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 #include <fctsys.h>
26 #include <gr_basic.h>
27 #include <macros.h>
28 #include <sch_draw_panel.h>
29 #include <trigo.h>
30 #include <common.h>
31 #include <richio.h>
32 #include <plotter.h>
33 #include <bitmaps.h>
34 #include <eeschema_config.h>
35 #include <general.h>
36 #include <sch_bus_entry.h>
37 #include <sch_line.h>
38 #include <sch_text.h>
39 
40 
41 SCH_BUS_ENTRY_BASE::SCH_BUS_ENTRY_BASE( KICAD_T aType, const wxPoint& pos, char shape ) :
42  SCH_ITEM( NULL, aType )
43 {
44  m_pos = pos;
45  m_size.x = Mils2iu( 100 );
46  m_size.y = Mils2iu( 100 );
47 
48  if( shape == '/' )
49  m_size.y *= -1;
50 
52 }
53 
54 
57 {
59  m_connected_bus_item = nullptr;
60 }
61 
62 
63 SCH_BUS_BUS_ENTRY::SCH_BUS_BUS_ENTRY( const wxPoint& pos, char shape ) :
65 {
67  m_connected_bus_items[0] = nullptr;
68  m_connected_bus_items[1] = nullptr;
69 }
70 
71 
73 {
74  return new SCH_BUS_WIRE_ENTRY( *this );
75 }
76 
77 
79 {
80  return new SCH_BUS_BUS_ENTRY( *this );
81 }
82 
83 
84 bool SCH_BUS_ENTRY_BASE::doIsConnected( const wxPoint& aPosition ) const
85 {
86  return ( m_pos == aPosition || m_End() == aPosition );
87 }
88 
89 
91 {
92  return wxPoint( m_pos.x + m_size.x, m_pos.y + m_size.y );
93 }
94 
95 
97 {
98  SCH_BUS_ENTRY_BASE* item = dynamic_cast<SCH_BUS_ENTRY_BASE*>( aItem );
99  wxCHECK_RET( item, wxT( "Cannot swap bus entry data with invalid item." ) );
100 
101  std::swap( m_pos, item->m_pos );
102  std::swap( m_size, item->m_size );
103 }
104 
105 
106 void SCH_BUS_ENTRY_BASE::ViewGetLayers( int aLayers[], int& aCount ) const
107 {
108  aCount = 2;
109  aLayers[0] = Type() == SCH_BUS_BUS_ENTRY_T ? LAYER_BUS : LAYER_WIRE;
110  aLayers[1] = LAYER_SELECTION_SHADOWS;
111 }
112 
113 
115 {
116  EDA_RECT box;
117 
118  box.SetOrigin( m_pos );
119  box.SetEnd( m_End() );
120 
121  box.Normalize();
122  box.Inflate( GetPenSize() / 2 );
123 
124  return box;
125 }
126 
127 
129 {
130  return GetDefaultWireThickness();
131 }
132 
133 
135 {
136  return GetDefaultBusThickness();
137 }
138 
139 
140 void SCH_BUS_WIRE_ENTRY::GetEndPoints( std::vector< DANGLING_END_ITEM >& aItemList )
141 {
142  DANGLING_END_ITEM item( WIRE_ENTRY_END, this, m_pos );
143  aItemList.push_back( item );
144 
145  DANGLING_END_ITEM item1( WIRE_ENTRY_END, this, m_End() );
146  aItemList.push_back( item1 );
147 }
148 
149 
150 void SCH_BUS_BUS_ENTRY::GetEndPoints( std::vector< DANGLING_END_ITEM >& aItemList )
151 {
152  DANGLING_END_ITEM item( BUS_ENTRY_END, this, m_pos );
153  aItemList.push_back( item );
154 
155  DANGLING_END_ITEM item1( BUS_ENTRY_END, this, m_End() );
156  aItemList.push_back( item1 );
157 }
158 
159 
160 void SCH_BUS_ENTRY_BASE::Print( wxDC* aDC, const wxPoint& aOffset )
161 {
163 
164  GRLine( nullptr, aDC, m_pos.x + aOffset.x, m_pos.y + aOffset.y, m_End().x + aOffset.x,
165  m_End().y + aOffset.y, GetPenSize(), color );
166 }
167 
168 
169 void SCH_BUS_ENTRY_BASE::MirrorX( int aXaxis_position )
170 {
171  MIRROR( m_pos.y, aXaxis_position );
172  m_size.y = -m_size.y;
173 }
174 
175 
176 void SCH_BUS_ENTRY_BASE::MirrorY( int aYaxis_position )
177 {
178  MIRROR( m_pos.x, aYaxis_position );
179  m_size.x = -m_size.x;
180 }
181 
182 
184 {
185  RotatePoint( &m_pos, aPosition, 900 );
186  RotatePoint( &m_size.x, &m_size.y, 900 );
187 }
188 
189 
190 bool SCH_BUS_WIRE_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList )
191 {
192  bool previousStateStart = m_isDanglingStart;
193  bool previousStateEnd = m_isDanglingEnd;
194 
196 
197  // Wires and buses are stored in the list as a pair, start and end. This
198  // variable holds the start position from one iteration so it can be used
199  // when the end position is found.
200  wxPoint seg_start;
201 
202  // Store the connection type and state for the start (0) and end (1)
203  bool has_wire[2] = { false };
204  bool has_bus[2] = { false };
205 
206  for( DANGLING_END_ITEM& each_item : aItemList )
207  {
208  if( each_item.GetItem() == this )
209  continue;
210 
211  switch( each_item.GetType() )
212  {
213  case WIRE_START_END:
214  case WIRE_END_END:
215  if( m_pos == each_item.GetPosition() )
216  has_wire[0] = true;
217  else if( m_End() == each_item.GetPosition() )
218  has_wire[1] = true;
219 
220  break;
221 
222  case BUS_START_END:
223  seg_start = each_item.GetPosition();
224  break;
225 
226  case BUS_END_END:
227  if( IsPointOnSegment( seg_start, each_item.GetPosition(), m_pos ) )
228  has_bus[0] = true;
229  else if( IsPointOnSegment( seg_start, each_item.GetPosition(), m_End() ) )
230  has_bus[1] = true;
231 
232  break;
233 
234  default:
235  break;
236  }
237  }
238 
239  // A bus-wire entry is connected at both ends if it has a bus and a wire on its
240  // ends. Otherwise, we connect only one end (in the case of a wire-wire or bus-bus)
241  if( ( has_wire[0] && has_bus[1] ) || ( has_wire[1] && has_bus[0] ) )
243  else if( has_wire[0] || has_bus[0] )
244  m_isDanglingStart = false;
245  else if( has_wire[1] || has_bus[1] )
246  m_isDanglingEnd = false;
247 
248  return (previousStateStart != m_isDanglingStart) || (previousStateEnd != m_isDanglingEnd);
249 }
250 
251 
252 bool SCH_BUS_BUS_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList )
253 {
254  bool previousStateStart = m_isDanglingStart;
255  bool previousStateEnd = m_isDanglingEnd;
256 
258 
259  // Wires and buses are stored in the list as a pair, start and end. This
260  // variable holds the start position from one iteration so it can be used
261  // when the end position is found.
262  wxPoint seg_start;
263 
264  for( DANGLING_END_ITEM& each_item : aItemList )
265  {
266  if( each_item.GetItem() == this )
267  continue;
268 
269  switch( each_item.GetType() )
270  {
271  case BUS_START_END:
272  seg_start = each_item.GetPosition();
273  break;
274  case BUS_END_END:
275  if( IsPointOnSegment( seg_start, each_item.GetPosition(), m_pos ) )
276  m_isDanglingStart = false;
277  if( IsPointOnSegment( seg_start, each_item.GetPosition(), m_End() ) )
278  m_isDanglingEnd = false;
279  break;
280  default:
281  break;
282  }
283  }
284 
285  return (previousStateStart != m_isDanglingStart) || (previousStateEnd != m_isDanglingEnd);
286 }
287 
288 
290 {
292 }
293 
294 
295 void SCH_BUS_ENTRY_BASE::GetConnectionPoints( std::vector< wxPoint >& aPoints ) const
296 {
297  aPoints.push_back( m_pos );
298  aPoints.push_back( m_End() );
299 }
300 
301 
303 {
304  return wxString( _( "Bus to Wire Entry" ) );
305 }
306 
307 
309 {
310  return wxString( _( "Bus to Bus Entry" ) );
311 }
312 
313 
315 {
316  return add_line2bus_xpm;
317 }
318 
319 
321 {
322  return add_bus2bus_xpm;
323 }
324 
325 
326 bool SCH_BUS_ENTRY_BASE::HitTest( const wxPoint& aPosition, int aAccuracy ) const
327 {
328  // Insure minimum accuracy
329  if( aAccuracy == 0 )
330  aAccuracy = ( GetPenSize() / 2 ) + 4;
331 
332  return TestSegmentHit( aPosition, m_pos, m_End(), aAccuracy );
333 }
334 
335 
336 bool SCH_BUS_ENTRY_BASE::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
337 {
338  EDA_RECT rect = aRect;
339 
340  rect.Inflate( aAccuracy );
341 
342  if( aContained )
343  return rect.Contains( GetBoundingBox() );
344 
345  return rect.Intersects( GetBoundingBox() );
346 }
347 
348 
350 {
351  aPlotter->SetCurrentLineWidth( GetPenSize() );
352  aPlotter->SetColor( GetLayerColor( GetLayer() ) );
353  aPlotter->MoveTo( m_pos );
354  aPlotter->FinishTo( m_End() );
355 }
356 
357 
359 {
360  switch( aShape )
361  {
362  case '\\':
363  if( m_size.y < 0 )
364  m_size.y = -m_size.y;
365  break;
366 
367  case '/':
368  if( m_size.y > 0 )
369  m_size.y = -m_size.y;
370  break;
371  }
372 }
373 
374 
376 {
377  if( GetSize().y < 0 )
378  return '/';
379  else
380  return '\\';
381 }
382 
383 
385 {
386  wxString msg;
387 
388  switch( GetLayer() )
389  {
390  default:
391  case LAYER_WIRE: msg = _( "Wire" ); break;
392  case LAYER_BUS: msg = _( "Bus" ); break;
393  }
394 
395  aList.push_back( MSG_PANEL_ITEM( _( "Bus Entry Type" ), msg, DARKCYAN ) );
396  if( auto conn = Connection( *g_CurrentSheet ) )
397  {
398 #if defined(DEBUG)
399  conn->AppendDebugInfoToMsgPanel( aList );
400 #else
401  conn->AppendInfoToMsgPanel( aList );
402 #endif
403  }
404 }
405 
406 
408 {
409  // Don't generate connections between bus entries and buses, since there is
410  // a connectivity change at that point (e.g. A[7..0] to A7)
411  if( ( aItem->Type() == SCH_LINE_T ) &&
412  ( static_cast<const SCH_LINE*>( aItem )->GetLayer() == LAYER_BUS ) )
413  {
414  return false;
415  }
416 
417  // Don't generate connections between bus entries and bus labels that happen
418  // to land at the same point on the bus wire as this bus entry
419  if( ( aItem->Type() == SCH_LABEL_T ) &&
420  SCH_CONNECTION::IsBusLabel( static_cast<const SCH_LABEL*>( aItem )->GetText() ) )
421  {
422  return false;
423  }
424 
425  // Don't generate connections between two bus-wire entries
426  if( aItem->Type() == SCH_BUS_WIRE_ENTRY_T )
427  return false;
428 
429  return true;
430 }
void FinishTo(const wxPoint &pos)
Definition: plotter.h:270
EDA_UNITS
Definition: common.h:72
void GetMsgPanelInfo(EDA_UNITS aUnits, std::vector< MSG_PANEL_ITEM > &aList) override
Function GetMsgPanelInfo populates aList of MSG_PANEL_ITEM objects with it's internal state for displ...
SCH_LAYER_ID m_Layer
Definition: sch_item.h:141
bool UpdateDanglingState(std::vector< DANGLING_END_ITEM > &aItemList) override
Function IsDanglingStateChanged tests the schematic item to aItemList to check if it's dangling state...
int GetDefaultWireThickness()
Default line thickness used to draw/plot wires.
bool doIsConnected(const wxPoint &aPosition) const override
Function doIsConnected provides the object specific test to see if it is connected to aPosition.
PNG memory record (file in memory).
Definition: bitmap_def.h:29
int GetPenSize() const override
Function GetPenSize virtual pure.
void GetConnectionPoints(std::vector< wxPoint > &aPoints) const override
Function GetConnectionPoints add all the connection points for this item to aPoints.
SCH_ITEM * m_connected_bus_item
Pointer to the bus item (usually a bus wire) connected to this bus-wire entry, if it is connected to ...
SCH_ITEM * m_connected_bus_items[2]
Pointer to the bus items (usually bus wires) connected to this bus-bus entry (either or both may be n...
const BITMAP_OPAQUE add_line2bus_xpm[1]
virtual void SetColor(COLOR4D color)=0
bool UpdateDanglingState(std::vector< DANGLING_END_ITEM > &aItemList) override
Function IsDanglingStateChanged tests the schematic item to aItemList to check if it's dangling state...
static bool IsBusLabel(const wxString &aLabel)
Test if aLabel has a bus notation.
int color
Definition: DXF_plotter.cpp:61
SCH_BUS_WIRE_ENTRY(const wxPoint &pos=wxPoint(0, 0), char shape='\\')
void ViewGetLayers(int aLayers[], int &aCount) const override
Function ViewGetLayers() Returns the all the layers within the VIEW the object is painted on.
void Rotate(wxPoint aPosition) override
Function Rotate rotates the item around aPosition 90 degrees in the clockwise direction.
bool IsPointOnSegment(const wxPoint &aSegStart, const wxPoint &aSegEnd, const wxPoint &aTestPoint)
Function IsPointOnSegment.
Definition: trigo.cpp:42
void SetOrigin(const wxPoint &pos)
Definition: eda_rect.h:131
const BITMAP_OPAQUE add_bus2bus_xpm[1]
Definition: add_bus2bus.cpp:38
wxPoint m_pos
Definition: sch_bus_entry.h:44
wxSize m_size
Definition: sch_bus_entry.h:45
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:208
COLOR4D GetLayerColor(SCH_LAYER_ID aLayer)
bool Contains(const wxPoint &aPoint) const
Function Contains.
void SwapData(SCH_ITEM *aItem) override
Function SwapData swap the internal data structures aItem with the schematic item.
KICAD_T
Enum KICAD_T is the set of class identification values, stored in EDA_ITEM::m_StructType.
Definition: typeinfo.h:78
This file contains miscellaneous commonly used macros and functions.
bool TestSegmentHit(const wxPoint &aRefPoint, wxPoint aStart, wxPoint aEnd, int aDist)
Function TestSegmentHit test for hit on line segment i.e.
Definition: trigo.cpp:129
Base class for a bus or wire entry.
Definition: sch_bus_entry.h:41
virtual bool ConnectionPropagatesTo(const EDA_ITEM *aItem) const override
Returns true if this item should propagate connection info to aItem.
EDA_ITEM * Clone() const override
Function Clone creates a duplicate of this item with linked list members set to NULL.
void MIRROR(T &aPoint, const T &aMirrorRef)
Definition: macros.h:123
SCH_BUS_ENTRY_BASE(KICAD_T aType, const wxPoint &pos=wxPoint(0, 0), char shape='\\')
wxString GetSelectMenuText(EDA_UNITS aUnits) const override
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
virtual int GetPenSize() const
Function GetPenSize virtual pure.
Definition: sch_item.h:231
EDA_ITEM * Clone() const override
Function Clone creates a duplicate of this item with linked list members set to NULL.
bool IsDangling() const override
#define NULL
SCH_SHEET_PATH * g_CurrentSheet
With the new connectivity algorithm, many more places than before want to know what the current sheet...
void SetEnd(int x, int y)
Definition: eda_rect.h:192
bool m_isDanglingStart
Definition: sch_bus_entry.h:46
void GetEndPoints(std::vector< DANGLING_END_ITEM > &aItemList) override
Function GetEndPoints adds the schematic item end points to aItemList if the item has end points.
char GetBusEntryShape() const
void SetBusEntryShape(char aShape)
wxPoint m_End() const
int GetPenSize() const override
Function GetPenSize virtual pure.
void Print(wxDC *aDC, const wxPoint &aOffset) override
Function Print Print a schematic item.
void GRLine(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int width, COLOR4D Color, wxPenStyle aStyle)
Definition: gr_basic.cpp:230
SCH_CONNECTION * Connection(const SCH_SHEET_PATH &aPath) const
Retrieves the connection associated with this object in the given sheet Note: the returned value can ...
Definition: sch_item.cpp:128
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes.
SCH_LAYER_ID GetLayer() const
Function GetLayer returns the layer this item is on.
Definition: sch_item.h:212
void MoveTo(const wxPoint &pos)
Definition: plotter.h:260
void Normalize()
Function Normalize ensures that the height ant width are positive.
Base plotter engine class.
Definition: plotter.h:103
wxSize GetSize() const
Definition: sch_bus_entry.h:77
void GetEndPoints(std::vector< DANGLING_END_ITEM > &aItemList) override
Function GetEndPoints adds the schematic item end points to aItemList if the item has end points.
wxString GetSelectMenuText(EDA_UNITS aUnits) const override
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
#define _(s)
Definition: 3d_actions.cpp:31
void MirrorX(int aXaxis_position) override
Function MirrorX mirrors item relative to the X axis about aXaxis_position.
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
bool m_isDanglingEnd
Definition: sch_bus_entry.h:46
SCH_BUS_BUS_ENTRY(const wxPoint &pos=wxPoint(0, 0), char shape='\\')
void Plot(PLOTTER *aPlotter) override
Function Plot plots the schematic item to aPlotter.
EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boards.
Definition: base_struct.h:163
The common library.
std::vector< MSG_PANEL_ITEM > MSG_PANEL_ITEMS
Definition: msgpanel.h:102
bool Intersects(const EDA_RECT &aRect) const
Function Intersects tests for a common area between rectangles.
DANGLING_END_ITEM is a helper class used to store the state of schematic items that can be connected ...
Definition: sch_item.h:67
EDA_MSG_ITEM is used EDA_MSG_PANEL as the item type for displaying messages.
Definition: msgpanel.h:53
BITMAP_DEF GetMenuImage() const override
Function GetMenuImage returns a pointer to an image to be used in menus.
bool HitTest(const wxPoint &aPosition, int aAccuracy=0) const override
Function HitTest tests if aPosition is contained within or on the bounding box of an item.
BITMAP_DEF GetMenuImage() const override
Function GetMenuImage returns a pointer to an image to be used in menus.
void MirrorY(int aYaxis_position) override
Function MirrorY mirrors item relative to the Y axis about aYaxis_position.
SCH_ITEM is a base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:136
int GetDefaultBusThickness()
Default line thickness used to draw/plot busses.
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
KICAD_T Type() const
Function Type()
Definition: base_struct.h:207
virtual void SetCurrentLineWidth(int width, void *aData=NULL)=0
Set the line width for the next drawing.
COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39