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.

1790 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) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
  5. * Copyright (C) 2015 Wayne Stambaugh <stambaughw@verizon.net>
  6. * Copyright (C) 1992-2015 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 sheet labels.
  28. */
  29. #include <fctsys.h>
  30. #include <gr_basic.h>
  31. #include <macros.h>
  32. #include <trigo.h>
  33. #include <eeschema_id.h>
  34. #include <class_drawpanel.h>
  35. #include <drawtxt.h>
  36. #include <schframe.h>
  37. #include <plot_common.h>
  38. #include <base_units.h>
  39. #include <msgpanel.h>
  40. #include <general.h>
  41. #include <protos.h>
  42. #include <sch_text.h>
  43. #include <class_netlist_object.h>
  44. extern void IncrementLabelMember( wxString& name );
  45. /* Names of sheet label types. */
  46. const char* SheetLabelType[] =
  47. {
  48. "Input",
  49. "Output",
  50. "BiDi",
  51. "3State",
  52. "UnSpc",
  53. "???"
  54. };
  55. /* Coding polygons for global symbol graphic shapes.
  56. * the first parml is the number of corners
  57. * others are the corners coordinates in reduced units
  58. * the real coordinate is the reduced coordinate * text half size
  59. */
  60. static int TemplateIN_HN[] = { 6, 0, 0, -1, -1, -2, -1, -2, 1, -1, 1, 0, 0 };
  61. static int TemplateIN_HI[] = { 6, 0, 0, 1, 1, 2, 1, 2, -1, 1, -1, 0, 0 };
  62. static int TemplateIN_UP[] = { 6, 0, 0, 1, -1, 1, -2, -1, -2, -1, -1, 0, 0 };
  63. static int TemplateIN_BOTTOM[] = { 6, 0, 0, 1, 1, 1, 2, -1, 2, -1, 1, 0, 0 };
  64. static int TemplateOUT_HN[] = { 6, -2, 0, -1, 1, 0, 1, 0, -1, -1, -1, -2, 0 };
  65. static int TemplateOUT_HI[] = { 6, 2, 0, 1, -1, 0, -1, 0, 1, 1, 1, 2, 0 };
  66. static int TemplateOUT_UP[] = { 6, 0, -2, 1, -1, 1, 0, -1, 0, -1, -1, 0, -2 };
  67. static int TemplateOUT_BOTTOM[] = { 6, 0, 2, 1, 1, 1, 0, -1, 0, -1, 1, 0, 2 };
  68. static int TemplateUNSPC_HN[] = { 5, 0, -1, -2, -1, -2, 1, 0, 1, 0, -1 };
  69. static int TemplateUNSPC_HI[] = { 5, 0, -1, 2, -1, 2, 1, 0, 1, 0, -1 };
  70. static int TemplateUNSPC_UP[] = { 5, 1, 0, 1, -2, -1, -2, -1, 0, 1, 0 };
  71. static int TemplateUNSPC_BOTTOM[] = { 5, 1, 0, 1, 2, -1, 2, -1, 0, 1, 0 };
  72. static int TemplateBIDI_HN[] = { 5, 0, 0, -1, -1, -2, 0, -1, 1, 0, 0 };
  73. static int TemplateBIDI_HI[] = { 5, 0, 0, 1, -1, 2, 0, 1, 1, 0, 0 };
  74. static int TemplateBIDI_UP[] = { 5, 0, 0, -1, -1, 0, -2, 1, -1, 0, 0 };
  75. static int TemplateBIDI_BOTTOM[] = { 5, 0, 0, -1, 1, 0, 2, 1, 1, 0, 0 };
  76. static int Template3STATE_HN[] = { 5, 0, 0, -1, -1, -2, 0, -1, 1, 0, 0 };
  77. static int Template3STATE_HI[] = { 5, 0, 0, 1, -1, 2, 0, 1, 1, 0, 0 };
  78. static int Template3STATE_UP[] = { 5, 0, 0, -1, -1, 0, -2, 1, -1, 0, 0 };
  79. static int Template3STATE_BOTTOM[] = { 5, 0, 0, -1, 1, 0, 2, 1, 1, 0, 0 };
  80. static int* TemplateShape[5][4] =
  81. {
  82. { TemplateIN_HN, TemplateIN_UP, TemplateIN_HI, TemplateIN_BOTTOM },
  83. { TemplateOUT_HN, TemplateOUT_UP, TemplateOUT_HI, TemplateOUT_BOTTOM },
  84. { TemplateBIDI_HN, TemplateBIDI_UP, TemplateBIDI_HI, TemplateBIDI_BOTTOM },
  85. { Template3STATE_HN, Template3STATE_UP, Template3STATE_HI, Template3STATE_BOTTOM },
  86. { TemplateUNSPC_HN, TemplateUNSPC_UP, TemplateUNSPC_HI, TemplateUNSPC_BOTTOM }
  87. };
  88. SCH_TEXT::SCH_TEXT( const wxPoint& pos, const wxString& text, KICAD_T aType ) :
  89. SCH_ITEM( NULL, aType ),
  90. EDA_TEXT( text )
  91. {
  92. m_Layer = LAYER_NOTES;
  93. m_Pos = pos;
  94. m_shape = 0;
  95. m_isDangling = false;
  96. m_MultilineAllowed = true;
  97. m_schematicOrientation = 0;
  98. }
  99. SCH_TEXT::SCH_TEXT( const SCH_TEXT& aText ) :
  100. SCH_ITEM( aText ),
  101. EDA_TEXT( aText )
  102. {
  103. m_Pos = aText.m_Pos;
  104. m_shape = aText.m_shape;
  105. m_MultilineAllowed = aText.m_MultilineAllowed;
  106. m_schematicOrientation = aText.m_schematicOrientation;
  107. m_isDangling = false;
  108. }
  109. EDA_ITEM* SCH_TEXT::Clone() const
  110. {
  111. return new SCH_TEXT( *this );
  112. }
  113. void SCH_TEXT::IncrementLabel()
  114. {
  115. IncrementLabelMember( m_Text );
  116. }
  117. wxPoint SCH_TEXT::GetSchematicTextOffset() const
  118. {
  119. wxPoint text_offset;
  120. // add a small offset (TXTMARGE) to x ( or y) position to allow a text to
  121. // be on a wire or a line and be readable
  122. switch( m_schematicOrientation )
  123. {
  124. default:
  125. case 0: /* Horiz Normal Orientation (left justified) */
  126. text_offset.y = -TXTMARGE;
  127. break;
  128. case 1: /* Vert Orientation UP */
  129. text_offset.x = -TXTMARGE;
  130. break;
  131. case 2: /* Horiz Orientation - Right justified */
  132. text_offset.y = -TXTMARGE;
  133. break;
  134. case 3: /* Vert Orientation BOTTOM */
  135. text_offset.x = -TXTMARGE;
  136. break;
  137. }
  138. return text_offset;
  139. }
  140. bool SCH_TEXT::Matches( wxFindReplaceData& aSearchData, void* aAuxData, wxPoint * aFindLocation )
  141. {
  142. wxLogTrace( traceFindItem, wxT( " item " ) + GetSelectMenuText() );
  143. if( SCH_ITEM::Matches( m_Text, aSearchData ) )
  144. {
  145. EDA_RECT BoundaryBox = GetBoundingBox();
  146. if( aFindLocation )
  147. *aFindLocation = BoundaryBox.Centre();
  148. return true;
  149. }
  150. return false;
  151. }
  152. void SCH_TEXT::MirrorY( int aYaxis_position )
  153. {
  154. // Text is NOT really mirrored; it is moved to a suitable horizontal position
  155. switch( GetOrientation() )
  156. {
  157. case 0: // horizontal text
  158. SetOrientation( 2 );
  159. break;
  160. case 2: // invert horizontal text
  161. SetOrientation( 0 );
  162. break;
  163. case 1: // Vert Orientation UP
  164. case 3: // Vert Orientation BOTTOM
  165. default:
  166. break;
  167. }
  168. m_Pos.x -= aYaxis_position;
  169. NEGATE( m_Pos.x );
  170. m_Pos.x += aYaxis_position;
  171. }
  172. void SCH_TEXT::MirrorX( int aXaxis_position )
  173. {
  174. // Text is NOT really mirrored; it is moved to a suitable vertical position
  175. switch( GetOrientation() )
  176. {
  177. case 1: // Vert Orientation UP
  178. SetOrientation( 3 );
  179. break;
  180. case 3: // Vert Orientation BOTTOM
  181. SetOrientation( 1 );
  182. break;
  183. case 0: // horizontal text
  184. case 2: // invert horizontal text
  185. default:
  186. break;
  187. }
  188. m_Pos.y -= aXaxis_position;
  189. NEGATE( m_Pos.y );
  190. 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. EXCHG( m_Text, item->m_Text );
  249. EXCHG( m_Pos, item->m_Pos );
  250. EXCHG( m_Size, item->m_Size );
  251. EXCHG( m_Thickness, item->m_Thickness );
  252. EXCHG( m_shape, item->m_shape );
  253. EXCHG( m_Orient, item->m_Orient );
  254. EXCHG( m_Layer, item->m_Layer );
  255. EXCHG( m_HJustify, item->m_HJustify );
  256. EXCHG( m_VJustify, item->m_VJustify );
  257. EXCHG( m_isDangling, item->m_isDangling );
  258. EXCHG( 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( m_Layer );
  285. GRSetDrawMode( DC, DrawMode );
  286. wxPoint text_offset = aOffset + GetSchematicTextOffset();
  287. EXCHG( linewidth, m_Thickness ); // Set the minimum width
  288. EDA_TEXT::Draw( clipbox, DC, text_offset, color, DrawMode, FILLED, UNSPECIFIED_COLOR );
  289. EXCHG( linewidth, m_Thickness ); // set initial value
  290. if( m_isDangling )
  291. DrawDanglingSymbol( panel, DC, m_Pos + aOffset, color );
  292. // Enable these line to draw the bounding box (debug tests purposes only)
  293. #if 0
  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, "%s %d %d %d %d %s %s %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( strnicmp( 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. wxPoint textpos = m_Pos + GetSchematicTextOffset();
  516. int thickness = GetPenSize();
  517. aPlotter->SetCurrentLineWidth( thickness );
  518. if( m_MultilineAllowed )
  519. {
  520. std::vector<wxPoint> positions;
  521. wxArrayString strings_list;
  522. wxStringSplit( GetShownText(), strings_list, '\n' );
  523. positions.reserve( strings_list.Count() );
  524. GetPositionsOfLinesOfMultilineText(positions, strings_list.Count() );
  525. for( unsigned ii = 0; ii < strings_list.Count(); ii++ )
  526. {
  527. wxString& txt = strings_list.Item( ii );
  528. aPlotter->Text( positions[ii], color, txt, m_Orient, m_Size, m_HJustify,
  529. m_VJustify, thickness, m_Italic, m_Bold );
  530. }
  531. }
  532. else
  533. {
  534. aPlotter->Text( textpos, color, GetShownText(), m_Orient, m_Size, m_HJustify,
  535. m_VJustify, thickness, m_Italic, m_Bold );
  536. }
  537. /* Draw graphic symbol for global or hierarchical labels */
  538. CreateGraphicShape( Poly, m_Pos );
  539. aPlotter->SetCurrentLineWidth( GetPenSize() );
  540. if( Poly.size() )
  541. aPlotter->PlotPoly( Poly, NO_FILL );
  542. }
  543. /*
  544. * Display the type, shape, size and some other props to the Message panel
  545. */
  546. void SCH_TEXT::GetMsgPanelInfo( MSG_PANEL_ITEMS& aList )
  547. {
  548. wxString msg;
  549. switch( Type() )
  550. {
  551. case SCH_TEXT_T:
  552. msg = _( "Graphic Text" );
  553. break;
  554. case SCH_LABEL_T:
  555. msg = _( "Label" );
  556. break;
  557. case SCH_GLOBAL_LABEL_T:
  558. msg = _( "Global Label" );
  559. break;
  560. case SCH_HIERARCHICAL_LABEL_T:
  561. msg = _( "Hierarchical Label" );
  562. break;
  563. case SCH_SHEET_PIN_T:
  564. msg = _( "Hierarchical Sheet Pin" );
  565. break;
  566. default:
  567. return;
  568. }
  569. aList.push_back( MSG_PANEL_ITEM( msg, GetShownText(), DARKCYAN ) );
  570. switch( GetOrientation() )
  571. {
  572. case 0: // horizontal text
  573. msg = _( "Horizontal" );
  574. break;
  575. case 1: // Vert Orientation UP
  576. msg = _( "Vertical up" );
  577. break;
  578. case 2: // invert horizontal text
  579. msg = _( "Horizontal invert" );
  580. break;
  581. case 3: // Vert Orientation Down
  582. msg = _( "Vertical down" );
  583. break;
  584. default:
  585. msg = wxT( "???" );
  586. break;
  587. }
  588. aList.push_back( MSG_PANEL_ITEM( _( "Orientation" ), msg, BROWN ) );
  589. wxString textStyle[] = { _( "Normal" ), _( "Italic" ), _( "Bold" ), _( "Bold Italic" ) };
  590. int style = 0;
  591. if( m_Italic )
  592. style = 1;
  593. if( m_Bold )
  594. style += 2;
  595. aList.push_back( MSG_PANEL_ITEM( _( "Style" ), textStyle[style], BROWN ) );
  596. // Display electricat type if it is relevant
  597. if( (Type() == SCH_GLOBAL_LABEL_T) ||
  598. (Type() == SCH_HIERARCHICAL_LABEL_T ) ||
  599. (Type() == SCH_SHEET_PIN_T ) )
  600. {
  601. switch( GetShape() )
  602. {
  603. case NET_INPUT: msg = _( "Input" ); break;
  604. case NET_OUTPUT: msg = _( "Output" ); break;
  605. case NET_BIDI: msg = _( "Bidirectional" ); break;
  606. case NET_TRISTATE: msg = _( "Tri-State" ); break;
  607. case NET_UNSPECIFIED: msg = _( "Passive" ); break;
  608. default: msg = wxT( "???" ); break;
  609. }
  610. aList.push_back( MSG_PANEL_ITEM( _( "Type" ), msg, BLUE ) );
  611. }
  612. // Display text size (X or Y value, with are the same value in Eeschema)
  613. msg = StringFromValue( g_UserUnit, m_Size.x, true );
  614. aList.push_back( MSG_PANEL_ITEM( _( "Size" ), msg, RED ) );
  615. }
  616. #if defined(DEBUG)
  617. void SCH_TEXT::Show( int nestLevel, std::ostream& os ) const
  618. {
  619. // XML output:
  620. wxString s = GetClass();
  621. NestedSpace( nestLevel, os ) << '<' << s.Lower().mb_str()
  622. << " layer=\"" << m_Layer << '"'
  623. << " shape=\"" << m_shape << '"'
  624. << " dangling=\"" << m_isDangling << '"'
  625. << '>'
  626. << TO_UTF8( m_Text )
  627. << "</" << s.Lower().mb_str() << ">\n";
  628. }
  629. #endif
  630. SCH_LABEL::SCH_LABEL( const wxPoint& pos, const wxString& text ) :
  631. SCH_TEXT( pos, text, SCH_LABEL_T )
  632. {
  633. m_Layer = LAYER_LOCLABEL;
  634. m_shape = NET_INPUT;
  635. m_isDangling = true;
  636. m_MultilineAllowed = false;
  637. }
  638. EDA_ITEM* SCH_LABEL::Clone() const
  639. {
  640. return new SCH_LABEL( *this );
  641. }
  642. wxPoint SCH_LABEL::GetSchematicTextOffset() const
  643. {
  644. return SCH_TEXT::GetSchematicTextOffset();
  645. }
  646. void SCH_LABEL::SetOrientation( int aOrientation )
  647. {
  648. SCH_TEXT::SetOrientation( aOrientation );
  649. }
  650. void SCH_LABEL::MirrorX( int aXaxis_position )
  651. {
  652. // Text is NOT really mirrored; it is moved to a suitable position
  653. switch( GetOrientation() )
  654. {
  655. case 1: // Vert Orientation UP
  656. SetOrientation( 3 );
  657. break;
  658. case 3: // Vert Orientation BOTTOM
  659. SetOrientation( 1 );
  660. break;
  661. case 0: // horizontal text
  662. case 2: // invert horizontal text
  663. default:
  664. break;
  665. }
  666. m_Pos.y -= aXaxis_position;
  667. NEGATE( m_Pos.y );
  668. m_Pos.y += aXaxis_position;
  669. }
  670. void SCH_LABEL::Rotate( wxPoint aPosition )
  671. {
  672. RotatePoint( &m_Pos, aPosition, 900 );
  673. SetOrientation( (GetOrientation() + 1) % 4 );
  674. }
  675. bool SCH_LABEL::Save( FILE* aFile ) const
  676. {
  677. bool success = true;
  678. const char* shape = "~";
  679. if( m_Italic )
  680. shape = "Italic";
  681. if( fprintf( aFile, "Text Label %-4d %-4d %-4d %-4d %s %d\n%s\n",
  682. m_Pos.x, m_Pos.y, m_schematicOrientation, m_Size.x, shape,
  683. m_Thickness, TO_UTF8( m_Text ) ) == EOF )
  684. {
  685. success = false;
  686. }
  687. return success;
  688. }
  689. bool SCH_LABEL::Load( LINE_READER& aLine, wxString& aErrorMsg )
  690. {
  691. char Name1[256];
  692. char Name2[256];
  693. char Name3[256];
  694. int thickness = 0, size = 0, orient = 0;
  695. Name1[0] = 0; Name2[0] = 0; Name3[0] = 0;
  696. char* sline = (char*) aLine;
  697. while( ( *sline != ' ' ) && *sline )
  698. sline++;
  699. // sline points the start of parameters
  700. int ii = sscanf( sline, "%s %d %d %d %d %s %s %d", Name1, &m_Pos.x, &m_Pos.y,
  701. &orient, &size, Name2, Name3, &thickness );
  702. if( ii < 4 )
  703. {
  704. aErrorMsg.Printf( wxT( "Eeschema file label load error at line %d" ),
  705. aLine.LineNumber() );
  706. return false;
  707. }
  708. if( !aLine.ReadLine() )
  709. {
  710. aErrorMsg.Printf( wxT( "Eeschema file label load error atline %d" ),
  711. aLine.LineNumber() );
  712. return false;
  713. }
  714. if( size == 0 )
  715. size = GetDefaultTextSize();
  716. char* text = strtok( (char*) aLine, "\n\r" );
  717. if( text == NULL )
  718. {
  719. aErrorMsg.Printf( wxT( "Eeschema file label load error at line %d" ),
  720. aLine.LineNumber() );
  721. return false;
  722. }
  723. m_Text = FROM_UTF8( text );
  724. m_Size.x = m_Size.y = size;
  725. SetOrientation( orient );
  726. if( isdigit( Name3[0] ) )
  727. {
  728. thickness = atol( Name3 );
  729. m_Bold = ( thickness != 0 );
  730. m_Thickness = m_Bold ? GetPenSizeForBold( size ) : 0;
  731. }
  732. if( stricmp( Name2, "Italic" ) == 0 )
  733. m_Italic = 1;
  734. return true;
  735. }
  736. void SCH_LABEL::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, const wxPoint& offset,
  737. GR_DRAWMODE DrawMode, EDA_COLOR_T Color )
  738. {
  739. SCH_TEXT::Draw( panel, DC, offset, DrawMode, Color );
  740. }
  741. const EDA_RECT SCH_LABEL::GetBoundingBox() const
  742. {
  743. int x, y, dx, dy, length, height;
  744. x = m_Pos.x;
  745. y = m_Pos.y;
  746. int width = (m_Thickness == 0) ? GetDefaultLineThickness() : m_Thickness;
  747. length = LenSize( GetShownText() );
  748. height = m_Size.y + width;
  749. dx = dy = 0;
  750. switch( m_schematicOrientation )
  751. {
  752. case 0: /* Horiz Normal Orientation (left justified) */
  753. dx = 2 * DANGLING_SYMBOL_SIZE + length;
  754. dy = -2 * DANGLING_SYMBOL_SIZE - height - TXTMARGE;
  755. x -= DANGLING_SYMBOL_SIZE;
  756. y += DANGLING_SYMBOL_SIZE;
  757. break;
  758. case 1: /* Vert Orientation UP */
  759. dx = -2 * DANGLING_SYMBOL_SIZE - height - TXTMARGE;
  760. dy = -2 * DANGLING_SYMBOL_SIZE - length;
  761. x += DANGLING_SYMBOL_SIZE;
  762. y += DANGLING_SYMBOL_SIZE;
  763. break;
  764. case 2: /* Horiz Orientation - Right justified */
  765. dx = -2 * DANGLING_SYMBOL_SIZE - length;
  766. dy = -2 * DANGLING_SYMBOL_SIZE - height - TXTMARGE;
  767. x += DANGLING_SYMBOL_SIZE;
  768. y += DANGLING_SYMBOL_SIZE;
  769. break;
  770. case 3: /* Vert Orientation BOTTOM */
  771. dx = -2 * DANGLING_SYMBOL_SIZE - height - TXTMARGE;
  772. dy = 2 * DANGLING_SYMBOL_SIZE + length;
  773. x += DANGLING_SYMBOL_SIZE;
  774. y -= DANGLING_SYMBOL_SIZE;
  775. break;
  776. }
  777. EDA_RECT box( wxPoint( x, y ), wxSize( dx, dy ) );
  778. box.Normalize();
  779. return box;
  780. }
  781. wxString SCH_LABEL::GetSelectMenuText() const
  782. {
  783. wxString msg;
  784. msg.Printf( _( "Label %s" ), GetChars( ShortenedShownText() ) );
  785. return msg;
  786. }
  787. SCH_GLOBALLABEL::SCH_GLOBALLABEL( const wxPoint& pos, const wxString& text ) :
  788. SCH_TEXT( pos, text, SCH_GLOBAL_LABEL_T )
  789. {
  790. m_Layer = LAYER_GLOBLABEL;
  791. m_shape = NET_BIDI;
  792. m_isDangling = true;
  793. m_MultilineAllowed = false;
  794. }
  795. EDA_ITEM* SCH_GLOBALLABEL::Clone() const
  796. {
  797. return new SCH_GLOBALLABEL( *this );
  798. }
  799. bool SCH_GLOBALLABEL::Save( FILE* aFile ) const
  800. {
  801. bool success = true;
  802. const char* shape = "~";
  803. if( m_Italic )
  804. shape = "Italic";
  805. if( fprintf( aFile, "Text GLabel %-4d %-4d %-4d %-4d %s %s %d\n%s\n",
  806. m_Pos.x, m_Pos.y, m_schematicOrientation, m_Size.x,
  807. SheetLabelType[m_shape], shape, m_Thickness, TO_UTF8( m_Text ) ) == EOF )
  808. {
  809. success = false;
  810. }
  811. return success;
  812. }
  813. bool SCH_GLOBALLABEL::Load( LINE_READER& aLine, wxString& aErrorMsg )
  814. {
  815. char Name1[256];
  816. char Name2[256];
  817. char Name3[256];
  818. int thickness = 0, size = 0, orient = 0;
  819. Name1[0] = 0; Name2[0] = 0; Name3[0] = 0;
  820. char* sline = (char*) aLine;
  821. while( (*sline != ' ' ) && *sline )
  822. sline++;
  823. // sline points the start of parameters
  824. int ii = sscanf( sline, "%s %d %d %d %d %s %s %d", Name1, &m_Pos.x, &m_Pos.y,
  825. &orient, &size, Name2, Name3, &thickness );
  826. if( ii < 4 )
  827. {
  828. aErrorMsg.Printf( wxT( "Eeschema file global label load error at line %d" ),
  829. aLine.LineNumber() );
  830. return false;
  831. }
  832. if( !aLine.ReadLine() )
  833. {
  834. aErrorMsg.Printf( wxT( "Eeschema file global label load error at line %d" ),
  835. aLine.LineNumber() );
  836. return false;
  837. }
  838. if( size == 0 )
  839. size = GetDefaultTextSize();
  840. char* text = strtok( (char*) aLine, "\n\r" );
  841. if( text == NULL )
  842. {
  843. aErrorMsg.Printf( wxT( "Eeschema file global label load error at line %d" ),
  844. aLine.LineNumber() );
  845. return false;
  846. }
  847. m_Text = FROM_UTF8( text );
  848. m_Size.x = m_Size.y = size;
  849. SetOrientation( orient );
  850. m_shape = NET_INPUT;
  851. m_Bold = ( thickness != 0 );
  852. m_Thickness = m_Bold ? GetPenSizeForBold( size ) : 0;
  853. if( stricmp( Name2, SheetLabelType[NET_OUTPUT] ) == 0 )
  854. m_shape = NET_OUTPUT;
  855. if( stricmp( Name2, SheetLabelType[NET_BIDI] ) == 0 )
  856. m_shape = NET_BIDI;
  857. if( stricmp( Name2, SheetLabelType[NET_TRISTATE] ) == 0 )
  858. m_shape = NET_TRISTATE;
  859. if( stricmp( Name2, SheetLabelType[NET_UNSPECIFIED] ) == 0 )
  860. m_shape = NET_UNSPECIFIED;
  861. if( stricmp( Name3, "Italic" ) == 0 )
  862. m_Italic = 1;
  863. return true;
  864. }
  865. void SCH_GLOBALLABEL::MirrorY( int aYaxis_position )
  866. {
  867. /* The global label is NOT really mirrored.
  868. * for an horizontal label, the schematic orientation is changed.
  869. * for a vertical label, the schematic orientation is not changed.
  870. * and the label is moved to a suitable position
  871. */
  872. switch( GetOrientation() )
  873. {
  874. case 0: /* horizontal text */
  875. SetOrientation( 2 );
  876. break;
  877. case 2: /* invert horizontal text*/
  878. SetOrientation( 0 );
  879. break;
  880. }
  881. m_Pos.x -= aYaxis_position;
  882. NEGATE( m_Pos.x );
  883. m_Pos.x += aYaxis_position;
  884. }
  885. void SCH_GLOBALLABEL::MirrorX( int aXaxis_position )
  886. {
  887. switch( GetOrientation() )
  888. {
  889. case 1: /* vertical text */
  890. SetOrientation( 3 );
  891. break;
  892. case 3: /* invert vertical text*/
  893. SetOrientation( 1 );
  894. break;
  895. }
  896. m_Pos.y -= aXaxis_position;
  897. NEGATE( m_Pos.y );
  898. m_Pos.y += aXaxis_position;
  899. }
  900. void SCH_GLOBALLABEL::Rotate( wxPoint aPosition )
  901. {
  902. RotatePoint( &m_Pos, aPosition, 900 );
  903. SetOrientation( (GetOrientation() + 3) % 4 );
  904. }
  905. wxPoint SCH_GLOBALLABEL::GetSchematicTextOffset() const
  906. {
  907. wxPoint text_offset;
  908. int width = (m_Thickness == 0) ? GetDefaultLineThickness() : m_Thickness;
  909. width = Clamp_Text_PenSize( width, m_Size, m_Bold );
  910. int HalfSize = m_Size.x / 2;
  911. int offset = width;
  912. switch( m_shape )
  913. {
  914. case NET_INPUT:
  915. case NET_BIDI:
  916. case NET_TRISTATE:
  917. offset += HalfSize;
  918. break;
  919. case NET_OUTPUT:
  920. case NET_UNSPECIFIED:
  921. offset += TXTMARGE;
  922. break;
  923. default:
  924. break;
  925. }
  926. switch( m_schematicOrientation )
  927. {
  928. case 0: /* Orientation horiz normal */
  929. text_offset.x -= offset;
  930. break;
  931. case 1: /* Orientation vert UP */
  932. text_offset.y -= offset;
  933. break;
  934. case 2: /* Orientation horiz inverse */
  935. text_offset.x += offset;
  936. break;
  937. case 3: /* Orientation vert BOTTOM */
  938. text_offset.y += offset;
  939. break;
  940. }
  941. return text_offset;
  942. }
  943. void SCH_GLOBALLABEL::SetOrientation( int aOrientation )
  944. {
  945. m_schematicOrientation = aOrientation;
  946. switch( m_schematicOrientation )
  947. {
  948. default:
  949. case 0: /* Horiz Normal Orientation */
  950. m_Orient = TEXT_ORIENT_HORIZ;
  951. m_HJustify = GR_TEXT_HJUSTIFY_RIGHT;
  952. m_VJustify = GR_TEXT_VJUSTIFY_CENTER;
  953. break;
  954. case 1: /* Vert Orientation UP */
  955. m_Orient = TEXT_ORIENT_VERT;
  956. m_HJustify = GR_TEXT_HJUSTIFY_LEFT;
  957. m_VJustify = GR_TEXT_VJUSTIFY_CENTER;
  958. break;
  959. case 2: /* Horiz Orientation */
  960. m_Orient = TEXT_ORIENT_HORIZ;
  961. m_HJustify = GR_TEXT_HJUSTIFY_LEFT;
  962. m_VJustify = GR_TEXT_VJUSTIFY_CENTER;
  963. break;
  964. case 3: /* Vert Orientation BOTTOM */
  965. m_Orient = TEXT_ORIENT_VERT;
  966. m_HJustify = GR_TEXT_HJUSTIFY_RIGHT;
  967. m_VJustify = GR_TEXT_VJUSTIFY_CENTER;
  968. break;
  969. }
  970. }
  971. void SCH_GLOBALLABEL::Draw( EDA_DRAW_PANEL* panel,
  972. wxDC* DC,
  973. const wxPoint& aOffset,
  974. GR_DRAWMODE DrawMode,
  975. EDA_COLOR_T Color )
  976. {
  977. static std::vector <wxPoint> Poly;
  978. EDA_COLOR_T color;
  979. wxPoint text_offset = aOffset + GetSchematicTextOffset();
  980. if( Color >= 0 )
  981. color = Color;
  982. else
  983. color = GetLayerColor( m_Layer );
  984. GRSetDrawMode( DC, DrawMode );
  985. int linewidth = (m_Thickness == 0) ? GetDefaultLineThickness() : m_Thickness;
  986. linewidth = Clamp_Text_PenSize( linewidth, m_Size, m_Bold );
  987. EXCHG( linewidth, m_Thickness ); // Set the minimum width
  988. EDA_RECT* clipbox = panel? panel->GetClipBox() : NULL;
  989. EDA_TEXT::Draw( clipbox, DC, text_offset, color, DrawMode, FILLED, UNSPECIFIED_COLOR );
  990. EXCHG( linewidth, m_Thickness ); // set initial value
  991. CreateGraphicShape( Poly, m_Pos + aOffset );
  992. GRPoly( clipbox, DC, Poly.size(), &Poly[0], 0, linewidth, color, color );
  993. if( m_isDangling )
  994. DrawDanglingSymbol( panel, DC, m_Pos + aOffset, color );
  995. // Enable these line to draw the bounding box (debug tests purposes only)
  996. #if 0
  997. {
  998. EDA_RECT BoundaryBox = GetBoundingBox();
  999. GRRect( clipbox, DC, BoundaryBox, 0, BROWN );
  1000. }
  1001. #endif
  1002. }
  1003. void SCH_GLOBALLABEL::CreateGraphicShape( std::vector <wxPoint>& aPoints, const wxPoint& Pos )
  1004. {
  1005. int HalfSize = m_Size.y / 2;
  1006. int linewidth = (m_Thickness == 0) ? GetDefaultLineThickness() : m_Thickness;
  1007. linewidth = Clamp_Text_PenSize( linewidth, m_Size, m_Bold );
  1008. aPoints.clear();
  1009. int symb_len = LenSize( GetShownText() ) + ( TXTMARGE * 2 );
  1010. // Create outline shape : 6 points
  1011. int x = symb_len + linewidth + 3;
  1012. // Use negation bar Y position to calculate full vertical size
  1013. #define Y_CORRECTION 1.3
  1014. // Note: this factor is due to the fact the negation bar Y position
  1015. // does not give exactly the full Y size of text
  1016. // and is experimentally set to this value
  1017. int y = KiROUND( OverbarPositionY( HalfSize ) * Y_CORRECTION );
  1018. // add room for line thickness and space between top of text and graphic shape
  1019. y += linewidth;
  1020. // Starting point(anchor)
  1021. aPoints.push_back( wxPoint( 0, 0 ) );
  1022. aPoints.push_back( wxPoint( 0, -y ) ); // Up
  1023. aPoints.push_back( wxPoint( -x, -y ) ); // left
  1024. aPoints.push_back( wxPoint( -x, 0 ) ); // Up left
  1025. aPoints.push_back( wxPoint( -x, y ) ); // left down
  1026. aPoints.push_back( wxPoint( 0, y ) ); // down
  1027. int x_offset = 0;
  1028. switch( m_shape )
  1029. {
  1030. case NET_INPUT:
  1031. x_offset = -HalfSize;
  1032. aPoints[0].x += HalfSize;
  1033. break;
  1034. case NET_OUTPUT:
  1035. aPoints[3].x -= HalfSize;
  1036. break;
  1037. case NET_BIDI:
  1038. case NET_TRISTATE:
  1039. x_offset = -HalfSize;
  1040. aPoints[0].x += HalfSize;
  1041. aPoints[3].x -= HalfSize;
  1042. break;
  1043. case NET_UNSPECIFIED:
  1044. default:
  1045. break;
  1046. }
  1047. int angle = 0;
  1048. switch( m_schematicOrientation )
  1049. {
  1050. case 0: /* Orientation horiz normal */
  1051. break;
  1052. case 1: /* Orientation vert UP */
  1053. angle = -900;
  1054. break;
  1055. case 2: /* Orientation horiz inverse */
  1056. angle = 1800;
  1057. break;
  1058. case 3: /* Orientation vert BOTTOM */
  1059. angle = 900;
  1060. break;
  1061. }
  1062. // Rotate outlines and move corners in real position
  1063. for( unsigned ii = 0; ii < aPoints.size(); ii++ )
  1064. {
  1065. aPoints[ii].x += x_offset;
  1066. if( angle )
  1067. RotatePoint( &aPoints[ii], angle );
  1068. aPoints[ii] += Pos;
  1069. }
  1070. aPoints.push_back( aPoints[0] ); // closing
  1071. }
  1072. const EDA_RECT SCH_GLOBALLABEL::GetBoundingBox() const
  1073. {
  1074. int x, y, dx, dy, length, height;
  1075. x = m_Pos.x;
  1076. y = m_Pos.y;
  1077. dx = dy = 0;
  1078. int width = (m_Thickness == 0) ? GetDefaultLineThickness() : m_Thickness;
  1079. height = ( (m_Size.y * 15) / 10 ) + width + 2 * TXTMARGE;
  1080. // text X size add height for triangular shapes(bidirectional)
  1081. length = LenSize( GetShownText() ) + height + DANGLING_SYMBOL_SIZE;
  1082. switch( m_schematicOrientation ) // respect orientation
  1083. {
  1084. case 0: /* Horiz Normal Orientation (left justified) */
  1085. dx = -length;
  1086. dy = height;
  1087. x += DANGLING_SYMBOL_SIZE;
  1088. y -= height / 2;
  1089. break;
  1090. case 1: /* Vert Orientation UP */
  1091. dx = height;
  1092. dy = -length;
  1093. x -= height / 2;
  1094. y += DANGLING_SYMBOL_SIZE;
  1095. break;
  1096. case 2: /* Horiz Orientation - Right justified */
  1097. dx = length;
  1098. dy = height;
  1099. x -= DANGLING_SYMBOL_SIZE;
  1100. y -= height / 2;
  1101. break;
  1102. case 3: /* Vert Orientation BOTTOM */
  1103. dx = height;
  1104. dy = length;
  1105. x -= height / 2;
  1106. y -= DANGLING_SYMBOL_SIZE;
  1107. break;
  1108. }
  1109. EDA_RECT box( wxPoint( x, y ), wxSize( dx, dy ) );
  1110. box.Normalize();
  1111. return box;
  1112. }
  1113. wxString SCH_GLOBALLABEL::GetSelectMenuText() const
  1114. {
  1115. wxString msg;
  1116. msg.Printf( _( "Global Label %s" ), GetChars( ShortenedShownText() ) );
  1117. return msg;
  1118. }
  1119. SCH_HIERLABEL::SCH_HIERLABEL( const wxPoint& pos, const wxString& text, KICAD_T aType ) :
  1120. SCH_TEXT( pos, text, aType )
  1121. {
  1122. m_Layer = LAYER_HIERLABEL;
  1123. m_shape = NET_INPUT;
  1124. m_isDangling = true;
  1125. m_MultilineAllowed = false;
  1126. }
  1127. EDA_ITEM* SCH_HIERLABEL::Clone() const
  1128. {
  1129. return new SCH_HIERLABEL( *this );
  1130. }
  1131. bool SCH_HIERLABEL::Save( FILE* aFile ) const
  1132. {
  1133. bool success = true;
  1134. const char* shape = "~";
  1135. if( m_Italic )
  1136. shape = "Italic";
  1137. if( fprintf( aFile, "Text HLabel %-4d %-4d %-4d %-4d %s %s %d\n%s\n",
  1138. m_Pos.x, m_Pos.y, m_schematicOrientation, m_Size.x,
  1139. SheetLabelType[m_shape], shape, m_Thickness, TO_UTF8( m_Text ) ) == EOF )
  1140. {
  1141. success = false;
  1142. }
  1143. return success;
  1144. }
  1145. bool SCH_HIERLABEL::Load( LINE_READER& aLine, wxString& aErrorMsg )
  1146. {
  1147. char Name1[256];
  1148. char Name2[256];
  1149. char Name3[256];
  1150. int thickness = 0, size = 0, orient = 0;
  1151. Name1[0] = 0; Name2[0] = 0; Name3[0] = 0;
  1152. char* sline = (char*) aLine;
  1153. while( (*sline != ' ' ) && *sline )
  1154. sline++;
  1155. // sline points the start of parameters
  1156. int ii = sscanf( sline, "%s %d %d %d %d %s %s %d", Name1, &m_Pos.x, &m_Pos.y,
  1157. &orient, &size, Name2, Name3, &thickness );
  1158. if( ii < 4 )
  1159. {
  1160. aErrorMsg.Printf( wxT( "Eeschema file hierarchical label load error at line %d" ),
  1161. aLine.LineNumber() );
  1162. return false;
  1163. }
  1164. if( !aLine.ReadLine() )
  1165. {
  1166. aErrorMsg.Printf( wxT( "Eeschema file hierarchical label load error at line %d" ),
  1167. aLine.LineNumber() );
  1168. return false;
  1169. }
  1170. if( size == 0 )
  1171. size = GetDefaultTextSize();
  1172. char* text = strtok( (char*) aLine, "\n\r" );
  1173. if( text == NULL )
  1174. {
  1175. aErrorMsg.Printf( wxT( "Eeschema file hierarchical label load error at line %d" ),
  1176. aLine.LineNumber() );
  1177. return false;
  1178. }
  1179. m_Text = FROM_UTF8( text );
  1180. m_Size.x = m_Size.y = size;
  1181. SetOrientation( orient );
  1182. m_shape = NET_INPUT;
  1183. m_Bold = ( thickness != 0 );
  1184. m_Thickness = m_Bold ? GetPenSizeForBold( size ) : 0;
  1185. if( stricmp( Name2, SheetLabelType[NET_OUTPUT] ) == 0 )
  1186. m_shape = NET_OUTPUT;
  1187. if( stricmp( Name2, SheetLabelType[NET_BIDI] ) == 0 )
  1188. m_shape = NET_BIDI;
  1189. if( stricmp( Name2, SheetLabelType[NET_TRISTATE] ) == 0 )
  1190. m_shape = NET_TRISTATE;
  1191. if( stricmp( Name2, SheetLabelType[NET_UNSPECIFIED] ) == 0 )
  1192. m_shape = NET_UNSPECIFIED;
  1193. if( stricmp( Name3, "Italic" ) == 0 )
  1194. m_Italic = 1;
  1195. return true;
  1196. }
  1197. void SCH_HIERLABEL::SetOrientation( int aOrientation )
  1198. {
  1199. m_schematicOrientation = aOrientation;
  1200. switch( m_schematicOrientation )
  1201. {
  1202. default:
  1203. case 0: /* Horiz Normal Orientation */
  1204. m_Orient = TEXT_ORIENT_HORIZ;
  1205. m_HJustify = GR_TEXT_HJUSTIFY_RIGHT;
  1206. m_VJustify = GR_TEXT_VJUSTIFY_CENTER;
  1207. break;
  1208. case 1: /* Vert Orientation UP */
  1209. m_Orient = TEXT_ORIENT_VERT;
  1210. m_HJustify = GR_TEXT_HJUSTIFY_LEFT;
  1211. m_VJustify = GR_TEXT_VJUSTIFY_CENTER;
  1212. break;
  1213. case 2: /* Horiz Orientation */
  1214. m_Orient = TEXT_ORIENT_HORIZ;
  1215. m_HJustify = GR_TEXT_HJUSTIFY_LEFT;
  1216. m_VJustify = GR_TEXT_VJUSTIFY_CENTER;
  1217. break;
  1218. case 3: /* Vert Orientation BOTTOM */
  1219. m_Orient = TEXT_ORIENT_VERT;
  1220. m_HJustify = GR_TEXT_HJUSTIFY_RIGHT;
  1221. m_VJustify = GR_TEXT_VJUSTIFY_CENTER;
  1222. break;
  1223. }
  1224. }
  1225. void SCH_HIERLABEL::Draw( EDA_DRAW_PANEL* panel,
  1226. wxDC* DC,
  1227. const wxPoint& offset,
  1228. GR_DRAWMODE DrawMode,
  1229. EDA_COLOR_T Color )
  1230. {
  1231. static std::vector <wxPoint> Poly;
  1232. EDA_COLOR_T color;
  1233. int linewidth = m_Thickness == 0 ?
  1234. GetDefaultLineThickness() : m_Thickness;
  1235. EDA_RECT* clipbox = panel? panel->GetClipBox() : NULL;
  1236. linewidth = Clamp_Text_PenSize( linewidth, m_Size, m_Bold );
  1237. if( Color >= 0 )
  1238. color = Color;
  1239. else
  1240. color = GetLayerColor( m_Layer );
  1241. GRSetDrawMode( DC, DrawMode );
  1242. EXCHG( linewidth, m_Thickness ); // Set the minimum width
  1243. wxPoint text_offset = offset + GetSchematicTextOffset();
  1244. EDA_TEXT::Draw( clipbox, DC, text_offset, color, DrawMode, FILLED, UNSPECIFIED_COLOR );
  1245. EXCHG( linewidth, m_Thickness ); // set initial value
  1246. CreateGraphicShape( Poly, m_Pos + offset );
  1247. GRPoly( clipbox, DC, Poly.size(), &Poly[0], 0, linewidth, color, color );
  1248. if( m_isDangling )
  1249. DrawDanglingSymbol( panel, DC, m_Pos + offset, color );
  1250. // Enable these line to draw the bounding box (debug tests purposes only)
  1251. #if 0
  1252. {
  1253. EDA_RECT BoundaryBox = GetBoundingBox();
  1254. GRRect( clipbox, DC, BoundaryBox, 0, BROWN );
  1255. }
  1256. #endif
  1257. }
  1258. void SCH_HIERLABEL::CreateGraphicShape( std::vector <wxPoint>& aPoints, const wxPoint& Pos )
  1259. {
  1260. int* Template = TemplateShape[m_shape][m_schematicOrientation];
  1261. int HalfSize = m_Size.x / 2;
  1262. int imax = *Template; Template++;
  1263. aPoints.clear();
  1264. for( int ii = 0; ii < imax; ii++ )
  1265. {
  1266. wxPoint corner;
  1267. corner.x = ( HalfSize * (*Template) ) + Pos.x;
  1268. Template++;
  1269. corner.y = ( HalfSize * (*Template) ) + Pos.y;
  1270. Template++;
  1271. aPoints.push_back( corner );
  1272. }
  1273. }
  1274. const EDA_RECT SCH_HIERLABEL::GetBoundingBox() const
  1275. {
  1276. int x, y, dx, dy, length, height;
  1277. x = m_Pos.x;
  1278. y = m_Pos.y;
  1279. dx = dy = 0;
  1280. int width = (m_Thickness == 0) ? GetDefaultLineThickness() : m_Thickness;
  1281. height = m_Size.y + width + 2 * TXTMARGE;
  1282. length = LenSize( GetShownText() )
  1283. + height // add height for triangular shapes
  1284. + 2 * DANGLING_SYMBOL_SIZE;
  1285. switch( m_schematicOrientation ) // respect orientation
  1286. {
  1287. case 0: /* Horiz Normal Orientation (left justified) */
  1288. dx = -length;
  1289. dy = height;
  1290. x += DANGLING_SYMBOL_SIZE;
  1291. y -= height / 2;
  1292. break;
  1293. case 1: /* Vert Orientation UP */
  1294. dx = height;
  1295. dy = -length;
  1296. x -= height / 2;
  1297. y += DANGLING_SYMBOL_SIZE;
  1298. break;
  1299. case 2: /* Horiz Orientation - Right justified */
  1300. dx = length;
  1301. dy = height;
  1302. x -= DANGLING_SYMBOL_SIZE;
  1303. y -= height / 2;
  1304. break;
  1305. case 3: /* Vert Orientation BOTTOM */
  1306. dx = height;
  1307. dy = length;
  1308. x -= height / 2;
  1309. y -= DANGLING_SYMBOL_SIZE;
  1310. break;
  1311. }
  1312. EDA_RECT box( wxPoint( x, y ), wxSize( dx, dy ) );
  1313. box.Normalize();
  1314. return box;
  1315. }
  1316. wxPoint SCH_HIERLABEL::GetSchematicTextOffset() const
  1317. {
  1318. wxPoint text_offset;
  1319. int width = std::max( m_Thickness, GetDefaultLineThickness() );
  1320. int ii = m_Size.x + TXTMARGE + width;
  1321. switch( m_schematicOrientation )
  1322. {
  1323. case 0: /* Orientation horiz normale */
  1324. text_offset.x = -ii;
  1325. break;
  1326. case 1: /* Orientation vert UP */
  1327. text_offset.y = -ii;
  1328. break;
  1329. case 2: /* Orientation horiz inverse */
  1330. text_offset.x = ii;
  1331. break;
  1332. case 3: /* Orientation vert BOTTOM */
  1333. text_offset.y = ii;
  1334. break;
  1335. }
  1336. return text_offset;
  1337. }
  1338. void SCH_HIERLABEL::MirrorY( int aYaxis_position )
  1339. {
  1340. /* The hierarchical label is NOT really mirrored for an horizontal label, the schematic
  1341. * orientation is changed. For a vertical label, the schematic orientation is not changed
  1342. * and the label is moved to a suitable position.
  1343. */
  1344. switch( GetOrientation() )
  1345. {
  1346. case 0: /* horizontal text */
  1347. SetOrientation( 2 );
  1348. break;
  1349. case 2: /* invert horizontal text*/
  1350. SetOrientation( 0 );
  1351. break;
  1352. }
  1353. m_Pos.x -= aYaxis_position;
  1354. NEGATE( m_Pos.x );
  1355. m_Pos.x += aYaxis_position;
  1356. }
  1357. void SCH_HIERLABEL::MirrorX( int aXaxis_position )
  1358. {
  1359. switch( GetOrientation() )
  1360. {
  1361. case 1: /* vertical text */
  1362. SetOrientation( 3 );
  1363. break;
  1364. case 3: /* invert vertical text*/
  1365. SetOrientation( 1 );
  1366. break;
  1367. }
  1368. m_Pos.y -= aXaxis_position;
  1369. NEGATE( m_Pos.y );
  1370. m_Pos.y += aXaxis_position;
  1371. }
  1372. void SCH_HIERLABEL::Rotate( wxPoint aPosition )
  1373. {
  1374. RotatePoint( &m_Pos, aPosition, 900 );
  1375. SetOrientation( (GetOrientation() + 3) % 4 );
  1376. }
  1377. wxString SCH_HIERLABEL::GetSelectMenuText() const
  1378. {
  1379. wxString msg;
  1380. msg.Printf( _( "Hierarchical Label %s" ), GetChars( ShortenedShownText() ) );
  1381. return msg;
  1382. }