KiCad PCB EDA Suite
class_text_mod.cpp
Go to the documentation of this file.
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) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
6  * Copyright (C) 1992-2019 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 #include <fctsys.h>
27 #include <pcb_edit_frame.h>
28 #include <base_units.h>
29 #include <bitmaps.h>
30 #include <class_board.h>
31 #include <class_module.h>
33 
35  BOARD_ITEM( parent, PCB_MODULE_TEXT_T ),
36  EDA_TEXT()
37 {
38  MODULE* module = static_cast<MODULE*>( m_Parent );
39 
40  m_Type = text_type;
41  m_keepUpright = true;
42 
43  // Set text thickness to a default value
45  SetLayer( F_SilkS );
46 
47  // Set position and give a default layer if a valid parent footprint exists
48  if( module && ( module->Type() == PCB_MODULE_T ) )
49  {
50  SetTextPos( module->GetPosition() );
51 
52  if( IsBackLayer( module->GetLayer() ) )
53  {
54  SetLayer( B_SilkS );
55  SetMirrored( true );
56  }
57  }
58 
59  SetDrawCoord();
60 }
61 
62 
64 {
65 }
66 
67 
68 void TEXTE_MODULE::SetTextAngle( double aAngle )
69 {
71 }
72 
73 
74 bool TEXTE_MODULE::TextHitTest( const wxPoint& aPoint, int aAccuracy ) const
75 {
76  EDA_RECT rect = GetTextBox();
77  wxPoint location = aPoint;
78 
79  rect.Inflate( aAccuracy );
80 
81  RotatePoint( &location, GetTextPos(), -GetDrawRotation() );
82 
83  return rect.Contains( location );
84 }
85 
86 
87 bool TEXTE_MODULE::TextHitTest( const EDA_RECT& aRect, bool aContains, int aAccuracy ) const
88 {
89  EDA_RECT rect = aRect;
90 
91  rect.Inflate( aAccuracy );
92 
93  if( aContains )
94  return rect.Contains( GetBoundingBox() );
95  else
96  return rect.Intersects( GetTextBox(), GetDrawRotation() );
97 }
98 
99 
100 void TEXTE_MODULE::KeepUpright( double aOldOrientation, double aNewOrientation )
101 {
102  if( !IsKeepUpright() )
103  return;
104 
105  double currentAngle = GetTextAngle() + aOldOrientation;
106  double newAngle = GetTextAngle() + aNewOrientation;
107 
108  NORMALIZE_ANGLE_POS( currentAngle );
109  NORMALIZE_ANGLE_POS( newAngle );
110 
111  bool isFlipped = currentAngle >= 1800.0;
112  bool needsFlipped = newAngle >= 1800.0;
113 
114  if( isFlipped != needsFlipped )
115  {
120 
121  SetTextAngle( GetTextAngle() + 1800.0 );
122  SetDrawCoord();
123  }
124 }
125 
126 
127 void TEXTE_MODULE::Rotate( const wxPoint& aRotCentre, double aAngle )
128 {
129  // Used in footprint editing
130  // Note also in module editor, m_Pos0 = m_Pos
131 
132  wxPoint pt = GetTextPos();
133  RotatePoint( &pt, aRotCentre, aAngle );
134  SetTextPos( pt );
135 
136  SetTextAngle( GetTextAngle() + aAngle );
137  SetLocalCoord();
138 }
139 
140 
141 void TEXTE_MODULE::Flip( const wxPoint& aCentre, bool aFlipLeftRight )
142 {
143  // flipping the footprint is relative to the X axis
144  if( aFlipLeftRight )
145  SetTextX( ::Mirror( GetTextPos().x, aCentre.x ) );
146  else
147  SetTextY( ::Mirror( GetTextPos().y, aCentre.y ) );
148 
150 
151  SetLayer( FlipLayer( GetLayer() ) );
153  SetLocalCoord();
154 
155  // adjust justified text for mirroring
157  {
158  SetHorizJustify( static_cast<EDA_TEXT_HJUSTIFY_T>( -GetHorizJustify() ) );
159  SetDrawCoord();
160  }
161 }
162 
164 {
165  if( GetParent() && GetParent()->GetLayer() == B_Cu )
166  return true;
167  return false;
168 }
169 
170 
171 void TEXTE_MODULE::Mirror( const wxPoint& aCentre, bool aMirrorAroundXAxis )
172 {
173  // Used in modedit, to transform the footprint
174  // the mirror is around the Y axis or X axis if aMirrorAroundXAxis = true
175  // the position is mirrored, but the text itself is not mirrored
176  if( aMirrorAroundXAxis )
177  SetTextY( ::Mirror( GetTextPos().y, aCentre.y ) );
178  else
179  SetTextX( ::Mirror( GetTextPos().x, aCentre.x ) );
180 
181  SetLocalCoord();
182 }
183 
184 
185 void TEXTE_MODULE::Move( const wxPoint& aMoveVector )
186 {
187  Offset( aMoveVector );
188  SetLocalCoord();
189 }
190 
191 
193 {
194  return GetText().Len();
195 }
196 
197 
199 {
200  const MODULE* module = static_cast<const MODULE*>( m_Parent );
201 
202  SetTextPos( m_Pos0 );
203 
204  if( module )
205  {
206  double angle = module->GetOrientation();
207 
208  wxPoint pt = GetTextPos();
209  RotatePoint( &pt, angle );
210  SetTextPos( pt );
211 
212  Offset( module->GetPosition() );
213  }
214 }
215 
216 
218 {
219  const MODULE* module = static_cast<const MODULE*>( m_Parent );
220 
221  if( module )
222  {
223  m_Pos0 = GetTextPos() - module->GetPosition();
224 
225  double angle = module->GetOrientation();
226 
227  RotatePoint( &m_Pos0.x, &m_Pos0.y, -angle );
228  }
229  else
230  {
231  m_Pos0 = GetTextPos();
232  }
233 }
234 
236 {
237  double angle = GetDrawRotation();
238  EDA_RECT text_area = GetTextBox();
239 
240  if( angle )
241  text_area = text_area.GetBoundingBoxRotated( GetTextPos(), angle );
242 
243  return text_area;
244 }
245 
246 
248 {
249  MODULE* module = (MODULE*) m_Parent;
250  double rotation = GetTextAngle();
251 
252  if( module )
253  rotation += module->GetOrientation();
254 
255  if( m_keepUpright )
256  {
257  // Keep angle between -90 .. 90 deg. Otherwise the text is not easy to read
258  while( rotation > 900 )
259  rotation -= 1800;
260 
261  while( rotation < -900 )
262  rotation += 1800;
263  }
264  else
265  {
266  NORMALIZE_ANGLE_POS( rotation );
267  }
268 
269  return rotation;
270 }
271 
272 
273 // see class_text_mod.h
274 void TEXTE_MODULE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
275 {
276  MODULE* module = (MODULE*) m_Parent;
277 
278  if( module == NULL ) // Happens in modedit, and for new texts
279  return;
280 
281  wxString msg, Line;
282 
283  static const wxString text_type_msg[3] =
284  {
285  _( "Ref." ), _( "Value" ), _( "Text" )
286  };
287 
288  Line = module->GetReference();
289  aList.emplace_back( _( "Footprint" ), Line, DARKCYAN );
290 
291  Line = GetShownText();
292  aList.emplace_back( _( "Text" ), Line, BROWN );
293 
294  wxASSERT( m_Type >= TEXT_is_REFERENCE && m_Type <= TEXT_is_DIVERS );
295  aList.emplace_back( _( "Type" ), text_type_msg[m_Type], DARKGREEN );
296 
297  if( !IsVisible() )
298  msg = _( "No" );
299  else
300  msg = _( "Yes" );
301 
302  aList.emplace_back( _( "Display" ), msg, DARKGREEN );
303 
304  // Display text layer
305  aList.emplace_back( _( "Layer" ), GetLayerName(), DARKGREEN );
306 
307  if( IsMirrored() )
308  msg = _( "Yes" );
309  else
310  msg = _( "No" );
311 
312  aList.emplace_back( _( "Mirror" ), msg, DARKGREEN );
313 
314  msg.Printf( wxT( "%.1f" ), GetTextAngleDegrees() );
315  aList.emplace_back( _( "Angle" ), msg, DARKGREEN );
316 
317  msg = MessageTextFromValue( aFrame->GetUserUnits(), GetTextThickness(), true );
318  aList.emplace_back( _( "Thickness" ), msg, DARKGREEN );
319 
320  msg = MessageTextFromValue( aFrame->GetUserUnits(), GetTextWidth(), true );
321  aList.emplace_back( _( "Width" ), msg, RED );
322 
323  msg = MessageTextFromValue( aFrame->GetUserUnits(), GetTextHeight(), true );
324  aList.emplace_back( _( "Height" ), msg, RED );
325 }
326 
327 
329 {
330  switch( m_Type )
331  {
332  case TEXT_is_REFERENCE:
333  return wxString::Format( _( "Reference '%s'" ),
334  static_cast<MODULE*>( GetParent() )->GetReference() );
335 
336  case TEXT_is_VALUE:
337  return wxString::Format( _( "Value '%s' of %s" ),
338  GetShownText(),
339  static_cast<MODULE*>( GetParent() )->GetReference() );
340 
341  default:
342  return wxString::Format( _( "Footprint Text '%s' of %s" ),
344  static_cast<MODULE*>( GetParent() )->GetReference() );
345  }
346 }
347 
348 
350 {
351  return footprint_text_xpm;
352 }
353 
354 
356 {
357  return new TEXTE_MODULE( *this );
358 }
359 
360 
362 {
363  double angle = GetDrawRotation();
364  EDA_RECT text_area = GetTextBox();
365 
366  if( angle != 0.0 )
367  text_area = text_area.GetBoundingBoxRotated( GetTextPos(), angle );
368 
369  return BOX2I( text_area.GetPosition(), text_area.GetSize() );
370 }
371 
372 
373 void TEXTE_MODULE::ViewGetLayers( int aLayers[], int& aCount ) const
374 {
375  if( IsVisible() )
376  aLayers[0] = GetLayer();
377  else
378  aLayers[0] = LAYER_MOD_TEXT_INVISIBLE;
379 
380  aCount = 1;
381 }
382 
383 
384 double TEXTE_MODULE::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
385 {
386  constexpr double HIDE = (double)std::numeric_limits<double>::max();
387 
388  if( !aView )
389  return 0.0;
390 
391  // Hidden text gets put on the LAYER_MOD_TEXT_INVISIBLE for rendering, but
392  // should only render if its native layer is visible.
393  if( !aView->IsLayerVisible( GetLayer() ) )
394  return HIDE;
395 
396  // Handle Render tab switches
397  if( ( m_Type == TEXT_is_VALUE || GetText() == wxT( "${VALUE}" ) )
398  && !aView->IsLayerVisible( LAYER_MOD_VALUES ) )
399  return HIDE;
400 
401  if( ( m_Type == TEXT_is_REFERENCE || GetText() == wxT( "${REFERENCE}" ) )
402  && !aView->IsLayerVisible( LAYER_MOD_REFERENCES ) )
403  return HIDE;
404 
405  if( !IsParentFlipped() && !aView->IsLayerVisible( LAYER_MOD_FR ) )
406  return HIDE;
407 
408  if( IsParentFlipped() && !aView->IsLayerVisible( LAYER_MOD_BK ) )
409  return HIDE;
410 
412  return HIDE;
413 
414  if( IsBackLayer( m_Layer ) && !aView->IsLayerVisible( LAYER_MOD_TEXT_BK ) )
415  return HIDE;
416 
417  // Other layers are shown without any conditions
418  return 0.0;
419 }
420 
421 
422 wxString TEXTE_MODULE::GetShownText( int aDepth ) const
423 {
424  const MODULE* module = static_cast<MODULE*>( GetParent() );
425  wxASSERT( module );
426  const BOARD* board = module->GetBoard();
427 
428  std::function<bool( wxString* )> moduleResolver =
429  [&]( wxString* token ) -> bool
430  {
431  return module && module->ResolveTextVar( token, aDepth );
432  };
433 
434  std::function<bool( wxString* )> boardTextResolver =
435  [&]( wxString* token ) -> bool
436  {
437  return board->ResolveTextVar( token, aDepth + 1 );
438  };
439 
440  bool processTextVars = false;
441  wxString text = EDA_TEXT::GetShownText( &processTextVars );
442 
443  if( processTextVars )
444  {
445  PROJECT* project = nullptr;
446 
447  if( module && module->GetParent() )
448  project = static_cast<BOARD*>( module->GetParent() )->GetProject();
449 
450  if( aDepth < 10 )
451  text = ExpandTextVars( text, &moduleResolver, project, &boardTextResolver );
452  }
453 
454  return text;
455 }
456 
457 
458 std::shared_ptr<SHAPE> TEXTE_MODULE::GetEffectiveShape( PCB_LAYER_ID aLayer ) const
459 {
460  return GetEffectiveTextShape();
461 }
462 
463 
464 static struct TEXTE_MODULE_DESC
465 {
467  {
474  }
void SetMirrored(bool isMirrored)
Definition: eda_text.h:188
EDA_UNITS
Definition: common.h:198
TEXT_TYPE
Text module type: there must be only one (and only one) for each of the reference and value texts in ...
BITMAP_DEF GetMenuImage() const override
Function GetMenuImage returns a pointer to an image to be used in menus.
void Offset(const wxPoint &aOffset)
Definition: eda_text.h:253
double GetOrientation() const
Definition: class_module.h:224
BOX2< VECTOR2I > BOX2I
Definition: box2.h:522
static PROPERTY_MANAGER & Instance()
Definition: property_mgr.h:61
EDA_ITEM * m_Parent
Linked list: Link (parent struct)
Definition: base_struct.h:174
#define TYPE_HASH(x)
Macro to generate unique identifier for a type
Definition: property.h:53
bool IsMirrored() const
Definition: eda_text.h:189
PROJECT holds project specific data.
Definition: project.h:61
PNG memory record (file in memory).
Definition: bitmap_def.h:29
void KeepUpright(double aOldOrientation, double aNewOrientation)
Called when rotating the parent footprint.
bool ResolveTextVar(wxString *token, int aDepth=0) const
Resolve any references to system tokens supported by the component.
const EDA_RECT GetBoundingBoxRotated(wxPoint aRotCenter, double aAngle) const
Function GetBoundingBoxRotated.
virtual void SetLayer(PCB_LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
Implementation of conversion functions that require both schematic and board internal units.
TEXTE_MODULE(MODULE *parent, TEXT_TYPE text_type=TEXT_is_DIVERS)
BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
virtual const BOX2I ViewBBox() const override
Function ViewBBox() returns the bounding box of the item covering all its layers.
void Rotate(const wxPoint &aOffset, double aAngle) override
Rotate text, in footprint editor (for instance in footprint rotation transform)
bool IsBackLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a back layer.
bool IsVisible() const
Definition: eda_text.h:186
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
Function FlippedLayerNumber.
Definition: lset.cpp:490
EDA_RECT GetTextBox(int aLine=-1, bool aInvertY=false) const
Useful in multiline texts to calculate the full text or a line area (for zones filling,...
Definition: eda_text.cpp:222
void Move(const wxPoint &aMoveVector) override
move text in move transform, in footprint editor
void SetTextPos(const wxPoint &aPoint)
Definition: eda_text.h:247
EDA_ITEM * Clone() const override
Function Clone creates a duplicate of this item with linked list members set to NULL.
Definition: color4d.h:61
double GetTextAngle() const
Definition: eda_text.h:174
show modules values (when texts are visibles)
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Function GetMsgPanelInfo populates aList of MSG_PANEL_ITEM objects with it's internal state for displ...
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:208
void NORMALIZE_ANGLE_POS(T &Angle)
Definition: trigo.h:276
int GetTextThickness() const
Definition: eda_text.h:159
The base class for create windows for drawing purpose.
#define REGISTER_TYPE(x)
Helper macro to map type hashes to names
Definition: property_mgr.h:244
bool Contains(const wxPoint &aPoint) const
Function Contains.
const wxString GetReference() const
Function GetReference.
Definition: class_module.h:451
int GetTextHeight() const
Definition: eda_text.h:245
void SetTextX(int aX)
Definition: eda_text.h:250
show modules on front
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:113
#define DEFAULT_TEXT_WIDTH
bool IsKeepUpright()
PCB_LAYER_ID m_Layer
class MODULE, a footprint
Definition: typeinfo.h:89
PCB_LAYER_ID
A quick note on layer IDs:
virtual std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER) const override
Function GetEffectiveShape Some pad shapes can be complex (rounded/chamfered rectangle),...
EDA_TEXT_HJUSTIFY_T GetHorizJustify() const
Definition: eda_text.h:199
#define NULL
static struct TEXTE_MODULE_DESC _TEXTE_MODULE_DESC
bool m_keepUpright
if true, keep rotation angle between -90 .
const wxPoint GetPosition() const
Definition: eda_rect.h:115
virtual BOARD * GetBoard() const
Function GetBoard returns the BOARD in which this BOARD_ITEM resides, or NULL if none.
void InheritsAfter(TYPE_ID aDerived, TYPE_ID aBase)
Declares an inheritance relationship between types.
wxString ShortenedShownText() const
Returns a shortened version (max 15 characters) of the shown text.
Definition: eda_text.cpp:201
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes.
void SetTextAngle(double aAngle) override
Definition: color4d.h:59
wxString ExpandTextVars(const wxString &aSource, const std::function< bool(wxString *)> *aLocalResolver, const PROJECT *aProject, const std::function< bool(wxString *)> *aFallbackResolver)
Expand '${var-name}' templates in text.
Definition: common.cpp:384
const BITMAP_OPAQUE footprint_text_xpm[1]
class TEXTE_MODULE, text in a footprint
Definition: typeinfo.h:93
bool IsFrontLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a front layer.
wxString MessageTextFromValue(EDA_UNITS aUnits, int aValue, bool aUseMils, EDA_DATA_TYPE aType)
Definition: base_units.cpp:124
void Flip(const wxPoint &aCentre, bool aFlipLeftRight) override
Flip entity during module flip.
int GetLength() const
void SetLocalCoord()
Set relative coordinates.
double GetTextAngleDegrees() const
Definition: eda_text.h:176
virtual wxString GetShownText(int aDepth=0) const override
Return the string actually shown after processing of the base text.
int GetTextWidth() const
Definition: eda_text.h:242
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:201
std::shared_ptr< SHAPE_COMPOUND > GetEffectiveTextShape() const
Definition: eda_text.cpp:620
BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:178
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Definition: eda_text.h:202
virtual void ViewGetLayers(int aLayers[], int &aCount) const override
Function ViewGetLayers() Returns the all the layers within the VIEW the object is painted on.
#define _(s)
Definition: 3d_actions.cpp:33
double ViewGetLOD(int aLayer, KIGFX::VIEW *aView) const override
Function ViewGetLOD() Returns the level of detail (LOD) of the item.
wxPoint m_Pos0
text coordinates relative to the footprint anchor, orient 0.
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
bool TextHitTest(const wxPoint &aPoint, int aAccuracy=0) const override
Test if aPoint is within the bounds of this object.
void AddTypeCast(TYPE_CAST_BASE *aCast)
Registers a type converter.
void SetDrawCoord()
Set absolute coordinates.
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boards.
Definition: base_struct.h:159
void Mirror(const wxPoint &aCentre, bool aMirrorAroundXAxis)
Mirror text position in footprint editing the text itself is not mirrored, and the layer not modified...
bool Intersects(const EDA_RECT &aRect) const
Function Intersects tests for a common area between rectangles.
const wxPoint & GetTextPos() const
Definition: eda_text.h:248
Provides class metadata.
Definition: property_mgr.h:58
bool IsParentFlipped() const
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.h:158
wxPoint GetPosition() const override
Definition: class_module.h:219
virtual void SetTextAngle(double aAngle)
Definition: eda_text.h:167
VIEW.
Definition: view.h:61
T NormalizeAngle360Min(T Angle)
Normalize angle to be > -360.0 and < 360.0 Angle equal to -360 or +360 are set to 0.
Definition: trigo.h:242
bool ResolveTextVar(wxString *token, int aDepth) const
BOARD_ITEM_CONTAINER * GetParent() const
TEXT_TYPE m_Type
0=ref, 1=val, etc.
double GetDrawRotation() const
wxString GetLayerName() const
Function GetLayerName returns the name of the PCB layer on which the item resides.
static constexpr int Millimeter2iu(double mm)
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
wxString GetSelectMenuText(EDA_UNITS aUnits) const override
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:127
virtual wxString GetShownText(int aDepth=0) const
Return the string actually shown after processing of the base text.
Definition: eda_text.h:134
show modules references (when texts are visibles)
EDA_UNITS GetUserUnits() const
Return the user units currently in use.
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
void SetTextY(int aY)
Definition: eda_text.h:251
const wxSize GetSize() const
Definition: eda_rect.h:103
KICAD_T Type() const
Function Type()
Definition: base_struct.h:193
bool IsLayerVisible(int aLayer) const
Function IsLayerVisible() Returns information about visibility of a particular layer.
Definition: view.h:405