1 /* 2 * This program source code file is part of KiCad, a free EDA CAD application. 3 * 4 * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com 5 * Copyright (C) 2004-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 SCH_ITEM_H 26 #define SCH_ITEM_H 27 28 #include <unordered_map> 29 #include <unordered_set> 30 31 #include <eda_item.h> 32 #include <plotters/plotter.h> // for PLOT_DASH_TYPE definition 33 34 #include <default_values.h> 35 #include <sch_sheet_path.h> 36 #include <netclass.h> 37 38 class CONNECTION_GRAPH; 39 class SCH_CONNECTION; 40 class SCH_SHEET_PATH; 41 class SCHEMATIC; 42 class LINE_READER; 43 class SCH_EDIT_FRAME; 44 class wxFindReplaceData; 45 class PLOTTER; 46 class NETLIST_OBJECT; 47 class NETLIST_OBJECT_LIST; 48 49 using KIGFX::RENDER_SETTINGS; 50 51 52 enum FIELDS_AUTOPLACED 53 { 54 FIELDS_AUTOPLACED_NO = 0, 55 FIELDS_AUTOPLACED_AUTO, 56 FIELDS_AUTOPLACED_MANUAL 57 }; 58 59 60 enum DANGLING_END_T 61 { 62 UNKNOWN = 0, 63 WIRE_END, 64 BUS_END, 65 JUNCTION_END, 66 PIN_END, 67 LABEL_END, 68 BUS_ENTRY_END, 69 WIRE_ENTRY_END, 70 SHEET_LABEL_END, 71 NO_CONNECT_END, 72 }; 73 74 75 /** 76 * Helper class used to store the state of schematic items that can be connected to 77 * other schematic items. 78 */ 79 class DANGLING_END_ITEM 80 { 81 public: DANGLING_END_ITEM(DANGLING_END_T aType,EDA_ITEM * aItem,const wxPoint & aPosition)82 DANGLING_END_ITEM( DANGLING_END_T aType, EDA_ITEM* aItem, const wxPoint& aPosition ) 83 { 84 m_item = aItem; 85 m_type = aType; 86 m_pos = aPosition; 87 m_parent = aItem; 88 } 89 DANGLING_END_ITEM(DANGLING_END_T aType,EDA_ITEM * aItem,const wxPoint & aPosition,const EDA_ITEM * aParent)90 DANGLING_END_ITEM( DANGLING_END_T aType, EDA_ITEM* aItem, const wxPoint& aPosition, 91 const EDA_ITEM* aParent ) 92 { 93 m_item = aItem; 94 m_type = aType; 95 m_pos = aPosition; 96 m_parent = aParent; 97 } 98 99 bool operator==( const DANGLING_END_ITEM& aB ) const 100 { 101 return GetItem() == aB.GetItem() 102 && GetPosition() == aB.GetPosition() 103 && GetType() == aB.GetType() 104 && GetParent() == aB.GetParent(); 105 } 106 107 bool operator!=( const DANGLING_END_ITEM& aB ) const 108 { 109 return GetItem() != aB.GetItem() 110 || GetPosition() != aB.GetPosition() 111 || GetType() != aB.GetType() 112 || GetParent() != aB.GetParent();; 113 } 114 115 bool operator<( const DANGLING_END_ITEM& rhs ) const 116 { 117 return( m_pos.x < rhs.m_pos.x || ( m_pos.x == rhs.m_pos.x && m_pos.y < rhs.m_pos.y ) 118 || ( m_pos == rhs.m_pos && m_item < rhs.m_item ) ); 119 } 120 GetPosition()121 wxPoint GetPosition() const { return m_pos; } GetItem()122 EDA_ITEM* GetItem() const { return m_item; } GetParent()123 const EDA_ITEM* GetParent() const { return m_parent; } GetType()124 DANGLING_END_T GetType() const { return m_type; } 125 126 private: 127 EDA_ITEM* m_item; /// A pointer to the connectable object. 128 wxPoint m_pos; /// The position of the connection point. 129 DANGLING_END_T m_type; /// The type of connection of #m_item. 130 const EDA_ITEM* m_parent; /// A pointer to the parent object (in the case of pins) 131 }; 132 133 134 typedef std::unordered_set<SCH_ITEM*> SCH_ITEM_SET; 135 136 137 /** 138 * Simple container to manage line stroke parameters. 139 */ 140 class STROKE_PARAMS 141 { 142 public: 143 STROKE_PARAMS( int aWidth = Mils2iu( DEFAULT_LINE_WIDTH_MILS ), 144 PLOT_DASH_TYPE aPlotStyle = PLOT_DASH_TYPE::DEFAULT, 145 const COLOR4D& aColor = COLOR4D::UNSPECIFIED ) : m_width(aWidth)146 m_width( aWidth ), 147 m_plotstyle( aPlotStyle ), 148 m_color( aColor ) 149 { 150 } 151 GetWidth()152 int GetWidth() const { return m_width; } SetWidth(int aWidth)153 void SetWidth( int aWidth ) { m_width = aWidth; } 154 GetPlotStyle()155 PLOT_DASH_TYPE GetPlotStyle() const { return m_plotstyle; } SetPlotStyle(PLOT_DASH_TYPE aPlotStyle)156 void SetPlotStyle( PLOT_DASH_TYPE aPlotStyle ) { m_plotstyle = aPlotStyle; } 157 GetColor()158 COLOR4D GetColor() const { return m_color; } SetColor(const COLOR4D & aColor)159 void SetColor( const COLOR4D& aColor ) { m_color = aColor; } 160 161 bool operator!=( const STROKE_PARAMS& aOther ) 162 { 163 return m_width != aOther.m_width 164 || m_plotstyle != aOther.m_plotstyle 165 || m_color != aOther.m_color; 166 } 167 168 private: 169 int m_width; 170 PLOT_DASH_TYPE m_plotstyle; 171 COLOR4D m_color; 172 }; 173 174 175 /** 176 * Base class for any item which can be embedded within the #SCHEMATIC container class, 177 * and therefore instances of derived classes should only be found in EESCHEMA or other 178 * programs that use class SCHEMATIC and its contents. 179 * 180 * The corresponding class in Pcbnew is #BOARD_ITEM. 181 */ 182 class SCH_ITEM : public EDA_ITEM 183 { 184 public: 185 SCH_ITEM( EDA_ITEM* aParent, KICAD_T aType ); 186 187 SCH_ITEM( const SCH_ITEM& aItem ); 188 189 SCH_ITEM& operator=( const SCH_ITEM& aPin ); 190 191 virtual ~SCH_ITEM(); 192 GetClass()193 virtual wxString GetClass() const override 194 { 195 return wxT( "SCH_ITEM" ); 196 } 197 198 /** 199 * Swap the internal data structures \a aItem with the schematic item. 200 * Obviously, aItem must have the same type than me. 201 * @param aItem The item to swap the data structures with. 202 */ 203 virtual void SwapData( SCH_ITEM* aItem ); 204 205 /** 206 * Routine to create a new copy of given item. 207 * The new object is not put in draw list (not linked). 208 * 209 * @param doClone (default = false) indicates unique values (such as timestamp and 210 * sheet name) should be duplicated. Use only for undo/redo operations. 211 */ 212 SCH_ITEM* Duplicate( bool doClone = false ) const; 213 214 /** 215 * @return true for items which are moved with the anchor point at mouse cursor 216 * and false for items moved with no reference to anchor 217 * Usually return true for small items (labels, junctions) and false for 218 * items which can be large (hierarchical sheets, symbols) 219 */ IsMovableFromAnchorPoint()220 virtual bool IsMovableFromAnchorPoint() const { return true; } 221 GetStoredPos()222 wxPoint& GetStoredPos() { return m_storedPos; } SetStoredPos(const wxPoint & aPos)223 void SetStoredPos( const wxPoint& aPos ) { m_storedPos = aPos; } 224 225 /** 226 * Searches the item hierarchy to find a SCHEMATIC. 227 * 228 * Every SCH_ITEM that lives on a SCH_SCREEN should be parented to either that screen 229 * or another SCH_ITEM on the same screen (for example, pins to their symbols). 230 * 231 * Every SCH_SCREEN should be parented to the SCHEMATIC. 232 * 233 * @note This hierarchy is not the same as the sheet hierarchy! 234 * 235 * @return the parent schematic this item lives on, or nullptr. 236 */ 237 SCHEMATIC* Schematic() const; 238 239 /** 240 * @return true if the object is locked, else false. 241 */ IsLocked()242 virtual bool IsLocked() const { return false; } 243 244 /** 245 * Set the 'lock' status to \a aLocked for of this item. 246 */ SetLocked(bool aLocked)247 virtual void SetLocked( bool aLocked ) {} 248 249 /** 250 * Allow items to support hypertext actions when hovered/clicked. 251 */ IsHypertext()252 virtual bool IsHypertext() const { return false; } 253 DoHypertextMenu(EDA_DRAW_FRAME * aFrame)254 virtual void DoHypertextMenu( EDA_DRAW_FRAME* aFrame ) { } 255 256 /** 257 * Return the layer this item is on. 258 */ GetLayer()259 SCH_LAYER_ID GetLayer() const { return m_layer; } 260 261 /** 262 * Set the layer this item is on. 263 * 264 * @param aLayer The layer number. 265 */ SetLayer(SCH_LAYER_ID aLayer)266 void SetLayer( SCH_LAYER_ID aLayer ) { m_layer = aLayer; } 267 268 /** 269 * Return the layers the item is drawn on (which may be more than its "home" layer) 270 */ 271 void ViewGetLayers( int aLayers[], int& aCount ) const override; 272 273 /** 274 * @return the size of the "pen" that be used to draw or plot this item 275 */ GetPenWidth()276 virtual int GetPenWidth() const { return 0; } 277 278 /** 279 * Print a schematic item. 280 * 281 * Each schematic item should have its own method 282 * 283 * @param aOffset is the drawing offset (usually {0,0} but can be different when moving an 284 * object). 285 */ 286 virtual void Print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset ) = 0; 287 288 /** 289 * Move the item by \a aMoveVector to a new position. 290 */ 291 virtual void Move( const wxPoint& aMoveVector ) = 0; 292 293 /** 294 * Mirror item horizontally about \a aCenter. 295 */ 296 virtual void MirrorHorizontally( int aCenter ) = 0; 297 298 /** 299 * Mirror item vertically about \a aCenter. 300 */ 301 virtual void MirrorVertically( int aCenter ) = 0; 302 303 /** 304 * Rotate the item around \a aCenter 90 degrees in the clockwise direction. 305 */ 306 virtual void Rotate( const wxPoint& aCenter ) = 0; 307 308 /** 309 * Add the schematic item end points to \a aItemList if the item has end points. 310 * 311 * The default version doesn't do anything since many of the schematic object cannot 312 * be tested for dangling ends. If you add a new schematic item that can have a 313 * dangling end ( no connect ), override this method to provide the correct end 314 * points. 315 * 316 * @param aItemList is the list of DANGLING_END_ITEMS to add to. 317 */ GetEndPoints(std::vector<DANGLING_END_ITEM> & aItemList)318 virtual void GetEndPoints( std::vector< DANGLING_END_ITEM >& aItemList ) {} 319 320 /** 321 * Test the schematic item to \a aItemList to check if it's dangling state has changed. 322 * 323 * Note that the return value only true when the state of the test has changed. Use 324 * the IsDangling() method to get the current dangling state of the item. Some of 325 * the schematic objects cannot be tested for a dangling state, the default method 326 * always returns false. Only override the method if the item can be tested for a 327 * dangling state. 328 * 329 * If aSheet is passed a non-null pointer to a SCH_SHEET_PATH, the overridden method can 330 * optionally use it to update sheet-local connectivity information 331 * 332 * @param aItemList is the list of items to test item against. 333 * @param aSheet is the sheet path to update connections for. 334 * @return True if the dangling state has changed from it's current setting. 335 */ 336 virtual bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList, 337 const SCH_SHEET_PATH* aPath = nullptr ) 338 { 339 return false; 340 } 341 IsDangling()342 virtual bool IsDangling() const { return false; } 343 CanConnect(const SCH_ITEM * aItem)344 virtual bool CanConnect( const SCH_ITEM* aItem ) const { return m_layer == aItem->GetLayer(); } 345 346 /** 347 * @return true if the schematic item can connect to another schematic item. 348 */ IsConnectable()349 virtual bool IsConnectable() const { return false; } 350 351 /** 352 * @return true if the given point can start drawing (usually means the anchor is 353 * unused/free/dangling). 354 */ IsPointClickableAnchor(const wxPoint & aPos)355 virtual bool IsPointClickableAnchor( const wxPoint& aPos ) const { return false; } 356 357 /** 358 * Add all the connection points for this item to \a aPoints. 359 * 360 * Not all schematic items have connection points so the default method does nothing. 361 * 362 * @param aPoints is the list of connection points to add to. 363 */ GetConnectionPoints()364 virtual std::vector<wxPoint> GetConnectionPoints() const { return {}; } 365 366 /** 367 * Clears all of the connection items from the list. 368 * 369 * The vector release method is used to prevent the item pointers from being deleted. 370 * Do not use the vector erase method on the connection list. 371 */ ClearConnections()372 void ClearConnections() { m_connections.clear(); } 373 374 /** 375 * Test the item to see if it is connected to \a aPoint. 376 * 377 * @param aPoint is a reference to a wxPoint object containing the coordinates to test. 378 * @return True if connection to \a aPoint exists. 379 */ 380 bool IsConnected( const wxPoint& aPoint ) const; 381 382 /** 383 * Retrieve the connection associated with this object in the given sheet. 384 * 385 * @note The returned value can be nullptr. 386 */ 387 SCH_CONNECTION* Connection( const SCH_SHEET_PATH* aSheet = nullptr ) const; 388 389 /** 390 * Retrieve the set of items connected to this item on the given sheet. 391 */ 392 SCH_ITEM_SET& ConnectedItems( const SCH_SHEET_PATH& aPath ); 393 394 /** 395 * Add a connection link between this item and another. 396 */ 397 void AddConnectionTo( const SCH_SHEET_PATH& aPath, SCH_ITEM* aItem ); 398 399 /** 400 * Create a new connection object associated with this object. 401 * 402 * @param aPath is the sheet path to initialize. 403 */ 404 SCH_CONNECTION* InitializeConnection( const SCH_SHEET_PATH& aPath, CONNECTION_GRAPH* aGraph ); 405 406 SCH_CONNECTION* GetOrInitConnection( const SCH_SHEET_PATH& aPath, CONNECTION_GRAPH* aGraph ); 407 408 /** 409 * Return true if this item should propagate connection info to \a aItem. 410 */ ConnectionPropagatesTo(const EDA_ITEM * aItem)411 virtual bool ConnectionPropagatesTo( const EDA_ITEM* aItem ) const { return true; } 412 IsConnectivityDirty()413 bool IsConnectivityDirty() const { return m_connectivity_dirty; } 414 415 void SetConnectivityDirty( bool aDirty = true ) { m_connectivity_dirty = aDirty; } 416 SetLastResolvedState(const SCH_ITEM * aItem)417 virtual void SetLastResolvedState( const SCH_ITEM* aItem ) { } 418 419 NETCLASSPTR NetClass( const SCH_SHEET_PATH* aSheet = nullptr ) const; 420 421 /** 422 * Return whether the fields have been automatically placed. 423 */ GetFieldsAutoplaced()424 FIELDS_AUTOPLACED GetFieldsAutoplaced() const { return m_fieldsAutoplaced; } 425 SetFieldsAutoplaced()426 void SetFieldsAutoplaced() { m_fieldsAutoplaced = FIELDS_AUTOPLACED_AUTO; } ClearFieldsAutoplaced()427 void ClearFieldsAutoplaced() { m_fieldsAutoplaced = FIELDS_AUTOPLACED_NO; } 428 429 /** 430 * Autoplace fields only if correct to do so automatically. 431 * 432 * Fields that have been moved by hand are not automatically placed. 433 * 434 * @param aScreen is the SCH_SCREEN associated with the current instance of the symbol. 435 */ AutoAutoplaceFields(SCH_SCREEN * aScreen)436 void AutoAutoplaceFields( SCH_SCREEN* aScreen ) 437 { 438 if( GetFieldsAutoplaced() ) 439 AutoplaceFields( aScreen, GetFieldsAutoplaced() == FIELDS_AUTOPLACED_MANUAL ); 440 } 441 AutoplaceFields(SCH_SCREEN * aScreen,bool aManual)442 virtual void AutoplaceFields( SCH_SCREEN* aScreen, bool aManual ) { } 443 RunOnChildren(const std::function<void (SCH_ITEM *)> & aFunction)444 virtual void RunOnChildren( const std::function<void( SCH_ITEM* )>& aFunction ) { } 445 446 /** 447 * Check if this schematic item has line stoke properties. 448 * 449 * @see #STROKE_PARAMS 450 * 451 * @return true if this schematic item support line stroke properties. Otherwise, false. 452 */ HasLineStroke()453 virtual bool HasLineStroke() const { return false; } 454 GetStroke()455 virtual STROKE_PARAMS GetStroke() const { wxCHECK( false, STROKE_PARAMS() ); } 456 SetStroke(const STROKE_PARAMS & aStroke)457 virtual void SetStroke( const STROKE_PARAMS& aStroke ) { wxCHECK( false, /* void */ ); } 458 459 /** 460 * Plot the schematic item to \a aPlotter. 461 * 462 * @param aPlotter is the #PLOTTER object to plot to. 463 */ 464 virtual void Plot( PLOTTER* aPlotter ) const; 465 466 virtual bool operator <( const SCH_ITEM& aItem ) const; 467 468 private: 469 friend class CONNECTION_GRAPH; 470 471 /** 472 * Provide the object specific test to see if it is connected to \a aPosition. 473 * 474 * @note Override this function if the derived object can be connect to another 475 * object such as a wire, bus, or junction. Do not override this function 476 * for objects that cannot have connections. The default will always return 477 * false. This functions is call through the public function IsConnected() 478 * which performs tests common to all schematic items before calling the 479 * item specific connection testing. 480 * 481 * @param aPosition is a reference to a wxPoint object containing the test position. 482 * @return True if connection to \a aPosition exists. 483 */ doIsConnected(const wxPoint & aPosition)484 virtual bool doIsConnected( const wxPoint& aPosition ) const { return false; } 485 486 protected: 487 SCH_LAYER_ID m_layer; 488 EDA_ITEMS m_connections; // List of items connected to this item. 489 FIELDS_AUTOPLACED m_fieldsAutoplaced; // indicates status of field autoplacement 490 wxPoint m_storedPos; // a temporary variable used in some move commands 491 // to store a initial pos of the item or mouse cursor 492 493 /// Store pointers to other items that are connected to this one, per sheet. 494 std::unordered_map<SCH_SHEET_PATH, SCH_ITEM_SET> m_connected_items; 495 496 /// Store connectivity information, per sheet. 497 std::unordered_map<SCH_SHEET_PATH, SCH_CONNECTION*> m_connection_map; 498 499 bool m_connectivity_dirty; 500 }; 501 502 #endif /* SCH_ITEM_H */ 503