You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

438 lines
11 KiB

18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
17 years ago
17 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2006 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
  5. * Copyright (C) 1992-2024 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. #include <algorithm>
  25. #include <bitmaps.h>
  26. #include <general.h>
  27. #include <geometry/shape_line_chain.h>
  28. #include <string_utils.h>
  29. #include <plotters/plotter.h>
  30. #include <sch_draw_panel.h>
  31. #include <sch_edit_frame.h>
  32. #include <sch_sheet.h>
  33. #include <sch_sheet_pin.h>
  34. #include <sch_painter.h>
  35. #include <schematic.h>
  36. #include <trigo.h>
  37. SCH_SHEET_PIN::SCH_SHEET_PIN( SCH_SHEET* parent, const VECTOR2I& pos, const wxString& text ) :
  38. SCH_HIERLABEL( pos, text, SCH_SHEET_PIN_T ),
  39. m_edge( SHEET_SIDE::UNDEFINED )
  40. {
  41. SetParent( parent );
  42. wxASSERT( parent );
  43. m_layer = LAYER_SHEETLABEL;
  44. SetTextPos( pos );
  45. if( parent->IsVerticalOrientation() )
  46. SetSide( SHEET_SIDE::TOP );
  47. else
  48. SetSide( SHEET_SIDE::LEFT );
  49. m_shape = LABEL_FLAG_SHAPE::L_INPUT;
  50. m_isDangling = true;
  51. m_number = 2;
  52. }
  53. EDA_ITEM* SCH_SHEET_PIN::Clone() const
  54. {
  55. return new SCH_SHEET_PIN( *this );
  56. }
  57. void SCH_SHEET_PIN::Print( const SCH_RENDER_SETTINGS* aSettings, int aUnit, int aBodyStyle,
  58. const VECTOR2I& aOffset, bool aForceNoFill, bool aDimmed )
  59. {
  60. // The icon selection is handle by the virtual method CreateGraphicShape called by ::Print
  61. SCH_HIERLABEL::Print( aSettings, aUnit, aBodyStyle, aOffset, aForceNoFill, aDimmed );
  62. }
  63. void SCH_SHEET_PIN::SwapData( SCH_ITEM* aItem )
  64. {
  65. SCH_HIERLABEL::SwapData( aItem );
  66. wxCHECK_RET( aItem->Type() == SCH_SHEET_PIN_T,
  67. wxString::Format( "SCH_SHEET_PIN object cannot swap data with %s object.",
  68. aItem->GetClass() ) );
  69. SCH_SHEET_PIN* pin = static_cast<SCH_SHEET_PIN*>( aItem );
  70. std::swap( m_number, pin->m_number );
  71. std::swap( m_edge, pin->m_edge );
  72. }
  73. bool SCH_SHEET_PIN::operator==( const SCH_SHEET_PIN* aPin ) const
  74. {
  75. return aPin == this;
  76. }
  77. int SCH_SHEET_PIN::GetPenWidth() const
  78. {
  79. if( Schematic() )
  80. return Schematic()->Settings().m_DefaultLineWidth;
  81. return schIUScale.MilsToIU( DEFAULT_LINE_WIDTH_MILS );
  82. }
  83. void SCH_SHEET_PIN::SetNumber( int aNumber )
  84. {
  85. wxASSERT( aNumber >= 2 );
  86. m_number = aNumber;
  87. }
  88. void SCH_SHEET_PIN::SetSide( SHEET_SIDE aEdge )
  89. {
  90. SCH_SHEET* Sheet = GetParent();
  91. // use SHEET_UNDEFINED_SIDE to adjust text orientation without changing edge
  92. switch( aEdge )
  93. {
  94. case SHEET_SIDE::LEFT:
  95. m_edge = aEdge;
  96. SetTextX( Sheet->m_pos.x );
  97. SetSpinStyle( SPIN_STYLE::RIGHT ); // Orientation horiz inverse
  98. break;
  99. case SHEET_SIDE::RIGHT:
  100. m_edge = aEdge;
  101. SetTextX( Sheet->m_pos.x + Sheet->m_size.x );
  102. SetSpinStyle( SPIN_STYLE::LEFT ); // Orientation horiz normal
  103. break;
  104. case SHEET_SIDE::TOP:
  105. m_edge = aEdge;
  106. SetTextY( Sheet->m_pos.y );
  107. SetSpinStyle( SPIN_STYLE::BOTTOM ); // Orientation vert BOTTOM
  108. break;
  109. case SHEET_SIDE::BOTTOM:
  110. m_edge = aEdge;
  111. SetTextY( Sheet->m_pos.y + Sheet->m_size.y );
  112. SetSpinStyle( SPIN_STYLE::UP ); // Orientation vert UP
  113. break;
  114. default:
  115. break;
  116. }
  117. }
  118. enum SHEET_SIDE SCH_SHEET_PIN::GetSide() const
  119. {
  120. return m_edge;
  121. }
  122. void SCH_SHEET_PIN::ConstrainOnEdge( VECTOR2I aPos, bool aAllowEdgeSwitch )
  123. {
  124. SCH_SHEET* sheet = GetParent();
  125. if( sheet == nullptr )
  126. return;
  127. int leftSide = sheet->m_pos.x;
  128. int rightSide = sheet->m_pos.x + sheet->m_size.x;
  129. int topSide = sheet->m_pos.y;
  130. int botSide = sheet->m_pos.y + sheet->m_size.y;
  131. SHAPE_LINE_CHAIN sheetEdge;
  132. sheetEdge.Append( leftSide, topSide );
  133. sheetEdge.Append( rightSide, topSide );
  134. sheetEdge.Append( rightSide, botSide );
  135. sheetEdge.Append( leftSide, botSide );
  136. sheetEdge.Append( leftSide, topSide );
  137. if( aAllowEdgeSwitch )
  138. {
  139. switch( sheetEdge.NearestSegment( aPos ) )
  140. {
  141. case 0: SetSide( SHEET_SIDE::TOP ); break;
  142. case 1: SetSide( SHEET_SIDE::RIGHT ); break;
  143. case 2: SetSide( SHEET_SIDE::BOTTOM ); break;
  144. case 3: SetSide( SHEET_SIDE::LEFT ); break;
  145. default: wxASSERT( "Invalid segment number" );
  146. }
  147. }
  148. else
  149. {
  150. SetSide( GetSide() );
  151. }
  152. switch( GetSide() )
  153. {
  154. case SHEET_SIDE::RIGHT:
  155. case SHEET_SIDE::LEFT:
  156. SetTextY( aPos.y );
  157. if( GetTextPos().y < topSide )
  158. SetTextY( topSide );
  159. if( GetTextPos().y > botSide )
  160. SetTextY( botSide );
  161. break;
  162. case SHEET_SIDE::BOTTOM:
  163. case SHEET_SIDE::TOP:
  164. SetTextX( aPos.x );
  165. if( GetTextPos().x < leftSide )
  166. SetTextX( leftSide );
  167. if( GetTextPos().x > rightSide )
  168. SetTextX( rightSide );
  169. break;
  170. case SHEET_SIDE::UNDEFINED:
  171. wxASSERT( "Undefined sheet side" );
  172. }
  173. }
  174. void SCH_SHEET_PIN::MirrorVertically( int aCenter )
  175. {
  176. int p = GetTextPos().y - aCenter;
  177. SetTextY( aCenter - p );
  178. switch( m_edge )
  179. {
  180. case SHEET_SIDE::TOP: SetSide( SHEET_SIDE::BOTTOM ); break;
  181. case SHEET_SIDE::BOTTOM: SetSide( SHEET_SIDE::TOP ); break;
  182. default: break;
  183. }
  184. }
  185. void SCH_SHEET_PIN::MirrorHorizontally( int aCenter )
  186. {
  187. int p = GetTextPos().x - aCenter;
  188. SetTextX( aCenter - p );
  189. switch( m_edge )
  190. {
  191. case SHEET_SIDE::LEFT: SetSide( SHEET_SIDE::RIGHT ); break;
  192. case SHEET_SIDE::RIGHT: SetSide( SHEET_SIDE::LEFT ); break;
  193. default: break;
  194. }
  195. }
  196. void SCH_SHEET_PIN::Rotate( const VECTOR2I& aCenter, bool aRotateCCW )
  197. {
  198. VECTOR2I pt = GetTextPos();
  199. VECTOR2I delta = pt - aCenter;
  200. RotatePoint( pt, aCenter, aRotateCCW ? ANGLE_90 : ANGLE_270 );
  201. SHEET_SIDE oldSide = GetSide();
  202. ConstrainOnEdge( pt, true );
  203. // If the new side is the same as the old side, instead mirror across the center of that side.
  204. if( GetSide() == oldSide )
  205. {
  206. switch( GetSide() )
  207. {
  208. case SHEET_SIDE::TOP:
  209. case SHEET_SIDE::BOTTOM:
  210. SetTextPos( VECTOR2I( aCenter.x - delta.x, GetTextPos().y ) );
  211. break;
  212. case SHEET_SIDE::LEFT:
  213. case SHEET_SIDE::RIGHT:
  214. SetTextPos( VECTOR2I( GetTextPos().x, aCenter.y - delta.y ) );
  215. break;
  216. default:
  217. break;
  218. }
  219. }
  220. // If the new side is opposite to the old side, instead mirror across the center of an adjacent
  221. // side.
  222. else if( GetSide() == GetOppositeSide( oldSide ) )
  223. {
  224. switch( GetSide() )
  225. {
  226. case SHEET_SIDE::TOP:
  227. case SHEET_SIDE::BOTTOM:
  228. SetTextPos( VECTOR2I( aCenter.x + delta.x, GetTextPos().y ) );
  229. break;
  230. case SHEET_SIDE::LEFT:
  231. case SHEET_SIDE::RIGHT:
  232. SetTextPos( VECTOR2I( GetTextPos().x, aCenter.y + delta.y ) );
  233. break;
  234. default:
  235. break;
  236. }
  237. }
  238. }
  239. void SCH_SHEET_PIN::CreateGraphicShape( const RENDER_SETTINGS* aSettings,
  240. std::vector<VECTOR2I>& aPoints, const VECTOR2I& aPos ) const
  241. {
  242. /*
  243. * These are the same icon shapes as SCH_HIERLABEL but the graphic icon is slightly
  244. * different in 2 cases:
  245. * for INPUT type the icon is the OUTPUT shape of SCH_HIERLABEL
  246. * for OUTPUT type the icon is the INPUT shape of SCH_HIERLABEL
  247. */
  248. LABEL_FLAG_SHAPE shape = m_shape;
  249. switch( shape )
  250. {
  251. case LABEL_FLAG_SHAPE::L_INPUT: shape = LABEL_FLAG_SHAPE::L_OUTPUT; break;
  252. case LABEL_FLAG_SHAPE::L_OUTPUT: shape = LABEL_FLAG_SHAPE::L_INPUT; break;
  253. default: break;
  254. }
  255. SCH_HIERLABEL::CreateGraphicShape( aSettings, aPoints, aPos, shape );
  256. }
  257. void SCH_SHEET_PIN::GetEndPoints( std::vector<DANGLING_END_ITEM>& aItemList )
  258. {
  259. DANGLING_END_ITEM item( SHEET_LABEL_END, this, GetTextPos() );
  260. aItemList.push_back( item );
  261. }
  262. wxString SCH_SHEET_PIN::GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const
  263. {
  264. return wxString::Format( _( "Hierarchical Sheet Pin %s" ),
  265. KIUI::EllipsizeMenuText( GetText() ) );
  266. }
  267. BITMAPS SCH_SHEET_PIN::GetMenuImage() const
  268. {
  269. return BITMAPS::add_hierar_pin;
  270. }
  271. bool SCH_SHEET_PIN::HitTest( const VECTOR2I& aPoint, int aAccuracy ) const
  272. {
  273. BOX2I rect = GetBoundingBox();
  274. rect.Inflate( aAccuracy );
  275. return rect.Contains( aPoint );
  276. }
  277. bool SCH_SHEET_PIN::operator==( const SCH_ITEM& aOther ) const
  278. {
  279. if( aOther.Type() != Type() )
  280. return false;
  281. const SCH_SHEET_PIN* other = static_cast<const SCH_SHEET_PIN*>( &aOther );
  282. return m_edge == other->m_edge && m_number == other->m_number
  283. && SCH_HIERLABEL::operator==( aOther );
  284. }
  285. double SCH_SHEET_PIN::Similarity( const SCH_ITEM& aOther ) const
  286. {
  287. if( aOther.Type() != Type() )
  288. return 0.0;
  289. const SCH_SHEET_PIN* other = static_cast<const SCH_SHEET_PIN*>( &aOther );
  290. double similarity = 1.0;
  291. if( m_edge != other->m_edge )
  292. similarity *= 0.9;
  293. if( m_number != other->m_number )
  294. similarity *= 0.9;
  295. similarity *= SCH_HIERLABEL::Similarity( aOther );
  296. return similarity;
  297. }
  298. bool SCH_SHEET_PIN::HasConnectivityChanges( const SCH_ITEM* aItem,
  299. const SCH_SHEET_PATH* aInstance ) const
  300. {
  301. // Do not compare to ourself.
  302. if( aItem == this )
  303. return false;
  304. const SCH_SHEET_PIN* pin = dynamic_cast<const SCH_SHEET_PIN*>( aItem );
  305. // Don't compare against a different SCH_ITEM.
  306. wxCHECK( pin, false );
  307. if( GetPosition() != pin->GetPosition() )
  308. return true;
  309. return GetText() != pin->GetText();
  310. }
  311. #if defined(DEBUG)
  312. void SCH_SHEET_PIN::Show( int nestLevel, std::ostream& os ) const
  313. {
  314. // XML output:
  315. NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() << ">"
  316. << " pin_name=\"" << TO_UTF8( GetText() )
  317. << '"' << "/>\n" << std::flush;
  318. }
  319. #endif
  320. static struct SCH_SHEET_PIN_DESC
  321. {
  322. SCH_SHEET_PIN_DESC()
  323. {
  324. PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
  325. REGISTER_TYPE( SCH_SHEET_PIN );
  326. propMgr.AddTypeCast( new TYPE_CAST<SCH_SHEET_PIN, SCH_HIERLABEL> );
  327. propMgr.AddTypeCast( new TYPE_CAST<SCH_SHEET_PIN, SCH_LABEL_BASE> );
  328. propMgr.AddTypeCast( new TYPE_CAST<SCH_SHEET_PIN, SCH_TEXT> );
  329. propMgr.AddTypeCast( new TYPE_CAST<SCH_SHEET_PIN, EDA_TEXT> );
  330. propMgr.InheritsAfter( TYPE_HASH( SCH_SHEET_PIN ), TYPE_HASH( SCH_HIERLABEL ) );
  331. }
  332. } _SCH_SHEET_PIN_DESC;