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.

604 lines
20 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2022-2024 KiCad Developers, see AUTHORS.txt for contributors.
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version 2
  9. * of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, you may find one here:
  18. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  19. * or you may search the http://www.gnu.org website for the version 2 license,
  20. * or you may write to the Free Software Foundation, Inc.,
  21. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  22. */
  23. #include <base_units.h>
  24. #include <pgm_base.h>
  25. #include <sch_edit_frame.h>
  26. #include <plotters/plotter.h>
  27. #include <widgets/msgpanel.h>
  28. #include <bitmaps.h>
  29. #include <string_utils.h>
  30. #include <schematic.h>
  31. #include <settings/color_settings.h>
  32. #include <sch_painter.h>
  33. #include <dialogs/html_message_box.h>
  34. #include <project/project_file.h>
  35. #include <project/net_settings.h>
  36. #include <core/kicad_algo.h>
  37. #include <trigo.h>
  38. #include <lib_textbox.h>
  39. using KIGFX::SCH_RENDER_SETTINGS;
  40. LIB_TEXTBOX::LIB_TEXTBOX( LIB_SYMBOL* aParent, int aLineWidth, FILL_T aFillType,
  41. const wxString& text ) :
  42. LIB_SHAPE( aParent, SHAPE_T::RECTANGLE, aLineWidth, aFillType, LIB_TEXTBOX_T ),
  43. EDA_TEXT( schIUScale, text )
  44. {
  45. SetTextSize( VECTOR2I( schIUScale.MilsToIU( DEFAULT_TEXT_SIZE ),
  46. schIUScale.MilsToIU( DEFAULT_TEXT_SIZE ) ) );
  47. SetHorizJustify( GR_TEXT_H_ALIGN_LEFT );
  48. SetVertJustify( GR_TEXT_V_ALIGN_TOP );
  49. SetMultilineAllowed( true );
  50. int defaultMargin = GetLegacyTextMargin();
  51. m_marginLeft = defaultMargin;
  52. m_marginTop = defaultMargin;
  53. m_marginRight = defaultMargin;
  54. m_marginBottom = defaultMargin;
  55. }
  56. LIB_TEXTBOX::LIB_TEXTBOX( const LIB_TEXTBOX& aText ) :
  57. LIB_SHAPE( aText ),
  58. EDA_TEXT( aText )
  59. {
  60. m_marginLeft = aText.m_marginLeft;
  61. m_marginTop = aText.m_marginTop;
  62. m_marginRight = aText.m_marginRight;
  63. m_marginBottom = aText.m_marginBottom;
  64. }
  65. int LIB_TEXTBOX::GetLegacyTextMargin() const
  66. {
  67. return KiROUND( GetTextSize().y * 0.8 );
  68. }
  69. void LIB_TEXTBOX::MirrorHorizontally( const VECTOR2I& center )
  70. {
  71. // Text is NOT really mirrored; it just has its justification flipped
  72. if( GetTextAngle() == ANGLE_HORIZONTAL )
  73. {
  74. switch( GetHorizJustify() )
  75. {
  76. case GR_TEXT_H_ALIGN_LEFT: SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT ); break;
  77. case GR_TEXT_H_ALIGN_CENTER: break;
  78. case GR_TEXT_H_ALIGN_RIGHT: SetHorizJustify( GR_TEXT_H_ALIGN_LEFT ); break;
  79. }
  80. }
  81. }
  82. void LIB_TEXTBOX::MirrorVertically( const VECTOR2I& center )
  83. {
  84. // Text is NOT really mirrored; it just has its justification flipped
  85. if( GetTextAngle() == ANGLE_VERTICAL )
  86. {
  87. switch( GetHorizJustify() )
  88. {
  89. case GR_TEXT_H_ALIGN_LEFT: SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT ); break;
  90. case GR_TEXT_H_ALIGN_CENTER: break;
  91. case GR_TEXT_H_ALIGN_RIGHT: SetHorizJustify( GR_TEXT_H_ALIGN_LEFT ); break;
  92. }
  93. }
  94. }
  95. void LIB_TEXTBOX::Rotate( const VECTOR2I& aCenter, bool aRotateCCW )
  96. {
  97. LIB_SHAPE::Rotate( aCenter, aRotateCCW );
  98. SetTextAngle( GetTextAngle() == ANGLE_VERTICAL ? ANGLE_HORIZONTAL : ANGLE_VERTICAL );
  99. }
  100. VECTOR2I LIB_TEXTBOX::GetDrawPos() const
  101. {
  102. BOX2I bbox( VECTOR2I( std::min( m_start.x, m_end.x ), std::min( -m_start.y, -m_end.y ) ),
  103. VECTOR2I( abs( m_end.x - m_start.x ), abs( m_end.y - m_start.y ) ) );
  104. VECTOR2I pos( bbox.GetLeft() + m_marginLeft, bbox.GetBottom() - m_marginBottom );
  105. if( GetTextAngle().IsVertical() )
  106. {
  107. switch( GetHorizJustify() )
  108. {
  109. case GR_TEXT_H_ALIGN_LEFT:
  110. pos.y = bbox.GetBottom() - m_marginBottom;
  111. break;
  112. case GR_TEXT_H_ALIGN_CENTER:
  113. pos.y = ( bbox.GetTop() + bbox.GetBottom() ) / 2;
  114. break;
  115. case GR_TEXT_H_ALIGN_RIGHT:
  116. pos.y = bbox.GetTop() + m_marginTop;
  117. break;
  118. }
  119. switch( GetVertJustify() )
  120. {
  121. case GR_TEXT_V_ALIGN_TOP:
  122. pos.x = bbox.GetLeft() + m_marginLeft;
  123. break;
  124. case GR_TEXT_V_ALIGN_CENTER:
  125. pos.x = ( bbox.GetLeft() + bbox.GetRight() ) / 2;
  126. break;
  127. case GR_TEXT_V_ALIGN_BOTTOM:
  128. pos.x = bbox.GetRight() - m_marginRight;
  129. break;
  130. }
  131. }
  132. else
  133. {
  134. switch( GetHorizJustify() )
  135. {
  136. case GR_TEXT_H_ALIGN_LEFT:
  137. pos.x = bbox.GetLeft() + m_marginLeft;
  138. break;
  139. case GR_TEXT_H_ALIGN_CENTER:
  140. pos.x = ( bbox.GetLeft() + bbox.GetRight() ) / 2;
  141. break;
  142. case GR_TEXT_H_ALIGN_RIGHT:
  143. pos.x = bbox.GetRight() - m_marginRight;
  144. break;
  145. }
  146. switch( GetVertJustify() )
  147. {
  148. case GR_TEXT_V_ALIGN_TOP:
  149. pos.y = bbox.GetTop() + m_marginTop;
  150. break;
  151. case GR_TEXT_V_ALIGN_CENTER:
  152. pos.y = ( bbox.GetTop() + bbox.GetBottom() ) / 2;
  153. break;
  154. case GR_TEXT_V_ALIGN_BOTTOM:
  155. pos.y = bbox.GetBottom() - m_marginBottom;
  156. break;
  157. }
  158. }
  159. return pos;
  160. }
  161. int LIB_TEXTBOX::compare( const LIB_ITEM& aOther, int aCompareFlags ) const
  162. {
  163. wxASSERT( aOther.Type() == LIB_TEXTBOX_T );
  164. int retv = LIB_ITEM::compare( aOther, aCompareFlags );
  165. if( retv )
  166. return retv;
  167. const LIB_TEXTBOX* tmp = static_cast<const LIB_TEXTBOX*>( &aOther );
  168. int result = GetText().CmpNoCase( tmp->GetText() );
  169. if( result != 0 )
  170. return result;
  171. if( GetTextWidth() != tmp->GetTextWidth() )
  172. return GetTextWidth() - tmp->GetTextWidth();
  173. if( GetTextHeight() != tmp->GetTextHeight() )
  174. return GetTextHeight() - tmp->GetTextHeight();
  175. if( IsBold() != tmp->IsBold() )
  176. return IsBold() - tmp->IsBold();
  177. if( IsItalic() != tmp->IsItalic() )
  178. return IsItalic() - tmp->IsItalic();
  179. if( GetHorizJustify() != tmp->GetHorizJustify() )
  180. return GetHorizJustify() - tmp->GetHorizJustify();
  181. if( GetTextAngle().AsTenthsOfADegree() != tmp->GetTextAngle().AsTenthsOfADegree() )
  182. return GetTextAngle().AsTenthsOfADegree() - tmp->GetTextAngle().AsTenthsOfADegree();
  183. if( GetMarginLeft() != tmp->GetMarginLeft() )
  184. return GetMarginLeft() - tmp->GetMarginLeft();
  185. if( GetMarginTop() != tmp->GetMarginTop() )
  186. return GetMarginTop() - tmp->GetMarginTop();
  187. if( GetMarginRight() != tmp->GetMarginRight() )
  188. return GetMarginRight() - tmp->GetMarginRight();
  189. if( GetMarginBottom() != tmp->GetMarginBottom() )
  190. return GetMarginBottom() - tmp->GetMarginBottom();
  191. return EDA_SHAPE::Compare( &static_cast<const LIB_SHAPE&>( aOther ) );
  192. }
  193. KIFONT::FONT* LIB_TEXTBOX::getDrawFont() const
  194. {
  195. KIFONT::FONT* font = EDA_TEXT::GetFont();
  196. if( !font )
  197. font = KIFONT::FONT::GetFont( GetDefaultFont(), IsBold(), IsItalic() );
  198. return font;
  199. }
  200. void LIB_TEXTBOX::print( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffset, void* aData,
  201. const TRANSFORM& aTransform, bool aDimmed )
  202. {
  203. if( IsPrivate() )
  204. return;
  205. bool forceNoFill = static_cast<bool>( aData );
  206. bool blackAndWhiteMode = GetGRForceBlackPenState();
  207. int penWidth = GetEffectivePenWidth( aSettings );
  208. COLOR4D color = GetStroke().GetColor();
  209. LINE_STYLE lineStyle = GetStroke().GetLineStyle();
  210. wxDC* DC = aSettings->GetPrintDC();
  211. VECTOR2I pt1 = aTransform.TransformCoordinate( m_start ) + aOffset;
  212. VECTOR2I pt2 = aTransform.TransformCoordinate( m_end ) + aOffset;
  213. if( !forceNoFill && GetFillMode() == FILL_T::FILLED_WITH_COLOR && !blackAndWhiteMode )
  214. GRFilledRect( DC, pt1, pt2, penWidth, GetFillColor(), GetFillColor() );
  215. if( penWidth > 0 )
  216. {
  217. penWidth = std::max( penWidth, aSettings->GetMinPenWidth() );
  218. if( blackAndWhiteMode || color == COLOR4D::UNSPECIFIED )
  219. color = aSettings->GetLayerColor( LAYER_DEVICE );
  220. COLOR4D bg = aSettings->GetBackgroundColor();
  221. if( bg == COLOR4D::UNSPECIFIED || GetGRForceBlackPenState() )
  222. bg = COLOR4D::WHITE;
  223. if( aDimmed )
  224. {
  225. color.Desaturate( );
  226. color = color.Mix( bg, 0.5f );
  227. }
  228. if( lineStyle == LINE_STYLE::DEFAULT )
  229. lineStyle = LINE_STYLE::SOLID;
  230. if( lineStyle <= LINE_STYLE::FIRST_TYPE )
  231. {
  232. GRRect( DC, pt1, pt2, penWidth, color );
  233. }
  234. else
  235. {
  236. std::vector<SHAPE*> shapes = MakeEffectiveShapes( true );
  237. for( SHAPE* shape : shapes )
  238. {
  239. STROKE_PARAMS::Stroke( shape, lineStyle, penWidth, aSettings,
  240. [&]( const VECTOR2I& a, const VECTOR2I& b )
  241. {
  242. VECTOR2I pts = aTransform.TransformCoordinate( a ) + aOffset;
  243. VECTOR2I pte = aTransform.TransformCoordinate( b ) + aOffset;
  244. GRLine( DC, pts.x, pts.y, pte.x, pte.y, penWidth, color );
  245. } );
  246. }
  247. for( SHAPE* shape : shapes )
  248. delete shape;
  249. }
  250. }
  251. LIB_TEXTBOX text( *this );
  252. color = GetTextColor();
  253. if( blackAndWhiteMode || color == COLOR4D::UNSPECIFIED )
  254. color = aSettings->GetLayerColor( LAYER_DEVICE );
  255. COLOR4D bg = aSettings->GetBackgroundColor();
  256. if( bg == COLOR4D::UNSPECIFIED || GetGRForceBlackPenState() )
  257. bg = COLOR4D::WHITE;
  258. if( aDimmed )
  259. {
  260. color.Desaturate( );
  261. color = color.Mix( bg, 0.5f );
  262. }
  263. penWidth = std::max( GetEffectiveTextPenWidth(), aSettings->GetMinPenWidth() );
  264. if( aTransform.y1 )
  265. {
  266. text.SetTextAngle( text.GetTextAngle() == ANGLE_HORIZONTAL ? ANGLE_VERTICAL
  267. : ANGLE_HORIZONTAL );
  268. }
  269. KIFONT::FONT* font = GetFont();
  270. if( !font )
  271. font = KIFONT::FONT::GetFont( aSettings->GetDefaultFont(), IsBold(), IsItalic() );
  272. // NB: GetDrawPos() will want Symbol Editor (upside-down) coordinates
  273. text.SetStart( VECTOR2I( pt1.x, -pt1.y ) );
  274. text.SetEnd( VECTOR2I( pt2.x, -pt2.y ) );
  275. GRPrintText( DC, text.GetDrawPos(), color, text.GetShownText( true ), text.GetTextAngle(),
  276. text.GetTextSize(), text.GetHorizJustify(), text.GetVertJustify(), penWidth,
  277. text.IsItalic(), text.IsBold(), font, GetFontMetrics() );
  278. }
  279. wxString LIB_TEXTBOX::GetShownText( bool aAllowExtraText, int aDepth ) const
  280. {
  281. wxString text = EDA_TEXT::GetShownText( aAllowExtraText, aDepth );
  282. KIFONT::FONT* font = GetFont();
  283. VECTOR2D size = GetEnd() - GetStart();
  284. int colWidth;
  285. if( GetTextAngle().IsVertical() )
  286. colWidth = abs( size.y ) - ( GetMarginTop() + GetMarginBottom() );
  287. else
  288. colWidth = abs( size.x ) - ( GetMarginLeft() + GetMarginRight() );
  289. if( !font )
  290. font = KIFONT::FONT::GetFont( GetDefaultFont(), IsBold(), IsItalic() );
  291. font->LinebreakText( text, colWidth, GetTextSize(), GetTextThickness(), IsBold(), IsItalic() );
  292. return text;
  293. }
  294. bool LIB_TEXTBOX::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
  295. {
  296. if( aAccuracy < schIUScale.MilsToIU( MINIMUM_SELECTION_DISTANCE ) )
  297. aAccuracy = schIUScale.MilsToIU( MINIMUM_SELECTION_DISTANCE );
  298. BOX2I rect = GetBoundingBox();
  299. rect.Inflate( aAccuracy );
  300. return rect.Contains( aPosition );
  301. }
  302. bool LIB_TEXTBOX::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
  303. {
  304. BOX2I rect = aRect;
  305. rect.Inflate( aAccuracy );
  306. if( aContained )
  307. return rect.Contains( GetBoundingBox() );
  308. return rect.Intersects( GetBoundingBox() );
  309. }
  310. wxString LIB_TEXTBOX::GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const
  311. {
  312. return wxString::Format( _( "Graphic Text Box" ) );
  313. }
  314. BITMAPS LIB_TEXTBOX::GetMenuImage() const
  315. {
  316. return BITMAPS::add_textbox;
  317. }
  318. void LIB_TEXTBOX::Plot( PLOTTER* aPlotter, bool aBackground, const VECTOR2I& aOffset,
  319. const TRANSFORM& aTransform, bool aDimmed ) const
  320. {
  321. wxASSERT( aPlotter != nullptr );
  322. if( IsPrivate() )
  323. return;
  324. if( aBackground )
  325. {
  326. LIB_SHAPE::Plot( aPlotter, aBackground, aOffset, aTransform, aDimmed );
  327. return;
  328. }
  329. RENDER_SETTINGS* renderSettings = aPlotter->RenderSettings();
  330. VECTOR2I start = aTransform.TransformCoordinate( m_start ) + aOffset;
  331. VECTOR2I end = aTransform.TransformCoordinate( m_end ) + aOffset;
  332. COLOR4D bg = renderSettings->GetBackgroundColor();
  333. if( bg == COLOR4D::UNSPECIFIED || !aPlotter->GetColorMode() )
  334. bg = COLOR4D::WHITE;
  335. int penWidth = GetEffectivePenWidth( renderSettings );
  336. COLOR4D color = GetStroke().GetColor();
  337. LINE_STYLE lineStyle = GetStroke().GetLineStyle();
  338. if( penWidth > 0 )
  339. {
  340. if( !aPlotter->GetColorMode() || color == COLOR4D::UNSPECIFIED )
  341. color = renderSettings->GetLayerColor( LAYER_DEVICE );
  342. if( lineStyle == LINE_STYLE::DEFAULT )
  343. lineStyle = LINE_STYLE::SOLID;
  344. if( aDimmed )
  345. {
  346. color.Desaturate( );
  347. color = color.Mix( bg, 0.5f );
  348. }
  349. aPlotter->SetColor( color );
  350. aPlotter->SetDash( penWidth, lineStyle );
  351. aPlotter->Rect( start, end, FILL_T::NO_FILL, penWidth );
  352. aPlotter->SetDash( penWidth, LINE_STYLE::SOLID );
  353. }
  354. KIFONT::FONT* font = GetFont();
  355. if( !font )
  356. font = KIFONT::FONT::GetFont( renderSettings->GetDefaultFont(), IsBold(), IsItalic() );
  357. LIB_TEXTBOX text( *this );
  358. color = GetTextColor();
  359. if( !aPlotter->GetColorMode() || color == COLOR4D::UNSPECIFIED )
  360. color = renderSettings->GetLayerColor( LAYER_DEVICE );
  361. if( aDimmed )
  362. {
  363. color.Desaturate( );
  364. color = color.Mix( bg, 0.5f );
  365. }
  366. penWidth = std::max( GetEffectiveTextPenWidth(), aPlotter->RenderSettings()->GetMinPenWidth() );
  367. if( aTransform.y1 )
  368. {
  369. text.SetTextAngle( text.GetTextAngle() == ANGLE_HORIZONTAL ? ANGLE_VERTICAL
  370. : ANGLE_HORIZONTAL );
  371. }
  372. // NB: GetDrawPos() will want Symbol Editor (upside-down) coordinates
  373. text.SetStart( VECTOR2I( start.x, -start.y ) );
  374. text.SetEnd( VECTOR2I( end.x, -end.y ) );
  375. std::vector<VECTOR2I> positions;
  376. wxArrayString strings_list;
  377. wxStringSplit( GetShownText( true ), strings_list, '\n' );
  378. positions.reserve( strings_list.Count() );
  379. text.GetLinePositions( positions, (int) strings_list.Count() );
  380. TEXT_ATTRIBUTES attrs = text.GetAttributes();
  381. attrs.m_StrokeWidth = penWidth;
  382. attrs.m_Multiline = false;
  383. for( unsigned ii = 0; ii < strings_list.Count(); ii++ )
  384. {
  385. aPlotter->PlotText( positions[ii], color, strings_list.Item( ii ), attrs, font,
  386. GetFontMetrics() );
  387. }
  388. }
  389. void LIB_TEXTBOX::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
  390. {
  391. // Don't use GetShownText() here; we want to show the user the variable references
  392. aList.emplace_back( _( "Text Box" ), KIUI::EllipsizeStatusText( aFrame, GetText() ) );
  393. aList.emplace_back( _( "Font" ), GetFont() ? GetFont()->GetName() : _( "Default" ) );
  394. wxString textStyle[] = { _( "Normal" ), _( "Italic" ), _( "Bold" ), _( "Bold Italic" ) };
  395. int style = IsBold() && IsItalic() ? 3 : IsBold() ? 2 : IsItalic() ? 1 : 0;
  396. aList.emplace_back( _( "Style" ), textStyle[style] );
  397. aList.emplace_back( _( "Text Size" ), aFrame->MessageTextFromValue( GetTextWidth() ) );
  398. aList.emplace_back( _( "Box Width" ),
  399. aFrame->MessageTextFromValue( std::abs( GetEnd().x - GetStart().x ) ) );
  400. aList.emplace_back( _( "Box Height" ),
  401. aFrame->MessageTextFromValue( std::abs( GetEnd().y - GetStart().y ) ) );
  402. m_stroke.GetMsgPanelInfo( aFrame, aList );
  403. }
  404. bool LIB_TEXTBOX::operator==( const LIB_ITEM& aOther ) const
  405. {
  406. if( aOther.Type() != LIB_TEXTBOX_T )
  407. return false;
  408. const LIB_TEXTBOX& other = static_cast<const LIB_TEXTBOX&>( aOther );
  409. return LIB_SHAPE::operator==( other ) && EDA_TEXT::operator==( other );
  410. }
  411. double LIB_TEXTBOX::Similarity( const LIB_ITEM& aOther ) const
  412. {
  413. if( m_Uuid == aOther.m_Uuid )
  414. return 1.0;
  415. if( aOther.Type() != LIB_TEXTBOX_T )
  416. return 0.0;
  417. const LIB_TEXTBOX& other = static_cast<const LIB_TEXTBOX&>( aOther );
  418. double similarity = SimilarityBase( other );
  419. similarity *= LIB_SHAPE::Similarity( other );
  420. similarity *= EDA_TEXT::Similarity( other );
  421. return similarity;
  422. }
  423. void LIB_TEXTBOX::ViewGetLayers( int aLayers[], int& aCount ) const
  424. {
  425. aCount = 3;
  426. aLayers[0] = IsPrivate() ? LAYER_PRIVATE_NOTES : LAYER_DEVICE;
  427. aLayers[1] = IsPrivate() ? LAYER_NOTES_BACKGROUND : LAYER_DEVICE_BACKGROUND;
  428. aLayers[2] = LAYER_SELECTION_SHADOWS;
  429. }
  430. static struct LIB_TEXTBOX_DESC
  431. {
  432. LIB_TEXTBOX_DESC()
  433. {
  434. PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
  435. REGISTER_TYPE( LIB_TEXTBOX );
  436. propMgr.AddTypeCast( new TYPE_CAST<LIB_TEXTBOX, LIB_SHAPE> );
  437. propMgr.AddTypeCast( new TYPE_CAST<LIB_TEXTBOX, EDA_SHAPE> );
  438. propMgr.AddTypeCast( new TYPE_CAST<LIB_TEXTBOX, EDA_TEXT> );
  439. propMgr.InheritsAfter( TYPE_HASH( LIB_TEXTBOX ), TYPE_HASH( LIB_SHAPE ) );
  440. propMgr.InheritsAfter( TYPE_HASH( LIB_TEXTBOX ), TYPE_HASH( EDA_SHAPE ) );
  441. propMgr.InheritsAfter( TYPE_HASH( LIB_TEXTBOX ), TYPE_HASH( EDA_TEXT ) );
  442. propMgr.Mask( TYPE_HASH( LIB_TEXTBOX ), TYPE_HASH( EDA_SHAPE ), _HKI( "Shape" ) );
  443. propMgr.Mask( TYPE_HASH( LIB_TEXTBOX ), TYPE_HASH( EDA_TEXT ), _HKI( "Visible" ) );
  444. propMgr.Mask( TYPE_HASH( LIB_TEXTBOX ), TYPE_HASH( EDA_TEXT ), _HKI( "Width" ) );
  445. propMgr.Mask( TYPE_HASH( LIB_TEXTBOX ), TYPE_HASH( EDA_TEXT ), _HKI( "Height" ) );
  446. propMgr.Mask( TYPE_HASH( LIB_TEXTBOX ), TYPE_HASH( EDA_TEXT ), _HKI( "Thickness" ) );
  447. propMgr.AddProperty( new PROPERTY<LIB_TEXTBOX, int>( _HKI( "Margin Left" ),
  448. &LIB_TEXTBOX::SetMarginLeft, &LIB_TEXTBOX::GetMarginLeft, PROPERTY_DISPLAY::PT_SIZE ) );
  449. propMgr.AddProperty( new PROPERTY<LIB_TEXTBOX, int>( _HKI( "Margin Top" ),
  450. &LIB_TEXTBOX::SetMarginTop, &LIB_TEXTBOX::GetMarginTop, PROPERTY_DISPLAY::PT_SIZE ) );
  451. propMgr.AddProperty( new PROPERTY<LIB_TEXTBOX, int>( _HKI( "Margin Right" ),
  452. &LIB_TEXTBOX::SetMarginRight, &LIB_TEXTBOX::GetMarginRight, PROPERTY_DISPLAY::PT_SIZE ) );
  453. propMgr.AddProperty( new PROPERTY<LIB_TEXTBOX, int>( _HKI( "Margin Bottom" ),
  454. &LIB_TEXTBOX::SetMarginBottom, &LIB_TEXTBOX::GetMarginBottom, PROPERTY_DISPLAY::PT_SIZE ) );
  455. propMgr.AddProperty( new PROPERTY<LIB_TEXTBOX, int>( _HKI( "Text Size" ),
  456. &LIB_TEXTBOX::SetLibTextSize, &LIB_TEXTBOX::GetLibTextSize, PROPERTY_DISPLAY::PT_SIZE ),
  457. _( "Text Properties" ) );
  458. propMgr.Mask( TYPE_HASH( LIB_TEXTBOX ), TYPE_HASH( EDA_TEXT ), _HKI( "Orientation" ) );
  459. }
  460. } _LIB_TEXTBOX_DESC;