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.

468 lines
11 KiB

  1. /**
  2. * @file class_module.cpp
  3. * @brief TEXT_MODULE class implementation.
  4. */
  5. #include "fctsys.h"
  6. #include "gr_basic.h"
  7. #include "wxstruct.h"
  8. #include "trigo.h"
  9. #include "class_drawpanel.h"
  10. #include "drawtxt.h"
  11. #include "kicad_string.h"
  12. #include "pcbcommon.h"
  13. #include "colors_selection.h"
  14. #include "richio.h"
  15. #include "macros.h"
  16. #include "wxBasePcbFrame.h"
  17. #include "class_board.h"
  18. #include "class_module.h"
  19. #include "pcbnew.h"
  20. TEXTE_MODULE::TEXTE_MODULE( MODULE* parent, int text_type ) :
  21. BOARD_ITEM( parent, PCB_MODULE_TEXT_T ), EDA_TEXT()
  22. {
  23. MODULE* Module = (MODULE*) m_Parent;
  24. m_Type = text_type; /* Reference */
  25. if( (m_Type != TEXT_is_REFERENCE) && (m_Type != TEXT_is_VALUE) )
  26. m_Type = TEXT_is_DIVERS;
  27. m_NoShow = false;
  28. m_Size.x = m_Size.y = 400;
  29. m_Thickness = 120; /* Set default dimension to a reasonable value. */
  30. SetLayer( SILKSCREEN_N_FRONT );
  31. if( Module && ( Module->Type() == PCB_MODULE_T ) )
  32. {
  33. m_Pos = Module->m_Pos;
  34. int moduleLayer = Module->GetLayer();
  35. if( moduleLayer == LAYER_N_BACK )
  36. SetLayer( SILKSCREEN_N_BACK );
  37. else if( moduleLayer == LAYER_N_FRONT )
  38. SetLayer( SILKSCREEN_N_FRONT );
  39. else
  40. SetLayer( moduleLayer );
  41. if( moduleLayer == SILKSCREEN_N_BACK
  42. || moduleLayer == ADHESIVE_N_BACK
  43. || moduleLayer == LAYER_N_BACK )
  44. {
  45. m_Mirror = true;
  46. }
  47. }
  48. }
  49. TEXTE_MODULE::~TEXTE_MODULE()
  50. {
  51. }
  52. void TEXTE_MODULE::Copy( TEXTE_MODULE* source )
  53. {
  54. if( source == NULL )
  55. return;
  56. m_Pos = source->m_Pos;
  57. SetLayer( source->GetLayer() );
  58. m_Mirror = source->m_Mirror;
  59. m_NoShow = source->m_NoShow;
  60. m_Type = source->m_Type;
  61. m_Orient = source->m_Orient;
  62. m_Pos0 = source->m_Pos0;
  63. m_Size = source->m_Size;
  64. m_Thickness = source->m_Thickness;
  65. m_Italic = source->m_Italic;
  66. m_Bold = source->m_Bold;
  67. m_Text = source->m_Text;
  68. }
  69. int TEXTE_MODULE:: GetLength() const
  70. {
  71. return m_Text.Len();
  72. }
  73. // Update draw coordinates
  74. void TEXTE_MODULE:: SetDrawCoord()
  75. {
  76. MODULE* Module = (MODULE*) m_Parent;
  77. m_Pos = m_Pos0;
  78. if( Module == NULL )
  79. return;
  80. int angle = Module->m_Orient;
  81. NORMALIZE_ANGLE_POS( angle );
  82. RotatePoint( &m_Pos.x, &m_Pos.y, angle );
  83. m_Pos += Module->m_Pos;
  84. }
  85. // Update "local" coordinates (coordinates relatives to the footprint
  86. // anchor point)
  87. void TEXTE_MODULE:: SetLocalCoord()
  88. {
  89. MODULE* Module = (MODULE*) m_Parent;
  90. if( Module == NULL )
  91. {
  92. m_Pos0 = m_Pos;
  93. return;
  94. }
  95. m_Pos0 = m_Pos - Module->m_Pos;
  96. int angle = Module->m_Orient;
  97. NORMALIZE_ANGLE_POS( angle );
  98. RotatePoint( &m_Pos0.x, &m_Pos0.y, -angle );
  99. }
  100. /**
  101. * Function GetTextRect
  102. * @return an EDA_RECT which gives the position and size of the text area
  103. * (for the footprint orientation)
  104. */
  105. EDA_RECT TEXTE_MODULE::GetTextRect( void ) const
  106. {
  107. EDA_RECT area;
  108. int dx, dy;
  109. dx = ( m_Size.x * GetLength() ) / 2;
  110. dx = (dx * 10) / 9; /* letter size = 10/9 */
  111. dx += m_Thickness / 2;
  112. dy = ( m_Size.y + m_Thickness ) / 2;
  113. wxPoint Org = m_Pos; // This is the position of the center of the area
  114. Org.x -= dx;
  115. Org.y -= dy;
  116. area.SetOrigin( Org );
  117. area.SetHeight( 2 * dy );
  118. area.SetWidth( 2 * dx );
  119. area.Normalize();
  120. return area;
  121. }
  122. /**
  123. * Function HitTest
  124. * tests if the given wxPoint is within the bounds of this object.
  125. * @param aRefPos A wxPoint to test
  126. * @return true if a hit, else false
  127. */
  128. bool TEXTE_MODULE::HitTest( const wxPoint& aRefPos )
  129. {
  130. wxPoint rel_pos;
  131. EDA_RECT area = GetTextRect();
  132. /* Rotate refPos to - angle
  133. * to test if refPos is within area (which is relative to an horizontal
  134. * text)
  135. */
  136. rel_pos = aRefPos;
  137. RotatePoint( &rel_pos, m_Pos, -GetDrawRotation() );
  138. if( area.Contains( rel_pos ) )
  139. return true;
  140. return false;
  141. }
  142. /**
  143. * Function GetBoundingBox
  144. * returns the bounding box of this Text (according to text and footprint
  145. * orientation)
  146. */
  147. EDA_RECT TEXTE_MODULE::GetBoundingBox() const
  148. {
  149. // Calculate area without text fields:
  150. EDA_RECT text_area;
  151. int angle = GetDrawRotation();
  152. wxPoint textstart, textend;
  153. text_area = GetTextRect();
  154. textstart = text_area.GetOrigin();
  155. textend = text_area.GetEnd();
  156. RotatePoint( &textstart, m_Pos, angle );
  157. RotatePoint( &textend, m_Pos, angle );
  158. text_area.SetOrigin( textstart );
  159. text_area.SetEnd( textend );
  160. text_area.Normalize();
  161. return text_area;
  162. }
  163. /**
  164. * Function Draw
  165. * Draw the text according to the footprint pos and orient
  166. * @param panel = draw panel, Used to know the clip box
  167. * @param DC = Current Device Context
  168. * @param offset = draw offset (usually wxPoint(0,0)
  169. * @param draw_mode = GR_OR, GR_XOR..
  170. */
  171. void TEXTE_MODULE::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, int draw_mode, const wxPoint& offset )
  172. {
  173. int width, color, orient;
  174. wxSize size;
  175. wxPoint pos; // Center of text
  176. PCB_BASE_FRAME* frame;
  177. MODULE* Module = (MODULE*) m_Parent; /* parent must *not* be null
  178. * (a module text without a footprint
  179. * parent has no sense) */
  180. if( panel == NULL )
  181. return;
  182. frame = (PCB_BASE_FRAME*) panel->GetParent();
  183. pos.x = m_Pos.x - offset.x;
  184. pos.y = m_Pos.y - offset.y;
  185. size = m_Size;
  186. orient = GetDrawRotation();
  187. width = m_Thickness;
  188. if( ( frame->m_DisplayModText == LINE )
  189. || ( DC->LogicalToDeviceXRel( width ) < MIN_DRAW_WIDTH ) )
  190. width = 0;
  191. else if( frame->m_DisplayModText == SKETCH )
  192. width = -width;
  193. GRSetDrawMode( DC, draw_mode );
  194. BOARD * brd = GetBoard( );
  195. if( brd->IsElementVisible( ANCHOR_VISIBLE ) )
  196. {
  197. color = brd->GetVisibleElementColor(ANCHOR_VISIBLE);
  198. int anchor_size = DC->DeviceToLogicalXRel( 2 );
  199. GRLine( panel->GetClipBox(), DC,
  200. pos.x - anchor_size, pos.y,
  201. pos.x + anchor_size, pos.y, 0, color );
  202. GRLine( panel->GetClipBox(), DC,
  203. pos.x, pos.y - anchor_size,
  204. pos.x, pos.y + anchor_size, 0, color );
  205. }
  206. color = brd->GetLayerColor(Module->GetLayer());
  207. if( Module->GetLayer() == LAYER_N_BACK )
  208. {
  209. if( brd->IsElementVisible( MOD_TEXT_BK_VISIBLE ) == false )
  210. return;
  211. color = brd->GetVisibleElementColor(MOD_TEXT_BK_VISIBLE);
  212. }
  213. else if( Module->GetLayer() == LAYER_N_FRONT )
  214. {
  215. if( brd->IsElementVisible( MOD_TEXT_FR_VISIBLE ) == false )
  216. return;
  217. color = brd->GetVisibleElementColor(MOD_TEXT_FR_VISIBLE);
  218. }
  219. if( m_NoShow )
  220. {
  221. if( brd->IsElementVisible( MOD_TEXT_INVISIBLE ) == false )
  222. return;
  223. color = brd->GetVisibleElementColor(MOD_TEXT_INVISIBLE);
  224. }
  225. /* If the text is mirrored : negate size.x (mirror / Y axis) */
  226. if( m_Mirror )
  227. size.x = -size.x;
  228. DrawGraphicText( panel, DC, pos, (enum EDA_Colors) color, m_Text, orient,
  229. size, m_HJustify, m_VJustify, width, m_Italic, m_Bold );
  230. }
  231. /* Draws a line from the TEXTE_MODULE origin to parent MODULE origin.
  232. */
  233. void TEXTE_MODULE::DrawUmbilical( EDA_DRAW_PANEL* aPanel,
  234. wxDC* aDC,
  235. int aDrawMode,
  236. const wxPoint& aOffset )
  237. {
  238. MODULE* parent = (MODULE*) GetParent();
  239. if( !parent )
  240. return;
  241. GRSetDrawMode( aDC, GR_XOR );
  242. GRLine( aPanel->GetClipBox(), aDC,
  243. parent->GetPosition(), GetPosition() + aOffset,
  244. 0, UMBILICAL_COLOR);
  245. }
  246. /* Return text rotation for drawings and plotting
  247. */
  248. int TEXTE_MODULE::GetDrawRotation() const
  249. {
  250. int rotation;
  251. MODULE* Module = (MODULE*) m_Parent;
  252. rotation = m_Orient;
  253. if( Module )
  254. rotation += Module->m_Orient;
  255. NORMALIZE_ANGLE_POS( rotation );
  256. // For angle = 0 .. 180 deg
  257. while( rotation > 900 )
  258. rotation -= 1800;
  259. return rotation;
  260. }
  261. // see class_text_mod.h
  262. void TEXTE_MODULE::DisplayInfo( EDA_DRAW_FRAME* frame )
  263. {
  264. MODULE* module = (MODULE*) m_Parent;
  265. if( module == NULL ) // Happens in modedit, and for new texts
  266. return;
  267. wxString msg, Line;
  268. int ii;
  269. static const wxString text_type_msg[3] =
  270. {
  271. _( "Ref." ), _( "Value" ), _( "Text" )
  272. };
  273. frame->ClearMsgPanel();
  274. Line = module->m_Reference->m_Text;
  275. frame->AppendMsgPanel( _( "Module" ), Line, DARKCYAN );
  276. Line = m_Text;
  277. frame->AppendMsgPanel( _( "Text" ), Line, BROWN );
  278. ii = m_Type;
  279. if( ii > 2 )
  280. ii = 2;
  281. frame->AppendMsgPanel( _( "Type" ), text_type_msg[ii], DARKGREEN );
  282. if( m_NoShow )
  283. msg = _( "No" );
  284. else
  285. msg = _( "Yes" );
  286. frame->AppendMsgPanel( _( "Display" ), msg, DARKGREEN );
  287. // Display text layer (use layer name if possible)
  288. BOARD* board = NULL;
  289. board = (BOARD*) module->GetParent();
  290. if( m_Layer < NB_LAYERS && board )
  291. msg = board->GetLayerName( m_Layer );
  292. else
  293. msg.Printf( wxT( "%d" ), m_Layer );
  294. frame->AppendMsgPanel( _( "Layer" ), msg, DARKGREEN );
  295. msg = _( " No" );
  296. if( m_Mirror )
  297. msg = _( " Yes" );
  298. frame->AppendMsgPanel( _( "Mirror" ), msg, DARKGREEN );
  299. msg.Printf( wxT( "%.1f" ), (float) m_Orient / 10 );
  300. frame->AppendMsgPanel( _( "Orient" ), msg, DARKGREEN );
  301. valeur_param( m_Thickness, msg );
  302. frame->AppendMsgPanel( _( "Thickness" ), msg, DARKGREEN );
  303. valeur_param( m_Size.x, msg );
  304. frame->AppendMsgPanel( _( "H Size" ), msg, RED );
  305. valeur_param( m_Size.y, msg );
  306. frame->AppendMsgPanel( _( "V Size" ), msg, RED );
  307. }
  308. // see class_text_mod.h
  309. bool TEXTE_MODULE::IsOnLayer( int aLayer ) const
  310. {
  311. if( m_Layer == aLayer )
  312. return true;
  313. /* test the parent, which is a MODULE */
  314. if( aLayer == GetParent()->GetLayer() )
  315. return true;
  316. if( aLayer == LAYER_N_BACK )
  317. {
  318. if( m_Layer==ADHESIVE_N_BACK || m_Layer==SILKSCREEN_N_BACK )
  319. return true;
  320. }
  321. else if( aLayer == LAYER_N_FRONT )
  322. {
  323. if( m_Layer==ADHESIVE_N_FRONT || m_Layer==SILKSCREEN_N_FRONT )
  324. return true;
  325. }
  326. return false;
  327. }
  328. /* see class_text_mod.h
  329. * bool TEXTE_MODULE::IsOnOneOfTheseLayers( int aLayerMask ) const
  330. * {
  331. *
  332. * }
  333. */
  334. wxString TEXTE_MODULE::GetSelectMenuText() const
  335. {
  336. wxString text;
  337. switch( m_Type )
  338. {
  339. case TEXT_is_REFERENCE:
  340. text << _( "Reference" ) << wxT( " " ) << m_Text;
  341. break;
  342. case TEXT_is_VALUE:
  343. text << _( "Value" ) << wxT( " " ) << m_Text << _( " of " )
  344. << ( (MODULE*) GetParent() )->GetReference();
  345. break;
  346. default: // wrap this one in quotes:
  347. text << _( "Text" ) << wxT( " \"" ) << m_Text << wxT( "\"" ) << _( " of " )
  348. << ( (MODULE*) GetParent() )->GetReference();
  349. break;
  350. }
  351. return text;
  352. }
  353. #if defined(DEBUG)
  354. void TEXTE_MODULE::Show( int nestLevel, std::ostream& os ) const
  355. {
  356. // for now, make it look like XML:
  357. NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() <<
  358. " string=\"" << m_Text.mb_str() << "\"/>\n";
  359. // NestedSpace( nestLevel, os ) << "</" << GetClass().Lower().mb_str()
  360. // << ">\n";
  361. }
  362. #endif