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.

1802 lines
46 KiB

15 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
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
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) 2009 Jean-Pierre Charras, jp.charras at wanadoo.fr
  5. * Copyright (C) 1992-2011 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. * @file sch_text.cpp
  26. * @brief Code for handling schematic sheet labels.
  27. */
  28. #include <fctsys.h>
  29. #include <gr_basic.h>
  30. #include <macros.h>
  31. #include <trigo.h>
  32. #include <eeschema_id.h>
  33. #include <class_drawpanel.h>
  34. #include <drawtxt.h>
  35. #include <wxEeschemaStruct.h>
  36. #include <plot_common.h>
  37. #include <base_units.h>
  38. #include <msgpanel.h>
  39. #include <general.h>
  40. #include <protos.h>
  41. #include <sch_text.h>
  42. #include <class_netlist_object.h>
  43. extern void IncrementLabelMember( wxString& name );
  44. /* Names of sheet label types. */
  45. const char* SheetLabelType[] =
  46. {
  47. "Input",
  48. "Output",
  49. "BiDi",
  50. "3State",
  51. "UnSpc",
  52. "???"
  53. };
  54. /* Coding polygons for global symbol graphic shapes.
  55. * the first parml is the number of corners
  56. * others are the corners coordinates in reduced units
  57. * the real coordinate is the reduced coordinate * text half size
  58. */
  59. static int TemplateIN_HN[] = { 6, 0, 0, -1, -1, -2, -1, -2, 1, -1, 1, 0, 0 };
  60. static int TemplateIN_HI[] = { 6, 0, 0, 1, 1, 2, 1, 2, -1, 1, -1, 0, 0 };
  61. static int TemplateIN_UP[] = { 6, 0, 0, 1, -1, 1, -2, -1, -2, -1, -1, 0, 0 };
  62. static int TemplateIN_BOTTOM[] = { 6, 0, 0, 1, 1, 1, 2, -1, 2, -1, 1, 0, 0 };
  63. static int TemplateOUT_HN[] = { 6, -2, 0, -1, 1, 0, 1, 0, -1, -1, -1, -2, 0 };
  64. static int TemplateOUT_HI[] = { 6, 2, 0, 1, -1, 0, -1, 0, 1, 1, 1, 2, 0 };
  65. static int TemplateOUT_UP[] = { 6, 0, -2, 1, -1, 1, 0, -1, 0, -1, -1, 0, -2 };
  66. static int TemplateOUT_BOTTOM[] = { 6, 0, 2, 1, 1, 1, 0, -1, 0, -1, 1, 0, 2 };
  67. static int TemplateUNSPC_HN[] = { 5, 0, -1, -2, -1, -2, 1, 0, 1, 0, -1 };
  68. static int TemplateUNSPC_HI[] = { 5, 0, -1, 2, -1, 2, 1, 0, 1, 0, -1 };
  69. static int TemplateUNSPC_UP[] = { 5, 1, 0, 1, -2, -1, -2, -1, 0, 1, 0 };
  70. static int TemplateUNSPC_BOTTOM[] = { 5, 1, 0, 1, 2, -1, 2, -1, 0, 1, 0 };
  71. static int TemplateBIDI_HN[] = { 5, 0, 0, -1, -1, -2, 0, -1, 1, 0, 0 };
  72. static int TemplateBIDI_HI[] = { 5, 0, 0, 1, -1, 2, 0, 1, 1, 0, 0 };
  73. static int TemplateBIDI_UP[] = { 5, 0, 0, -1, -1, 0, -2, 1, -1, 0, 0 };
  74. static int TemplateBIDI_BOTTOM[] = { 5, 0, 0, -1, 1, 0, 2, 1, 1, 0, 0 };
  75. static int Template3STATE_HN[] = { 5, 0, 0, -1, -1, -2, 0, -1, 1, 0, 0 };
  76. static int Template3STATE_HI[] = { 5, 0, 0, 1, -1, 2, 0, 1, 1, 0, 0 };
  77. static int Template3STATE_UP[] = { 5, 0, 0, -1, -1, 0, -2, 1, -1, 0, 0 };
  78. static int Template3STATE_BOTTOM[] = { 5, 0, 0, -1, 1, 0, 2, 1, 1, 0, 0 };
  79. static int* TemplateShape[5][4] =
  80. {
  81. { TemplateIN_HN, TemplateIN_UP, TemplateIN_HI, TemplateIN_BOTTOM },
  82. { TemplateOUT_HN, TemplateOUT_UP, TemplateOUT_HI, TemplateOUT_BOTTOM },
  83. { TemplateBIDI_HN, TemplateBIDI_UP, TemplateBIDI_HI, TemplateBIDI_BOTTOM },
  84. { Template3STATE_HN, Template3STATE_UP, Template3STATE_HI, Template3STATE_BOTTOM },
  85. { TemplateUNSPC_HN, TemplateUNSPC_UP, TemplateUNSPC_HI, TemplateUNSPC_BOTTOM }
  86. };
  87. SCH_TEXT::SCH_TEXT( const wxPoint& pos, const wxString& text, KICAD_T aType ) :
  88. SCH_ITEM( NULL, aType ),
  89. EDA_TEXT( text )
  90. {
  91. m_Layer = LAYER_NOTES;
  92. m_Pos = pos;
  93. m_shape = 0;
  94. m_isDangling = false;
  95. m_MultilineAllowed = true;
  96. m_schematicOrientation = 0;
  97. }
  98. SCH_TEXT::SCH_TEXT( const SCH_TEXT& aText ) :
  99. SCH_ITEM( aText ),
  100. EDA_TEXT( aText )
  101. {
  102. m_Pos = aText.m_Pos;
  103. m_shape = aText.m_shape;
  104. m_MultilineAllowed = aText.m_MultilineAllowed;
  105. m_schematicOrientation = aText.m_schematicOrientation;
  106. m_isDangling = false;
  107. }
  108. EDA_ITEM* SCH_TEXT::Clone() const
  109. {
  110. return new SCH_TEXT( *this );
  111. }
  112. void SCH_TEXT::IncrementLabel()
  113. {
  114. IncrementLabelMember( m_Text );
  115. }
  116. wxPoint SCH_TEXT::GetSchematicTextOffset() const
  117. {
  118. wxPoint text_offset;
  119. // add a small offset (TXTMARGE) to x ( or y) position to allow a text to
  120. // be on a wire or a line and be readable
  121. switch( m_schematicOrientation )
  122. {
  123. default:
  124. case 0: /* Horiz Normal Orientation (left justified) */
  125. text_offset.y = -TXTMARGE;
  126. break;
  127. case 1: /* Vert Orientation UP */
  128. text_offset.x = -TXTMARGE;
  129. break;
  130. case 2: /* Horiz Orientation - Right justified */
  131. text_offset.y = -TXTMARGE;
  132. break;
  133. case 3: /* Vert Orientation BOTTOM */
  134. text_offset.x = -TXTMARGE;
  135. break;
  136. }
  137. return text_offset;
  138. }
  139. bool SCH_TEXT::Matches( wxFindReplaceData& aSearchData, void* aAuxData, wxPoint * aFindLocation )
  140. {
  141. wxLogTrace( traceFindItem, wxT( " item " ) + GetSelectMenuText() );
  142. if( SCH_ITEM::Matches( m_Text, aSearchData ) )
  143. {
  144. EDA_RECT BoundaryBox = GetBoundingBox();
  145. if( aFindLocation )
  146. *aFindLocation = BoundaryBox.Centre();
  147. return true;
  148. }
  149. return false;
  150. }
  151. void SCH_TEXT::MirrorY( int aYaxis_position )
  152. {
  153. // Text is NOT really mirrored; it is moved to a suitable horizontal position
  154. switch( GetOrientation() )
  155. {
  156. case 0: // horizontal text
  157. SetOrientation( 2 );
  158. break;
  159. case 2: // invert horizontal text
  160. SetOrientation( 0 );
  161. break;
  162. case 1: // Vert Orientation UP
  163. case 3: // Vert Orientation BOTTOM
  164. default:
  165. break;
  166. }
  167. m_Pos.x -= aYaxis_position;
  168. NEGATE( m_Pos.x );
  169. m_Pos.x += aYaxis_position;
  170. }
  171. void SCH_TEXT::MirrorX( int aXaxis_position )
  172. {
  173. // Text is NOT really mirrored; it is moved to a suitable vertical position
  174. switch( GetOrientation() )
  175. {
  176. case 1: // Vert Orientation UP
  177. SetOrientation( 3 );
  178. break;
  179. case 3: // Vert Orientation BOTTOM
  180. SetOrientation( 1 );
  181. break;
  182. case 0: // horizontal text
  183. case 2: // invert horizontal text
  184. default:
  185. break;
  186. }
  187. m_Pos.y -= aXaxis_position;
  188. NEGATE( m_Pos.y );
  189. m_Pos.y += aXaxis_position;
  190. }
  191. void SCH_TEXT::Rotate( wxPoint aPosition )
  192. {
  193. int dy;
  194. RotatePoint( &m_Pos, aPosition, 900 );
  195. SetOrientation( (GetOrientation() + 1) % 4 );
  196. switch( GetOrientation() )
  197. {
  198. case 0: // horizontal text
  199. dy = m_Size.y;
  200. break;
  201. case 1: // Vert Orientation UP
  202. dy = 0;
  203. break;
  204. case 2: // invert horizontal text
  205. dy = m_Size.y;
  206. break;
  207. case 3: // Vert Orientation BOTTOM
  208. dy = 0;
  209. break;
  210. default:
  211. dy = 0;
  212. break;
  213. }
  214. m_Pos.y += dy;
  215. }
  216. void SCH_TEXT::SetOrientation( int aOrientation )
  217. {
  218. m_schematicOrientation = aOrientation;
  219. switch( m_schematicOrientation )
  220. {
  221. default:
  222. case 0: /* Horiz Normal Orientation (left justified) */
  223. m_Orient = TEXT_ORIENT_HORIZ;
  224. m_HJustify = GR_TEXT_HJUSTIFY_LEFT;
  225. m_VJustify = GR_TEXT_VJUSTIFY_BOTTOM;
  226. break;
  227. case 1: /* Vert Orientation UP */
  228. m_Orient = TEXT_ORIENT_VERT;
  229. m_HJustify = GR_TEXT_HJUSTIFY_LEFT;
  230. m_VJustify = GR_TEXT_VJUSTIFY_BOTTOM;
  231. break;
  232. case 2: /* Horiz Orientation - Right justified */
  233. m_Orient = TEXT_ORIENT_HORIZ;
  234. m_HJustify = GR_TEXT_HJUSTIFY_RIGHT;
  235. m_VJustify = GR_TEXT_VJUSTIFY_BOTTOM;
  236. break;
  237. case 3: /* Vert Orientation BOTTOM */
  238. m_Orient = TEXT_ORIENT_VERT;
  239. m_HJustify = GR_TEXT_HJUSTIFY_RIGHT;
  240. m_VJustify = GR_TEXT_VJUSTIFY_BOTTOM;
  241. break;
  242. }
  243. }
  244. void SCH_TEXT::SwapData( SCH_ITEM* aItem )
  245. {
  246. SCH_TEXT* item = (SCH_TEXT*) aItem;
  247. EXCHG( m_Text, item->m_Text );
  248. EXCHG( m_Pos, item->m_Pos );
  249. EXCHG( m_Size, item->m_Size );
  250. EXCHG( m_Thickness, item->m_Thickness );
  251. EXCHG( m_shape, item->m_shape );
  252. EXCHG( m_Orient, item->m_Orient );
  253. EXCHG( m_Layer, item->m_Layer );
  254. EXCHG( m_HJustify, item->m_HJustify );
  255. EXCHG( m_VJustify, item->m_VJustify );
  256. EXCHG( m_isDangling, item->m_isDangling );
  257. EXCHG( m_schematicOrientation, item->m_schematicOrientation );
  258. }
  259. int SCH_TEXT::GetPenSize() const
  260. {
  261. int pensize = m_Thickness;
  262. if( pensize == 0 ) // Use default values for pen size
  263. {
  264. if( m_Bold )
  265. pensize = GetPenSizeForBold( m_Size.x );
  266. else
  267. pensize = GetDefaultLineThickness();
  268. }
  269. // Clip pen size for small texts:
  270. pensize = Clamp_Text_PenSize( pensize, m_Size, m_Bold );
  271. return pensize;
  272. }
  273. void SCH_TEXT::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, const wxPoint& aOffset,
  274. GR_DRAWMODE DrawMode, EDA_COLOR_T Color )
  275. {
  276. EDA_COLOR_T color;
  277. int linewidth = ( m_Thickness == 0 ) ? GetDefaultLineThickness() : m_Thickness;
  278. EDA_RECT* clipbox = panel? panel->GetClipBox() : NULL;
  279. linewidth = Clamp_Text_PenSize( linewidth, m_Size, m_Bold );
  280. if( Color >= 0 )
  281. color = Color;
  282. else
  283. color = GetLayerColor( m_Layer );
  284. GRSetDrawMode( DC, DrawMode );
  285. wxPoint text_offset = aOffset + GetSchematicTextOffset();
  286. EXCHG( linewidth, m_Thickness ); // Set the minimum width
  287. EDA_TEXT::Draw( clipbox, DC, text_offset, color, DrawMode, FILLED, UNSPECIFIED_COLOR );
  288. EXCHG( linewidth, m_Thickness ); // set initial value
  289. if( m_isDangling )
  290. DrawDanglingSymbol( panel, DC, m_Pos + aOffset, color );
  291. // Enable these line to draw the bounding box (debug tests purposes only)
  292. #if 0
  293. {
  294. EDA_RECT BoundaryBox = GetBoundingBox();
  295. GRRect( clipbox, DC, BoundaryBox, 0, BROWN );
  296. }
  297. #endif
  298. }
  299. bool SCH_TEXT::Save( FILE* aFile ) const
  300. {
  301. bool success = true;
  302. const char* shape = "~";
  303. if( m_Italic )
  304. shape = "Italic";
  305. // For compatibility reason, the text must be saved in only one text line
  306. // so we replace all E.O.L. by \\n
  307. wxString text = m_Text;
  308. text.Replace( wxT("\n"), wxT( "\\n" ) );
  309. // Here we should have no CR or LF character in line
  310. // This is not always the case if a multiline text was copied (using a copy/paste function)
  311. // from a text that uses E.O.L characters that differs from the current EOL format
  312. // This is mainly the case under Linux using LF symbol when copying a text from
  313. // Windows (using CRLF symbol)
  314. // So we must just remove the extra CR left (or LF left under MacOSX)
  315. for( unsigned ii = 0; ii < text.Len(); )
  316. {
  317. if( text[ii] == 0x0A || text[ii] == 0x0D )
  318. text.erase( ii, 1 );
  319. else
  320. ii++;
  321. }
  322. if( fprintf( aFile, "Text Notes %-4d %-4d %-4d %-4d %s %d\n%s\n",
  323. m_Pos.x, m_Pos.y, m_schematicOrientation, m_Size.x,
  324. shape, m_Thickness, TO_UTF8( text ) ) == EOF )
  325. {
  326. success = false;
  327. }
  328. return success;
  329. }
  330. bool SCH_TEXT::Load( LINE_READER& aLine, wxString& aErrorMsg )
  331. {
  332. char Name1[256];
  333. char Name2[256];
  334. char Name3[256];
  335. int thickness = 0, size = 0, orient = 0;
  336. Name1[0] = 0; Name2[0] = 0; Name3[0] = 0;
  337. char* sline = (char*) aLine;
  338. while( ( *sline != ' ' ) && *sline )
  339. sline++;
  340. // sline points the start of parameters
  341. int ii = sscanf( sline, "%s %d %d %d %d %s %s %d", Name1, &m_Pos.x, &m_Pos.y,
  342. &orient, &size, Name2, Name3, &thickness );
  343. if( ii < 4 )
  344. {
  345. aErrorMsg.Printf( wxT( "Eeschema file text load error at line %d" ),
  346. aLine.LineNumber() );
  347. return false;
  348. }
  349. if( !aLine.ReadLine() )
  350. {
  351. aErrorMsg.Printf( wxT( "Eeschema file text load error at line %d" ),
  352. aLine.LineNumber() );
  353. return false;
  354. }
  355. if( size == 0 )
  356. size = DEFAULT_SIZE_TEXT;
  357. char* text = strtok( (char*) aLine, "\n\r" );
  358. if( text == NULL )
  359. {
  360. aErrorMsg.Printf( wxT( "Eeschema file text load error at line %d" ),
  361. aLine.LineNumber() );
  362. return false;
  363. }
  364. wxString val = FROM_UTF8( text );
  365. for( ; ; )
  366. {
  367. int i = val.find( wxT( "\\n" ) );
  368. if( i == wxNOT_FOUND )
  369. break;
  370. val.erase( i, 2 );
  371. val.insert( i, wxT( "\n" ) );
  372. }
  373. m_Text = val;
  374. m_Size.x = m_Size.y = size;
  375. SetOrientation( orient );
  376. if( isdigit( Name3[0] ) )
  377. {
  378. thickness = atol( Name3 );
  379. m_Bold = ( thickness != 0 );
  380. m_Thickness = m_Bold ? GetPenSizeForBold( size ) : 0;
  381. }
  382. if( strnicmp( Name2, "Italic", 6 ) == 0 )
  383. m_Italic = 1;
  384. return true;
  385. }
  386. void SCH_TEXT::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
  387. {
  388. // Normal text labels cannot be tested for dangling ends.
  389. if( Type() == SCH_TEXT_T )
  390. return;
  391. DANGLING_END_ITEM item( LABEL_END, this, m_Pos );
  392. aItemList.push_back( item );
  393. }
  394. bool SCH_TEXT::IsDanglingStateChanged( std::vector< DANGLING_END_ITEM >& aItemList )
  395. {
  396. // Normal text labels cannot be tested for dangling ends.
  397. if( Type() == SCH_TEXT_T )
  398. return false;
  399. bool previousState = m_isDangling;
  400. m_isDangling = true;
  401. for( unsigned ii = 0; ii < aItemList.size(); ii++ )
  402. {
  403. DANGLING_END_ITEM& item = aItemList[ii];
  404. if( item.GetItem() == this )
  405. continue;
  406. switch( item.GetType() )
  407. {
  408. case PIN_END:
  409. case LABEL_END:
  410. case SHEET_LABEL_END:
  411. if( m_Pos == item.GetPosition() )
  412. m_isDangling = false;
  413. break;
  414. case WIRE_START_END:
  415. case BUS_START_END:
  416. {
  417. // These schematic items have created 2 DANGLING_END_ITEM one per end. But being
  418. // a paranoid programmer, I'll check just in case.
  419. ii++;
  420. wxCHECK_MSG( ii < aItemList.size(), previousState != m_isDangling,
  421. wxT( "Dangling end type list overflow. Bad programmer!" ) );
  422. DANGLING_END_ITEM & nextItem = aItemList[ii];
  423. m_isDangling = !IsPointOnSegment( item.GetPosition(), nextItem.GetPosition(), m_Pos );
  424. }
  425. break;
  426. default:
  427. break;
  428. }
  429. if( !m_isDangling )
  430. break;
  431. }
  432. return previousState != m_isDangling;
  433. }
  434. bool SCH_TEXT::IsSelectStateChanged( const wxRect& aRect )
  435. {
  436. bool previousState = IsSelected();
  437. if( aRect.Contains( m_Pos ) )
  438. SetFlags( SELECTED );
  439. else
  440. SetFlags( SELECTED );
  441. return previousState != IsSelected();
  442. }
  443. void SCH_TEXT::GetConnectionPoints( std::vector< wxPoint >& aPoints ) const
  444. {
  445. // Normal text labels do not have connection points. All others do.
  446. if( Type() == SCH_TEXT_T )
  447. return;
  448. aPoints.push_back( m_Pos );
  449. }
  450. const EDA_RECT SCH_TEXT::GetBoundingBox() const
  451. {
  452. // We must pass the effective text thickness to GetTextBox
  453. // when calculating the bounding box
  454. int linewidth = ( m_Thickness == 0 ) ? GetDefaultLineThickness() : m_Thickness;
  455. linewidth = Clamp_Text_PenSize( linewidth, m_Size, m_Bold );
  456. EDA_RECT rect = GetTextBox( -1, linewidth );
  457. if( m_Orient ) // Rotate rect
  458. {
  459. wxPoint pos = rect.GetOrigin();
  460. wxPoint end = rect.GetEnd();
  461. RotatePoint( &pos, m_Pos, m_Orient );
  462. RotatePoint( &end, m_Pos, m_Orient );
  463. rect.SetOrigin( pos );
  464. rect.SetEnd( end );
  465. }
  466. rect.Normalize();
  467. return rect;
  468. }
  469. wxString SCH_TEXT::GetSelectMenuText() const
  470. {
  471. wxString tmp = GetText();
  472. tmp.Replace( wxT( "\n" ), wxT( " " ) );
  473. tmp.Replace( wxT( "\r" ), wxT( " " ) );
  474. tmp.Replace( wxT( "\t" ), wxT( " " ) );
  475. tmp =( tmp.Length() > 15 ) ? tmp.Left( 12 ) + wxT( "..." ) : tmp;
  476. wxString msg;
  477. msg.Printf( _( "Graphic Text %s" ), GetChars( tmp ) );
  478. return msg;
  479. }
  480. void SCH_TEXT::GetNetListItem( NETLIST_OBJECT_LIST& aNetListItems,
  481. SCH_SHEET_PATH* aSheetPath )
  482. {
  483. if( GetLayer() == LAYER_NOTES || GetLayer() == LAYER_SHEETLABEL )
  484. return;
  485. NETLIST_OBJECT* item = new NETLIST_OBJECT();
  486. item->m_SheetPath = *aSheetPath;
  487. item->m_SheetPathInclude = *aSheetPath;
  488. item->m_Comp = (SCH_ITEM*) this;
  489. item->m_Type = NET_LABEL;
  490. if( GetLayer() == LAYER_GLOBLABEL )
  491. item->m_Type = NET_GLOBLABEL;
  492. else if( GetLayer() == LAYER_HIERLABEL )
  493. item->m_Type = NET_HIERLABEL;
  494. item->m_Label = m_Text;
  495. item->m_Start = item->m_End = m_Pos;
  496. aNetListItems.push_back( item );
  497. /* If a bus connects to label */
  498. if( IsBusLabel( m_Text ) )
  499. item->ConvertBusToNetListItems( aNetListItems );
  500. }
  501. bool SCH_TEXT::HitTest( const wxPoint& aPosition, int aAccuracy ) const
  502. {
  503. EDA_RECT bBox = GetBoundingBox();
  504. bBox.Inflate( aAccuracy );
  505. return bBox.Contains( aPosition );
  506. }
  507. bool SCH_TEXT::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
  508. {
  509. EDA_RECT bBox = GetBoundingBox();
  510. bBox.Inflate( aAccuracy );
  511. if( aContained )
  512. return aRect.Contains( bBox );
  513. return aRect.Intersects( bBox );
  514. }
  515. void SCH_TEXT::Plot( PLOTTER* aPlotter )
  516. {
  517. static std::vector <wxPoint> Poly;
  518. EDA_COLOR_T color = GetLayerColor( GetLayer() );
  519. wxPoint textpos = m_Pos + GetSchematicTextOffset();
  520. int thickness = GetPenSize();
  521. aPlotter->SetCurrentLineWidth( thickness );
  522. if( m_MultilineAllowed )
  523. {
  524. std::vector<wxPoint> positions;
  525. wxArrayString* list = wxStringSplit( m_Text, '\n' );
  526. positions.reserve( list->Count() );
  527. GetPositionsOfLinesOfMultilineText(positions, list->Count() );
  528. for( unsigned ii = 0; ii < list->Count(); ii++ )
  529. {
  530. wxString& txt = list->Item( ii );
  531. aPlotter->Text( positions[ii], color, txt, m_Orient, m_Size, m_HJustify,
  532. m_VJustify, thickness, m_Italic, m_Bold );
  533. }
  534. delete (list);
  535. }
  536. else
  537. {
  538. aPlotter->Text( textpos, color, m_Text, m_Orient, m_Size, m_HJustify,
  539. m_VJustify, thickness, m_Italic, m_Bold );
  540. }
  541. /* Draw graphic symbol for global or hierarchical labels */
  542. CreateGraphicShape( Poly, m_Pos );
  543. aPlotter->SetCurrentLineWidth( GetPenSize() );
  544. if( Poly.size() )
  545. aPlotter->PlotPoly( Poly, NO_FILL );
  546. }
  547. /*
  548. * Display the type, shape, size and some other props to the Message panel
  549. */
  550. void SCH_TEXT::GetMsgPanelInfo( MSG_PANEL_ITEMS& aList )
  551. {
  552. wxString msg;
  553. switch( Type() )
  554. {
  555. case SCH_TEXT_T:
  556. msg = _( "Graphic text" );
  557. break;
  558. case SCH_LABEL_T:
  559. msg = _( "Label" );
  560. break;
  561. case SCH_GLOBAL_LABEL_T:
  562. msg = _( "Global label" );
  563. break;
  564. case SCH_HIERARCHICAL_LABEL_T:
  565. msg = _( "Hierarchical label" );
  566. break;
  567. case SCH_SHEET_PIN_T:
  568. msg = _( "Hierarchical Sheet Pin" );
  569. break;
  570. default:
  571. return;
  572. }
  573. aList.push_back( MSG_PANEL_ITEM( msg, GetText(), DARKCYAN ) );
  574. switch( GetOrientation() )
  575. {
  576. case 0: // horizontal text
  577. msg = _( "Horizontal" );
  578. break;
  579. case 1: // Vert Orientation UP
  580. msg = _( "Vertical up" );
  581. break;
  582. case 2: // invert horizontal text
  583. msg = _( "Horizontal invert" );
  584. break;
  585. case 3: // Vert Orientation Down
  586. msg = _( "Vertical down" );
  587. break;
  588. default:
  589. msg = wxT( "???" );
  590. break;
  591. }
  592. aList.push_back( MSG_PANEL_ITEM( _( "Orientation" ), msg, BROWN ) );
  593. wxString textStyle[] = { _( "Normal" ), _( "Italic" ), _( "Bold" ), _( "Bold Italic" ) };
  594. int style = 0;
  595. if( m_Italic )
  596. style = 1;
  597. if( m_Bold )
  598. style += 2;
  599. aList.push_back( MSG_PANEL_ITEM( _("Style"), textStyle[style], BROWN ) );
  600. // Display electricat type if it is relevant
  601. if( (Type() == SCH_GLOBAL_LABEL_T) ||
  602. (Type() == SCH_HIERARCHICAL_LABEL_T ) ||
  603. (Type() == SCH_SHEET_PIN_T ) )
  604. {
  605. switch( GetShape() )
  606. {
  607. case NET_INPUT: msg = _( "Input" ); break;
  608. case NET_OUTPUT: msg = _( "Output" ); break;
  609. case NET_BIDI: msg = _( "Bidirectional" ); break;
  610. case NET_TRISTATE: msg = _( "Tri-State" ); break;
  611. case NET_UNSPECIFIED: msg = _( "Passive" ); break;
  612. default: msg = wxT( "???" ); break;
  613. }
  614. aList.push_back( MSG_PANEL_ITEM( _( "Type" ), msg, BLUE ) );
  615. }
  616. // Display text size (X or Y value, with are the same value in Eeschema)
  617. msg = ReturnStringFromValue( g_UserUnit, m_Size.x, true );
  618. aList.push_back( MSG_PANEL_ITEM( _( "Size" ), msg, RED ) );
  619. }
  620. #if defined(DEBUG)
  621. void SCH_TEXT::Show( int nestLevel, std::ostream& os ) const
  622. {
  623. // XML output:
  624. wxString s = GetClass();
  625. NestedSpace( nestLevel, os ) << '<' << s.Lower().mb_str()
  626. << " layer=\"" << m_Layer << '"'
  627. << " shape=\"" << m_shape << '"'
  628. << " dangling=\"" << m_isDangling << '"'
  629. << '>'
  630. << TO_UTF8( m_Text )
  631. << "</" << s.Lower().mb_str() << ">\n";
  632. }
  633. #endif
  634. SCH_LABEL::SCH_LABEL( const wxPoint& pos, const wxString& text ) :
  635. SCH_TEXT( pos, text, SCH_LABEL_T )
  636. {
  637. m_Layer = LAYER_LOCLABEL;
  638. m_shape = NET_INPUT;
  639. m_isDangling = true;
  640. m_MultilineAllowed = false;
  641. }
  642. EDA_ITEM* SCH_LABEL::Clone() const
  643. {
  644. return new SCH_LABEL( *this );
  645. }
  646. wxPoint SCH_LABEL::GetSchematicTextOffset() const
  647. {
  648. return SCH_TEXT::GetSchematicTextOffset();
  649. }
  650. void SCH_LABEL::SetOrientation( int aOrientation )
  651. {
  652. SCH_TEXT::SetOrientation( aOrientation );
  653. }
  654. void SCH_LABEL::MirrorX( int aXaxis_position )
  655. {
  656. // Text is NOT really mirrored; it is moved to a suitable position
  657. switch( GetOrientation() )
  658. {
  659. case 1: // Vert Orientation UP
  660. SetOrientation( 3 );
  661. break;
  662. case 3: // Vert Orientation BOTTOM
  663. SetOrientation( 1 );
  664. break;
  665. case 0: // horizontal text
  666. case 2: // invert horizontal text
  667. default:
  668. break;
  669. }
  670. m_Pos.y -= aXaxis_position;
  671. NEGATE( m_Pos.y );
  672. m_Pos.y += aXaxis_position;
  673. }
  674. void SCH_LABEL::Rotate( wxPoint aPosition )
  675. {
  676. RotatePoint( &m_Pos, aPosition, 900 );
  677. SetOrientation( (GetOrientation() + 1) % 4 );
  678. }
  679. bool SCH_LABEL::Save( FILE* aFile ) const
  680. {
  681. bool success = true;
  682. const char* shape = "~";
  683. if( m_Italic )
  684. shape = "Italic";
  685. if( fprintf( aFile, "Text Label %-4d %-4d %-4d %-4d %s %d\n%s\n",
  686. m_Pos.x, m_Pos.y, m_schematicOrientation, m_Size.x, shape,
  687. m_Thickness, TO_UTF8( m_Text ) ) == EOF )
  688. {
  689. success = false;
  690. }
  691. return success;
  692. }
  693. bool SCH_LABEL::Load( LINE_READER& aLine, wxString& aErrorMsg )
  694. {
  695. char Name1[256];
  696. char Name2[256];
  697. char Name3[256];
  698. int thickness = 0, size = 0, orient = 0;
  699. Name1[0] = 0; Name2[0] = 0; Name3[0] = 0;
  700. char* sline = (char*) aLine;
  701. while( ( *sline != ' ' ) && *sline )
  702. sline++;
  703. // sline points the start of parameters
  704. int ii = sscanf( sline, "%s %d %d %d %d %s %s %d", Name1, &m_Pos.x, &m_Pos.y,
  705. &orient, &size, Name2, Name3, &thickness );
  706. if( ii < 4 )
  707. {
  708. aErrorMsg.Printf( wxT( "Eeschema file label load error at line %d" ),
  709. aLine.LineNumber() );
  710. return false;
  711. }
  712. if( !aLine.ReadLine() )
  713. {
  714. aErrorMsg.Printf( wxT( "Eeschema file label load error atline %d" ),
  715. aLine.LineNumber() );
  716. return false;
  717. }
  718. if( size == 0 )
  719. size = DEFAULT_SIZE_TEXT;
  720. char* text = strtok( (char*) aLine, "\n\r" );
  721. if( text == NULL )
  722. {
  723. aErrorMsg.Printf( wxT( "Eeschema file label load error at line %d" ),
  724. aLine.LineNumber() );
  725. return false;
  726. }
  727. m_Text = FROM_UTF8( text );
  728. m_Size.x = m_Size.y = size;
  729. SetOrientation( orient );
  730. if( isdigit( Name3[0] ) )
  731. {
  732. thickness = atol( Name3 );
  733. m_Bold = ( thickness != 0 );
  734. m_Thickness = m_Bold ? GetPenSizeForBold( size ) : 0;
  735. }
  736. if( stricmp( Name2, "Italic" ) == 0 )
  737. m_Italic = 1;
  738. return true;
  739. }
  740. void SCH_LABEL::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, const wxPoint& offset,
  741. GR_DRAWMODE DrawMode, EDA_COLOR_T Color )
  742. {
  743. SCH_TEXT::Draw( panel, DC, offset, DrawMode, Color );
  744. }
  745. const EDA_RECT SCH_LABEL::GetBoundingBox() const
  746. {
  747. int x, y, dx, dy, length, height;
  748. x = m_Pos.x;
  749. y = m_Pos.y;
  750. int width = (m_Thickness == 0) ? GetDefaultLineThickness() : m_Thickness;
  751. length = LenSize( m_Text );
  752. height = m_Size.y + width;
  753. dx = dy = 0;
  754. switch( m_schematicOrientation )
  755. {
  756. case 0: /* Horiz Normal Orientation (left justified) */
  757. dx = 2 * DANGLING_SYMBOL_SIZE + length;
  758. dy = -2 * DANGLING_SYMBOL_SIZE - height - TXTMARGE;
  759. x -= DANGLING_SYMBOL_SIZE;
  760. y += DANGLING_SYMBOL_SIZE;
  761. break;
  762. case 1: /* Vert Orientation UP */
  763. dx = -2 * DANGLING_SYMBOL_SIZE - height - TXTMARGE;
  764. dy = -2 * DANGLING_SYMBOL_SIZE - length;
  765. x += DANGLING_SYMBOL_SIZE;
  766. y += DANGLING_SYMBOL_SIZE;
  767. break;
  768. case 2: /* Horiz Orientation - Right justified */
  769. dx = -2 * DANGLING_SYMBOL_SIZE - length;
  770. dy = -2 * DANGLING_SYMBOL_SIZE - height - TXTMARGE;
  771. x += DANGLING_SYMBOL_SIZE;
  772. y += DANGLING_SYMBOL_SIZE;
  773. break;
  774. case 3: /* Vert Orientation BOTTOM */
  775. dx = -2 * DANGLING_SYMBOL_SIZE - height - TXTMARGE;
  776. dy = 2 * DANGLING_SYMBOL_SIZE + length;
  777. x += DANGLING_SYMBOL_SIZE;
  778. y -= DANGLING_SYMBOL_SIZE;
  779. break;
  780. }
  781. EDA_RECT box( wxPoint( x, y ), wxSize( dx, dy ) );
  782. box.Normalize();
  783. return box;
  784. }
  785. wxString SCH_LABEL::GetSelectMenuText() const
  786. {
  787. wxString tmp = ( GetText().Length() > 15 ) ? GetText().Left( 12 ) + wxT( "..." ) : GetText();
  788. wxString msg;
  789. msg.Printf( _( "Label %s" ), GetChars(tmp) );
  790. return msg;
  791. }
  792. SCH_GLOBALLABEL::SCH_GLOBALLABEL( const wxPoint& pos, const wxString& text ) :
  793. SCH_TEXT( pos, text, SCH_GLOBAL_LABEL_T )
  794. {
  795. m_Layer = LAYER_GLOBLABEL;
  796. m_shape = NET_BIDI;
  797. m_isDangling = true;
  798. m_MultilineAllowed = false;
  799. }
  800. EDA_ITEM* SCH_GLOBALLABEL::Clone() const
  801. {
  802. return new SCH_GLOBALLABEL( *this );
  803. }
  804. bool SCH_GLOBALLABEL::Save( FILE* aFile ) const
  805. {
  806. bool success = true;
  807. const char* shape = "~";
  808. if( m_Italic )
  809. shape = "Italic";
  810. if( fprintf( aFile, "Text GLabel %-4d %-4d %-4d %-4d %s %s %d\n%s\n",
  811. m_Pos.x, m_Pos.y, m_schematicOrientation, m_Size.x,
  812. SheetLabelType[m_shape], shape, m_Thickness, TO_UTF8( m_Text ) ) == EOF )
  813. {
  814. success = false;
  815. }
  816. return success;
  817. }
  818. bool SCH_GLOBALLABEL::Load( LINE_READER& aLine, wxString& aErrorMsg )
  819. {
  820. char Name1[256];
  821. char Name2[256];
  822. char Name3[256];
  823. int thickness = 0, size = 0, orient = 0;
  824. Name1[0] = 0; Name2[0] = 0; Name3[0] = 0;
  825. char* sline = (char*) aLine;
  826. while( (*sline != ' ' ) && *sline )
  827. sline++;
  828. // sline points the start of parameters
  829. int ii = sscanf( sline, "%s %d %d %d %d %s %s %d", Name1, &m_Pos.x, &m_Pos.y,
  830. &orient, &size, Name2, Name3, &thickness );
  831. if( ii < 4 )
  832. {
  833. aErrorMsg.Printf( wxT( "Eeschema file global label load error at line %d" ),
  834. aLine.LineNumber() );
  835. return false;
  836. }
  837. if( !aLine.ReadLine() )
  838. {
  839. aErrorMsg.Printf( wxT( "Eeschema file global label load error at line %d" ),
  840. aLine.LineNumber() );
  841. return false;
  842. }
  843. if( size == 0 )
  844. size = DEFAULT_SIZE_TEXT;
  845. char* text = strtok( (char*) aLine, "\n\r" );
  846. if( text == NULL )
  847. {
  848. aErrorMsg.Printf( wxT( "Eeschema file global label load error at line %d" ),
  849. aLine.LineNumber() );
  850. return false;
  851. }
  852. m_Text = FROM_UTF8( text );
  853. m_Size.x = m_Size.y = size;
  854. SetOrientation( orient );
  855. m_shape = NET_INPUT;
  856. m_Bold = ( thickness != 0 );
  857. m_Thickness = m_Bold ? GetPenSizeForBold( size ) : 0;
  858. if( stricmp( Name2, SheetLabelType[NET_OUTPUT] ) == 0 )
  859. m_shape = NET_OUTPUT;
  860. if( stricmp( Name2, SheetLabelType[NET_BIDI] ) == 0 )
  861. m_shape = NET_BIDI;
  862. if( stricmp( Name2, SheetLabelType[NET_TRISTATE] ) == 0 )
  863. m_shape = NET_TRISTATE;
  864. if( stricmp( Name2, SheetLabelType[NET_UNSPECIFIED] ) == 0 )
  865. m_shape = NET_UNSPECIFIED;
  866. if( stricmp( Name3, "Italic" ) == 0 )
  867. m_Italic = 1;
  868. return true;
  869. }
  870. void SCH_GLOBALLABEL::MirrorY( int aYaxis_position )
  871. {
  872. /* The global label is NOT really mirrored.
  873. * for an horizontal label, the schematic orientation is changed.
  874. * for a vertical label, the schematic orientation is not changed.
  875. * and the label is moved to a suitable position
  876. */
  877. switch( GetOrientation() )
  878. {
  879. case 0: /* horizontal text */
  880. SetOrientation( 2 );
  881. break;
  882. case 2: /* invert horizontal text*/
  883. SetOrientation( 0 );
  884. break;
  885. }
  886. m_Pos.x -= aYaxis_position;
  887. NEGATE( m_Pos.x );
  888. m_Pos.x += aYaxis_position;
  889. }
  890. void SCH_GLOBALLABEL::MirrorX( int aXaxis_position )
  891. {
  892. switch( GetOrientation() )
  893. {
  894. case 1: /* vertical text */
  895. SetOrientation( 3 );
  896. break;
  897. case 3: /* invert vertical text*/
  898. SetOrientation( 1 );
  899. break;
  900. }
  901. m_Pos.y -= aXaxis_position;
  902. NEGATE( m_Pos.y );
  903. m_Pos.y += aXaxis_position;
  904. }
  905. void SCH_GLOBALLABEL::Rotate( wxPoint aPosition )
  906. {
  907. RotatePoint( &m_Pos, aPosition, 900 );
  908. SetOrientation( (GetOrientation() + 3) % 4 );
  909. }
  910. wxPoint SCH_GLOBALLABEL::GetSchematicTextOffset() const
  911. {
  912. wxPoint text_offset;
  913. int width = (m_Thickness == 0) ? GetDefaultLineThickness() : m_Thickness;
  914. width = Clamp_Text_PenSize( width, m_Size, m_Bold );
  915. int HalfSize = m_Size.x / 2;
  916. int offset = width;
  917. switch( m_shape )
  918. {
  919. case NET_INPUT:
  920. case NET_BIDI:
  921. case NET_TRISTATE:
  922. offset += HalfSize;
  923. break;
  924. case NET_OUTPUT:
  925. case NET_UNSPECIFIED:
  926. offset += TXTMARGE;
  927. break;
  928. default:
  929. break;
  930. }
  931. switch( m_schematicOrientation )
  932. {
  933. case 0: /* Orientation horiz normal */
  934. text_offset.x -= offset;
  935. break;
  936. case 1: /* Orientation vert UP */
  937. text_offset.y -= offset;
  938. break;
  939. case 2: /* Orientation horiz inverse */
  940. text_offset.x += offset;
  941. break;
  942. case 3: /* Orientation vert BOTTOM */
  943. text_offset.y += offset;
  944. break;
  945. }
  946. return text_offset;
  947. }
  948. void SCH_GLOBALLABEL::SetOrientation( int aOrientation )
  949. {
  950. m_schematicOrientation = aOrientation;
  951. switch( m_schematicOrientation )
  952. {
  953. default:
  954. case 0: /* Horiz Normal Orientation */
  955. m_Orient = TEXT_ORIENT_HORIZ;
  956. m_HJustify = GR_TEXT_HJUSTIFY_RIGHT;
  957. m_VJustify = GR_TEXT_VJUSTIFY_CENTER;
  958. break;
  959. case 1: /* Vert Orientation UP */
  960. m_Orient = TEXT_ORIENT_VERT;
  961. m_HJustify = GR_TEXT_HJUSTIFY_LEFT;
  962. m_VJustify = GR_TEXT_VJUSTIFY_CENTER;
  963. break;
  964. case 2: /* Horiz Orientation */
  965. m_Orient = TEXT_ORIENT_HORIZ;
  966. m_HJustify = GR_TEXT_HJUSTIFY_LEFT;
  967. m_VJustify = GR_TEXT_VJUSTIFY_CENTER;
  968. break;
  969. case 3: /* Vert Orientation BOTTOM */
  970. m_Orient = TEXT_ORIENT_VERT;
  971. m_HJustify = GR_TEXT_HJUSTIFY_RIGHT;
  972. m_VJustify = GR_TEXT_VJUSTIFY_CENTER;
  973. break;
  974. }
  975. }
  976. void SCH_GLOBALLABEL::Draw( EDA_DRAW_PANEL* panel,
  977. wxDC* DC,
  978. const wxPoint& aOffset,
  979. GR_DRAWMODE DrawMode,
  980. EDA_COLOR_T Color )
  981. {
  982. static std::vector <wxPoint> Poly;
  983. EDA_COLOR_T color;
  984. wxPoint text_offset = aOffset + GetSchematicTextOffset();
  985. if( Color >= 0 )
  986. color = Color;
  987. else
  988. color = GetLayerColor( m_Layer );
  989. GRSetDrawMode( DC, DrawMode );
  990. int linewidth = (m_Thickness == 0) ? GetDefaultLineThickness() : m_Thickness;
  991. linewidth = Clamp_Text_PenSize( linewidth, m_Size, m_Bold );
  992. EXCHG( linewidth, m_Thickness ); // Set the minimum width
  993. EDA_RECT* clipbox = panel? panel->GetClipBox() : NULL;
  994. EDA_TEXT::Draw( clipbox, DC, text_offset, color, DrawMode, FILLED, UNSPECIFIED_COLOR );
  995. EXCHG( linewidth, m_Thickness ); // set initial value
  996. CreateGraphicShape( Poly, m_Pos + aOffset );
  997. GRPoly( clipbox, DC, Poly.size(), &Poly[0], 0, linewidth, color, color );
  998. if( m_isDangling )
  999. DrawDanglingSymbol( panel, DC, m_Pos + aOffset, color );
  1000. // Enable these line to draw the bounding box (debug tests purposes only)
  1001. #if 0
  1002. {
  1003. EDA_RECT BoundaryBox = GetBoundingBox();
  1004. GRRect( clipbox, DC, BoundaryBox, 0, BROWN );
  1005. }
  1006. #endif
  1007. }
  1008. void SCH_GLOBALLABEL::CreateGraphicShape( std::vector <wxPoint>& aPoints, const wxPoint& Pos )
  1009. {
  1010. int HalfSize = m_Size.y / 2;
  1011. int linewidth = (m_Thickness == 0) ? GetDefaultLineThickness() : m_Thickness;
  1012. linewidth = Clamp_Text_PenSize( linewidth, m_Size, m_Bold );
  1013. aPoints.clear();
  1014. int symb_len = LenSize( m_Text ) + ( TXTMARGE * 2 );
  1015. // Create outline shape : 6 points
  1016. int x = symb_len + linewidth + 3;
  1017. // Use negation bar Y position to calculate full vertical size
  1018. #define Y_CORRECTION 1.3
  1019. // Note: this factor is due to the fact the negation bar Y position
  1020. // does not give exactly the full Y size of text
  1021. // and is experimentally set to this value
  1022. int y = KiROUND( OverbarPositionY( HalfSize ) * Y_CORRECTION );
  1023. // add room for line thickness and space between top of text and graphic shape
  1024. y += linewidth;
  1025. // Starting point(anchor)
  1026. aPoints.push_back( wxPoint( 0, 0 ) );
  1027. aPoints.push_back( wxPoint( 0, -y ) ); // Up
  1028. aPoints.push_back( wxPoint( -x, -y ) ); // left
  1029. aPoints.push_back( wxPoint( -x, 0 ) ); // Up left
  1030. aPoints.push_back( wxPoint( -x, y ) ); // left down
  1031. aPoints.push_back( wxPoint( 0, y ) ); // down
  1032. int x_offset = 0;
  1033. switch( m_shape )
  1034. {
  1035. case NET_INPUT:
  1036. x_offset = -HalfSize;
  1037. aPoints[0].x += HalfSize;
  1038. break;
  1039. case NET_OUTPUT:
  1040. aPoints[3].x -= HalfSize;
  1041. break;
  1042. case NET_BIDI:
  1043. case NET_TRISTATE:
  1044. x_offset = -HalfSize;
  1045. aPoints[0].x += HalfSize;
  1046. aPoints[3].x -= HalfSize;
  1047. break;
  1048. case NET_UNSPECIFIED:
  1049. default:
  1050. break;
  1051. }
  1052. int angle = 0;
  1053. switch( m_schematicOrientation )
  1054. {
  1055. case 0: /* Orientation horiz normal */
  1056. break;
  1057. case 1: /* Orientation vert UP */
  1058. angle = -900;
  1059. break;
  1060. case 2: /* Orientation horiz inverse */
  1061. angle = 1800;
  1062. break;
  1063. case 3: /* Orientation vert BOTTOM */
  1064. angle = 900;
  1065. break;
  1066. }
  1067. // Rotate outlines and move corners in real position
  1068. for( unsigned ii = 0; ii < aPoints.size(); ii++ )
  1069. {
  1070. aPoints[ii].x += x_offset;
  1071. if( angle )
  1072. RotatePoint( &aPoints[ii], angle );
  1073. aPoints[ii] += Pos;
  1074. }
  1075. aPoints.push_back( aPoints[0] ); // closing
  1076. }
  1077. const EDA_RECT SCH_GLOBALLABEL::GetBoundingBox() const
  1078. {
  1079. int x, y, dx, dy, length, height;
  1080. x = m_Pos.x;
  1081. y = m_Pos.y;
  1082. dx = dy = 0;
  1083. int width = (m_Thickness == 0) ? GetDefaultLineThickness() : m_Thickness;
  1084. height = ( (m_Size.y * 15) / 10 ) + width + 2 * TXTMARGE;
  1085. // text X size add height for triangular shapes(bidirectional)
  1086. length = LenSize( m_Text ) + height + DANGLING_SYMBOL_SIZE;
  1087. switch( m_schematicOrientation ) // respect orientation
  1088. {
  1089. case 0: /* Horiz Normal Orientation (left justified) */
  1090. dx = -length;
  1091. dy = height;
  1092. x += DANGLING_SYMBOL_SIZE;
  1093. y -= height / 2;
  1094. break;
  1095. case 1: /* Vert Orientation UP */
  1096. dx = height;
  1097. dy = -length;
  1098. x -= height / 2;
  1099. y += DANGLING_SYMBOL_SIZE;
  1100. break;
  1101. case 2: /* Horiz Orientation - Right justified */
  1102. dx = length;
  1103. dy = height;
  1104. x -= DANGLING_SYMBOL_SIZE;
  1105. y -= height / 2;
  1106. break;
  1107. case 3: /* Vert Orientation BOTTOM */
  1108. dx = height;
  1109. dy = length;
  1110. x -= height / 2;
  1111. y -= DANGLING_SYMBOL_SIZE;
  1112. break;
  1113. }
  1114. EDA_RECT box( wxPoint( x, y ), wxSize( dx, dy ) );
  1115. box.Normalize();
  1116. return box;
  1117. }
  1118. wxString SCH_GLOBALLABEL::GetSelectMenuText() const
  1119. {
  1120. wxString tmp = ( GetText().Length() > 15 ) ? GetText().Left( 12 ) + wxT( "..." ) : GetText();
  1121. wxString msg;
  1122. msg.Printf( _( "Global Label %s" ), GetChars(tmp) );
  1123. return msg;
  1124. }
  1125. SCH_HIERLABEL::SCH_HIERLABEL( const wxPoint& pos, const wxString& text, KICAD_T aType ) :
  1126. SCH_TEXT( pos, text, aType )
  1127. {
  1128. m_Layer = LAYER_HIERLABEL;
  1129. m_shape = NET_INPUT;
  1130. m_isDangling = true;
  1131. m_MultilineAllowed = false;
  1132. }
  1133. EDA_ITEM* SCH_HIERLABEL::Clone() const
  1134. {
  1135. return new SCH_HIERLABEL( *this );
  1136. }
  1137. bool SCH_HIERLABEL::Save( FILE* aFile ) const
  1138. {
  1139. bool success = true;
  1140. const char* shape = "~";
  1141. if( m_Italic )
  1142. shape = "Italic";
  1143. if( fprintf( aFile, "Text HLabel %-4d %-4d %-4d %-4d %s %s %d\n%s\n",
  1144. m_Pos.x, m_Pos.y, m_schematicOrientation, m_Size.x,
  1145. SheetLabelType[m_shape], shape, m_Thickness, TO_UTF8( m_Text ) ) == EOF )
  1146. {
  1147. success = false;
  1148. }
  1149. return success;
  1150. }
  1151. bool SCH_HIERLABEL::Load( LINE_READER& aLine, wxString& aErrorMsg )
  1152. {
  1153. char Name1[256];
  1154. char Name2[256];
  1155. char Name3[256];
  1156. int thickness = 0, size = 0, orient = 0;
  1157. Name1[0] = 0; Name2[0] = 0; Name3[0] = 0;
  1158. char* sline = (char*) aLine;
  1159. while( (*sline != ' ' ) && *sline )
  1160. sline++;
  1161. // sline points the start of parameters
  1162. int ii = sscanf( sline, "%s %d %d %d %d %s %s %d", Name1, &m_Pos.x, &m_Pos.y,
  1163. &orient, &size, Name2, Name3, &thickness );
  1164. if( ii < 4 )
  1165. {
  1166. aErrorMsg.Printf( wxT( "Eeschema file hierarchical label load error at line %d" ),
  1167. aLine.LineNumber() );
  1168. return false;
  1169. }
  1170. if( !aLine.ReadLine() )
  1171. {
  1172. aErrorMsg.Printf( wxT( "Eeschema file hierarchical label load error at line %d" ),
  1173. aLine.LineNumber() );
  1174. return false;
  1175. }
  1176. if( size == 0 )
  1177. size = DEFAULT_SIZE_TEXT;
  1178. char* text = strtok( (char*) aLine, "\n\r" );
  1179. if( text == NULL )
  1180. {
  1181. aErrorMsg.Printf( wxT( "Eeschema file hierarchical label load error at line %d" ),
  1182. aLine.LineNumber() );
  1183. return false;
  1184. }
  1185. m_Text = FROM_UTF8( text );
  1186. m_Size.x = m_Size.y = size;
  1187. SetOrientation( orient );
  1188. m_shape = NET_INPUT;
  1189. m_Bold = ( thickness != 0 );
  1190. m_Thickness = m_Bold ? GetPenSizeForBold( size ) : 0;
  1191. if( stricmp( Name2, SheetLabelType[NET_OUTPUT] ) == 0 )
  1192. m_shape = NET_OUTPUT;
  1193. if( stricmp( Name2, SheetLabelType[NET_BIDI] ) == 0 )
  1194. m_shape = NET_BIDI;
  1195. if( stricmp( Name2, SheetLabelType[NET_TRISTATE] ) == 0 )
  1196. m_shape = NET_TRISTATE;
  1197. if( stricmp( Name2, SheetLabelType[NET_UNSPECIFIED] ) == 0 )
  1198. m_shape = NET_UNSPECIFIED;
  1199. if( stricmp( Name3, "Italic" ) == 0 )
  1200. m_Italic = 1;
  1201. return true;
  1202. }
  1203. void SCH_HIERLABEL::SetOrientation( int aOrientation )
  1204. {
  1205. m_schematicOrientation = aOrientation;
  1206. switch( m_schematicOrientation )
  1207. {
  1208. default:
  1209. case 0: /* Horiz Normal Orientation */
  1210. m_Orient = TEXT_ORIENT_HORIZ;
  1211. m_HJustify = GR_TEXT_HJUSTIFY_RIGHT;
  1212. m_VJustify = GR_TEXT_VJUSTIFY_CENTER;
  1213. break;
  1214. case 1: /* Vert Orientation UP */
  1215. m_Orient = TEXT_ORIENT_VERT;
  1216. m_HJustify = GR_TEXT_HJUSTIFY_LEFT;
  1217. m_VJustify = GR_TEXT_VJUSTIFY_CENTER;
  1218. break;
  1219. case 2: /* Horiz Orientation */
  1220. m_Orient = TEXT_ORIENT_HORIZ;
  1221. m_HJustify = GR_TEXT_HJUSTIFY_LEFT;
  1222. m_VJustify = GR_TEXT_VJUSTIFY_CENTER;
  1223. break;
  1224. case 3: /* Vert Orientation BOTTOM */
  1225. m_Orient = TEXT_ORIENT_VERT;
  1226. m_HJustify = GR_TEXT_HJUSTIFY_RIGHT;
  1227. m_VJustify = GR_TEXT_VJUSTIFY_CENTER;
  1228. break;
  1229. }
  1230. }
  1231. void SCH_HIERLABEL::Draw( EDA_DRAW_PANEL* panel,
  1232. wxDC* DC,
  1233. const wxPoint& offset,
  1234. GR_DRAWMODE DrawMode,
  1235. EDA_COLOR_T Color )
  1236. {
  1237. static std::vector <wxPoint> Poly;
  1238. EDA_COLOR_T color;
  1239. int linewidth = m_Thickness == 0 ?
  1240. GetDefaultLineThickness() : m_Thickness;
  1241. EDA_RECT* clipbox = panel? panel->GetClipBox() : NULL;
  1242. linewidth = Clamp_Text_PenSize( linewidth, m_Size, m_Bold );
  1243. if( Color >= 0 )
  1244. color = Color;
  1245. else
  1246. color = GetLayerColor( m_Layer );
  1247. GRSetDrawMode( DC, DrawMode );
  1248. EXCHG( linewidth, m_Thickness ); // Set the minimum width
  1249. wxPoint text_offset = offset + GetSchematicTextOffset();
  1250. EDA_TEXT::Draw( clipbox, DC, text_offset, color, DrawMode, FILLED, UNSPECIFIED_COLOR );
  1251. EXCHG( linewidth, m_Thickness ); // set initial value
  1252. CreateGraphicShape( Poly, m_Pos + offset );
  1253. GRPoly( clipbox, DC, Poly.size(), &Poly[0], 0, linewidth, color, color );
  1254. if( m_isDangling )
  1255. DrawDanglingSymbol( panel, DC, m_Pos + offset, color );
  1256. // Enable these line to draw the bounding box (debug tests purposes only)
  1257. #if 0
  1258. {
  1259. EDA_RECT BoundaryBox = GetBoundingBox();
  1260. GRRect( clipbox, DC, BoundaryBox, 0, BROWN );
  1261. }
  1262. #endif
  1263. }
  1264. void SCH_HIERLABEL::CreateGraphicShape( std::vector <wxPoint>& aPoints, const wxPoint& Pos )
  1265. {
  1266. int* Template = TemplateShape[m_shape][m_schematicOrientation];
  1267. int HalfSize = m_Size.x / 2;
  1268. int imax = *Template; Template++;
  1269. aPoints.clear();
  1270. for( int ii = 0; ii < imax; ii++ )
  1271. {
  1272. wxPoint corner;
  1273. corner.x = ( HalfSize * (*Template) ) + Pos.x;
  1274. Template++;
  1275. corner.y = ( HalfSize * (*Template) ) + Pos.y;
  1276. Template++;
  1277. aPoints.push_back( corner );
  1278. }
  1279. }
  1280. const EDA_RECT SCH_HIERLABEL::GetBoundingBox() const
  1281. {
  1282. int x, y, dx, dy, length, height;
  1283. x = m_Pos.x;
  1284. y = m_Pos.y;
  1285. dx = dy = 0;
  1286. int width = (m_Thickness == 0) ? GetDefaultLineThickness() : m_Thickness;
  1287. height = m_Size.y + width + 2 * TXTMARGE;
  1288. length = LenSize( m_Text )
  1289. + height // add height for triangular shapes
  1290. + 2 * DANGLING_SYMBOL_SIZE;
  1291. switch( m_schematicOrientation ) // respect orientation
  1292. {
  1293. case 0: /* Horiz Normal Orientation (left justified) */
  1294. dx = -length;
  1295. dy = height;
  1296. x += DANGLING_SYMBOL_SIZE;
  1297. y -= height / 2;
  1298. break;
  1299. case 1: /* Vert Orientation UP */
  1300. dx = height;
  1301. dy = -length;
  1302. x -= height / 2;
  1303. y += DANGLING_SYMBOL_SIZE;
  1304. break;
  1305. case 2: /* Horiz Orientation - Right justified */
  1306. dx = length;
  1307. dy = height;
  1308. x -= DANGLING_SYMBOL_SIZE;
  1309. y -= height / 2;
  1310. break;
  1311. case 3: /* Vert Orientation BOTTOM */
  1312. dx = height;
  1313. dy = length;
  1314. x -= height / 2;
  1315. y -= DANGLING_SYMBOL_SIZE;
  1316. break;
  1317. }
  1318. EDA_RECT box( wxPoint( x, y ), wxSize( dx, dy ) );
  1319. box.Normalize();
  1320. return box;
  1321. }
  1322. wxPoint SCH_HIERLABEL::GetSchematicTextOffset() const
  1323. {
  1324. wxPoint text_offset;
  1325. int width = std::max( m_Thickness, GetDefaultLineThickness() );
  1326. int ii = m_Size.x + TXTMARGE + width;
  1327. switch( m_schematicOrientation )
  1328. {
  1329. case 0: /* Orientation horiz normale */
  1330. text_offset.x = -ii;
  1331. break;
  1332. case 1: /* Orientation vert UP */
  1333. text_offset.y = -ii;
  1334. break;
  1335. case 2: /* Orientation horiz inverse */
  1336. text_offset.x = ii;
  1337. break;
  1338. case 3: /* Orientation vert BOTTOM */
  1339. text_offset.y = ii;
  1340. break;
  1341. }
  1342. return text_offset;
  1343. }
  1344. void SCH_HIERLABEL::MirrorY( int aYaxis_position )
  1345. {
  1346. /* The hierarchical label is NOT really mirrored for an horizontal label, the schematic
  1347. * orientation is changed. For a vertical label, the schematic orientation is not changed
  1348. * and the label is moved to a suitable position.
  1349. */
  1350. switch( GetOrientation() )
  1351. {
  1352. case 0: /* horizontal text */
  1353. SetOrientation( 2 );
  1354. break;
  1355. case 2: /* invert horizontal text*/
  1356. SetOrientation( 0 );
  1357. break;
  1358. }
  1359. m_Pos.x -= aYaxis_position;
  1360. NEGATE( m_Pos.x );
  1361. m_Pos.x += aYaxis_position;
  1362. }
  1363. void SCH_HIERLABEL::MirrorX( int aXaxis_position )
  1364. {
  1365. switch( GetOrientation() )
  1366. {
  1367. case 1: /* vertical text */
  1368. SetOrientation( 3 );
  1369. break;
  1370. case 3: /* invert vertical text*/
  1371. SetOrientation( 1 );
  1372. break;
  1373. }
  1374. m_Pos.y -= aXaxis_position;
  1375. NEGATE( m_Pos.y );
  1376. m_Pos.y += aXaxis_position;
  1377. }
  1378. void SCH_HIERLABEL::Rotate( wxPoint aPosition )
  1379. {
  1380. RotatePoint( &m_Pos, aPosition, 900 );
  1381. SetOrientation( (GetOrientation() + 3) % 4 );
  1382. }
  1383. wxString SCH_HIERLABEL::GetSelectMenuText() const
  1384. {
  1385. wxString tmp = ( GetText().Length() > 15 ) ? GetText().Left( 12 ) + wxT( "..." ) : GetText();
  1386. wxString msg;
  1387. msg.Printf( _( "Hierarchical Label %s" ), GetChars( tmp ) );
  1388. return msg;
  1389. }