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.

1775 lines
46 KiB

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