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 <gr_text.h>
28 #include <kicad_string.h>
29 #include <pcb_edit_frame.h>
30 #include <base_units.h>
31 #include <bitmaps.h>
32 #include <class_board.h>
33 #include <class_module.h>
34 #include <view/view.h>
37 
39  BOARD_ITEM( parent, PCB_MODULE_TEXT_T ),
40  EDA_TEXT()
41 {
42  MODULE* module = static_cast<MODULE*>( m_Parent );
43 
44  m_Type = text_type;
45  m_keepUpright = true;
46 
47  // Set text thickness to a default value
48  SetTextThickness( Millimeter2iu( DEFAULT_TEXT_WIDTH ) );
49  SetLayer( F_SilkS );
50 
51  // Set position and give a default layer if a valid parent footprint exists
52  if( module && ( module->Type() == PCB_MODULE_T ) )
53  {
54  SetTextPos( module->GetPosition() );
55 
56  if( IsBackLayer( module->GetLayer() ) )
57  {
58  SetLayer( B_SilkS );
59  SetMirrored( true );
60  }
61  }
62 
63  SetDrawCoord();
64 }
65 
66 
68 {
69 }
70 
71 
72 void TEXTE_MODULE::SetTextAngle( double aAngle )
73 {
75 }
76 
77 
78 bool TEXTE_MODULE::TextHitTest( const wxPoint& aPoint, int aAccuracy ) const
79 {
80  EDA_RECT rect = GetTextBox();
81  wxPoint location = aPoint;
82 
83  rect.Inflate( aAccuracy );
84 
85  RotatePoint( &location, GetTextPos(), -GetDrawRotation() );
86 
87  return rect.Contains( location );
88 }
89 
90 
91 bool TEXTE_MODULE::TextHitTest( const EDA_RECT& aRect, bool aContains, int aAccuracy ) const
92 {
93  EDA_RECT rect = aRect;
94 
95  rect.Inflate( aAccuracy );
96 
97  if( aContains )
98  return rect.Contains( GetBoundingBox() );
99  else
100  return rect.Intersects( GetTextBox(), GetDrawRotation() );
101 }
102 
103 
104 void TEXTE_MODULE::KeepUpright( double aOldOrientation, double aNewOrientation )
105 {
106  if( !IsKeepUpright() )
107  return;
108 
109  double currentAngle = GetTextAngle() + aOldOrientation;
110  double newAngle = GetTextAngle() + aNewOrientation;
111 
112  NORMALIZE_ANGLE_POS( currentAngle );
113  NORMALIZE_ANGLE_POS( newAngle );
114 
115  bool isFlipped = currentAngle >= 1800.0;
116  bool needsFlipped = newAngle >= 1800.0;
117 
118  if( isFlipped != needsFlipped )
119  {
124 
125  SetTextAngle( GetTextAngle() + 1800.0 );
126  SetDrawCoord();
127  }
128 }
129 
130 
131 void TEXTE_MODULE::Rotate( const wxPoint& aRotCentre, double aAngle )
132 {
133  // Used in footprint editing
134  // Note also in module editor, m_Pos0 = m_Pos
135 
136  wxPoint pt = GetTextPos();
137  RotatePoint( &pt, aRotCentre, aAngle );
138  SetTextPos( pt );
139 
140  SetTextAngle( GetTextAngle() + aAngle );
141  SetLocalCoord();
142 }
143 
144 
145 void TEXTE_MODULE::Flip( const wxPoint& aCentre, bool aFlipLeftRight )
146 {
147  // flipping the footprint is relative to the X axis
148  if( aFlipLeftRight )
149  SetTextX( ::Mirror( GetTextPos().x, aCentre.x ) );
150  else
151  SetTextY( ::Mirror( GetTextPos().y, aCentre.y ) );
152 
154 
155  SetLayer( FlipLayer( GetLayer() ) );
157  SetLocalCoord();
158 
159  // adjust justified text for mirroring
161  {
162  SetHorizJustify( static_cast<EDA_TEXT_HJUSTIFY_T>( -GetHorizJustify() ) );
163  SetDrawCoord();
164  }
165 }
166 
168 {
169  if( GetParent() && GetParent()->GetLayer() == B_Cu )
170  return true;
171  return false;
172 }
173 
174 
175 void TEXTE_MODULE::Mirror( const wxPoint& aCentre, bool aMirrorAroundXAxis )
176 {
177  // Used in modedit, to transform the footprint
178  // the mirror is around the Y axis or X axis if aMirrorAroundXAxis = true
179  // the position is mirrored, but the text itself is not mirrored
180  if( aMirrorAroundXAxis )
181  SetTextY( ::Mirror( GetTextPos().y, aCentre.y ) );
182  else
183  SetTextX( ::Mirror( GetTextPos().x, aCentre.x ) );
184 
185  SetLocalCoord();
186 }
187 
188 
189 void TEXTE_MODULE::Move( const wxPoint& aMoveVector )
190 {
191  Offset( aMoveVector );
192  SetLocalCoord();
193 }
194 
195 
197 {
198  return GetText().Len();
199 }
200 
201 
203 {
204  const MODULE* module = static_cast<const MODULE*>( m_Parent );
205 
206  SetTextPos( m_Pos0 );
207 
208  if( module )
209  {
210  double angle = module->GetOrientation();
211 
212  wxPoint pt = GetTextPos();
213  RotatePoint( &pt, angle );
214  SetTextPos( pt );
215 
216  Offset( module->GetPosition() );
217  }
218 }
219 
220 
222 {
223  const MODULE* module = static_cast<const MODULE*>( m_Parent );
224 
225  if( module )
226  {
227  m_Pos0 = GetTextPos() - module->GetPosition();
228 
229  double angle = module->GetOrientation();
230 
231  RotatePoint( &m_Pos0.x, &m_Pos0.y, -angle );
232  }
233  else
234  {
235  m_Pos0 = GetTextPos();
236  }
237 }
238 
240 {
241  double angle = GetDrawRotation();
242  EDA_RECT text_area = GetTextBox();
243 
244  if( angle )
245  text_area = text_area.GetBoundingBoxRotated( GetTextPos(), angle );
246 
247  return text_area;
248 }
249 
250 
252 {
253  MODULE* module = (MODULE*) m_Parent;
254  double rotation = GetTextAngle();
255 
256  if( module )
257  rotation += module->GetOrientation();
258 
259  if( m_keepUpright )
260  {
261  // Keep angle between -90 .. 90 deg. Otherwise the text is not easy to read
262  while( rotation > 900 )
263  rotation -= 1800;
264 
265  while( rotation < -900 )
266  rotation += 1800;
267  }
268  else
269  {
270  NORMALIZE_ANGLE_POS( rotation );
271  }
272 
273  return rotation;
274 }
275 
276 
277 // see class_text_mod.h
278 void TEXTE_MODULE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
279 {
280  MODULE* module = (MODULE*) m_Parent;
281 
282  if( module == NULL ) // Happens in modedit, and for new texts
283  return;
284 
285  wxString msg, Line;
286 
287  static const wxString text_type_msg[3] =
288  {
289  _( "Ref." ), _( "Value" ), _( "Text" )
290  };
291 
292  Line = module->GetReference();
293  aList.emplace_back( _( "Footprint" ), Line, DARKCYAN );
294 
295  Line = GetShownText();
296  aList.emplace_back( _( "Text" ), Line, BROWN );
297 
298  wxASSERT( m_Type >= TEXT_is_REFERENCE && m_Type <= TEXT_is_DIVERS );
299  aList.emplace_back( _( "Type" ), text_type_msg[m_Type], DARKGREEN );
300 
301  if( !IsVisible() )
302  msg = _( "No" );
303  else
304  msg = _( "Yes" );
305 
306  aList.emplace_back( _( "Display" ), msg, DARKGREEN );
307 
308  // Display text layer
309  aList.emplace_back( _( "Layer" ), GetLayerName(), DARKGREEN );
310 
311  if( IsMirrored() )
312  msg = _( "Yes" );
313  else
314  msg = _( "No" );
315 
316  aList.emplace_back( _( "Mirror" ), msg, DARKGREEN );
317 
318  msg.Printf( wxT( "%.1f" ), GetTextAngleDegrees() );
319  aList.emplace_back( _( "Angle" ), msg, DARKGREEN );
320 
321  msg = MessageTextFromValue( aFrame->GetUserUnits(), GetTextThickness(), true );
322  aList.emplace_back( _( "Thickness" ), msg, DARKGREEN );
323 
324  msg = MessageTextFromValue( aFrame->GetUserUnits(), GetTextWidth(), true );
325  aList.emplace_back( _( "Width" ), msg, RED );
326 
327  msg = MessageTextFromValue( aFrame->GetUserUnits(), GetTextHeight(), true );
328  aList.emplace_back( _( "Height" ), msg, RED );
329 }
330 
331 
333 {
334  switch( m_Type )
335  {
336  case TEXT_is_REFERENCE:
337  return wxString::Format( _( "Reference %s" ),
338  static_cast<MODULE*>( GetParent() )->GetReference() );
339 
340  case TEXT_is_VALUE:
341  return wxString::Format( _( "Value %s of %s" ),
342  GetShownText(),
343  static_cast<MODULE*>( GetParent() )->GetReference() );
344 
345  default: // wrap this one in quotes:
346  return wxString::Format( _( "Text \"%s\" of %s on %s" ),
348  static_cast<MODULE*>( GetParent() )->GetReference(),
349  GetLayerName() );
350  }
351 }
352 
353 
355 {
356  return footprint_text_xpm;
357 }
358 
359 
361 {
362  return new TEXTE_MODULE( *this );
363 }
364 
365 
367 {
368  double angle = GetDrawRotation();
369  EDA_RECT text_area = GetTextBox();
370 
371  if( angle != 0.0 )
372  text_area = text_area.GetBoundingBoxRotated( GetTextPos(), angle );
373 
374  return BOX2I( text_area.GetPosition(), text_area.GetSize() );
375 }
376 
377 
378 void TEXTE_MODULE::ViewGetLayers( int aLayers[], int& aCount ) const
379 {
380  if( IsVisible() )
381  aLayers[0] = GetLayer();
382  else
383  aLayers[0] = LAYER_MOD_TEXT_INVISIBLE;
384 
385  aCount = 1;
386 }
387 
388 
389 unsigned int TEXTE_MODULE::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
390 {
391  const int HIDE = std::numeric_limits<unsigned int>::max();
392 
393  if( !aView )
394  return 0;
395 
396  // Hidden text gets put on the LAYER_MOD_TEXT_INVISIBLE for rendering, but
397  // should only render if its native layer is visible.
398  if( !aView->IsLayerVisible( GetLayer() ) )
399  return HIDE;
400 
401  // Handle Render tab switches
402  if( ( m_Type == TEXT_is_VALUE || GetText() == wxT( "${VALUE}" ) )
403  && !aView->IsLayerVisible( LAYER_MOD_VALUES ) )
404  return HIDE;
405 
406  if( ( m_Type == TEXT_is_REFERENCE || GetText() == wxT( "${REFERENCE}" ) )
407  && !aView->IsLayerVisible( LAYER_MOD_REFERENCES ) )
408  return HIDE;
409 
410  if( !IsParentFlipped() && !aView->IsLayerVisible( LAYER_MOD_FR ) )
411  return HIDE;
412 
413  if( IsParentFlipped() && !aView->IsLayerVisible( LAYER_MOD_BK ) )
414  return HIDE;
415 
417  return HIDE;
418 
419  if( IsBackLayer( m_Layer ) && !aView->IsLayerVisible( LAYER_MOD_TEXT_BK ) )
420  return HIDE;
421 
422  // Other layers are shown without any conditions
423  return 0;
424 }
425 
426 
427 wxString TEXTE_MODULE::GetShownText( int aDepth ) const
428 {
429  const MODULE* module = static_cast<MODULE*>( GetParent() );
430  wxASSERT( module );
431 
432  std::function<bool( wxString* )> moduleResolver =
433  [&]( wxString* token ) -> bool
434  {
435  return module && module->ResolveTextVar( token, aDepth );
436  };
437 
438  bool processTextVars = false;
439  wxString text = EDA_TEXT::GetShownText( &processTextVars );
440 
441  if( processTextVars )
442  {
443  PROJECT* project = nullptr;
444 
445  if( module && module->GetParent() )
446  project = static_cast<BOARD*>( module->GetParent() )->GetProject();
447 
448  if( aDepth < 10 )
449  text = ExpandTextVars( text, &moduleResolver, project );
450  }
451 
452  return text;
453 }
void SetMirrored(bool isMirrored)
Definition: eda_text.h:187
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:252
double GetOrientation() const
Definition: class_module.h:211
virtual unsigned int ViewGetLOD(int aLayer, KIGFX::VIEW *aView) const override
Function ViewGetLOD() Returns the level of detail (LOD) of the item.
BOX2< VECTOR2I > BOX2I
Definition: box2.h:521
EDA_ITEM * m_Parent
Linked list: Link (parent struct)
Definition: base_struct.h:174
bool IsMirrored() const
Definition: eda_text.h:188
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.
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:185
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
Function FlippedLayerNumber.
Definition: lset.cpp:485
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:217
void Move(const wxPoint &aMoveVector) override
move text in move transform, in footprint editor
void SetTextPos(const wxPoint &aPoint)
Definition: eda_text.h:246
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:173
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:257
int GetTextThickness() const
Definition: eda_text.h:158
The base class for create windows for drawing purpose.
bool Contains(const wxPoint &aPoint) const
Function Contains.
const wxString GetReference() const
Function GetReference.
Definition: class_module.h:433
int GetTextHeight() const
Definition: eda_text.h:244
void SetTextX(int aX)
Definition: eda_text.h:249
show modules on front
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:112
#define DEFAULT_TEXT_WIDTH
bool IsKeepUpright()
PCB_LAYER_ID m_Layer
class MODULE, a footprint
Definition: typeinfo.h:89
EDA_TEXT_HJUSTIFY_T GetHorizJustify() const
Definition: eda_text.h:198
#define NULL
bool m_keepUpright
if true, keep rotation angle between -90 .
const wxPoint GetPosition() const
Definition: eda_rect.h:115
const EDA_RECT GetBoundingBoxRotated(wxPoint aRotCenter, double aAngle)
Function GetBoundingBoxRotated.
wxString ShortenedShownText() const
Returns a shortened version (max 15 characters) of the shown text.
Definition: eda_text.cpp:196
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
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:175
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:241
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:205
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Definition: eda_text.h:201
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
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 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
wxString ExpandTextVars(const wxString &aSource, const std::function< bool(wxString *)> *aLocalResolver, const PROJECT *aProject)
Expand '${var-name}' templates in text.
Definition: common.cpp:382
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:247
bool IsParentFlipped() const
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.h:157
virtual void SetTextAngle(double aAngle)
Definition: eda_text.h:166
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:237
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.
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...
const wxPoint GetPosition() const override
Definition: class_module.h:206
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:126
virtual wxString GetShownText(int aDepth=0) const
Return the string actually shown after processing of the base text.
Definition: eda_text.h:133
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:250
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:416