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.

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