KiCad PCB EDA Suite
class_worksheet_dataitem.cpp
Go to the documentation of this file.
1 
6 /*
7  * This program source code file is part of KiCad, a free EDA CAD application.
8  *
9  * Copyright (C) 1992-2013 Jean-Pierre Charras <jp.charras at wanadoo.fr>.
10  * Copyright (C) 1992-2016 KiCad Developers, see change_log.txt for contributors.
11  *
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, you may find one here:
25  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
26  * or you may search the http://www.gnu.org website for the version 2 license,
27  * or you may write to the Free Software Foundation, Inc.,
28  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
29  */
30 
31 
32 /*
33  * the class WORKSHEET_DATAITEM (and derived) defines
34  * a basic shape of a page layout ( frame references and title block )
35  * Basic shapes are line, rect and texts
36  * the WORKSHEET_DATAITEM coordinates units is the mm, and are relative to
37  * one of 4 page corners.
38  *
39  * These items cannot be drawn or plot "as this". they should be converted
40  * to a "draw list" (WS_DRAW_ITEM_BASE and derived items)
41 
42  * The list of these items is stored in a WORKSHEET_LAYOUT instance.
43  *
44  * When building the draw list:
45  * the WORKSHEET_LAYOUT is used to create a WS_DRAW_ITEM_LIST
46  * coordinates are converted to draw/plot coordinates.
47  * texts are expanded if they contain format symbols.
48  * Items with m_RepeatCount > 1 are created m_RepeatCount times
49  *
50  * the WORKSHEET_LAYOUT is created only once.
51  * the WS_DRAW_ITEM_LIST is created each time the page layout is plot/drawn
52  *
53  * the WORKSHEET_LAYOUT instance is created from a S expression which
54  * describes the page layout (can be the default page layout or a custom file).
55  */
56 
57 #include <fctsys.h>
58 #include <drawtxt.h>
59 #include <class_eda_rect.h>
60 #include <worksheet.h>
61 #include <class_title_block.h>
64 
65 using KIGFX::COLOR4D;
66 
67 
68 // Static members of class WORKSHEET_DATAITEM:
76 COLOR4D WORKSHEET_DATAITEM::m_Color = COLOR4D( RED ); // the default color to draw items
77 COLOR4D WORKSHEET_DATAITEM::m_AltColor = COLOR4D( RED ); // an alternate color to draw items
78 COLOR4D WORKSHEET_DATAITEM::m_SelectedColor = COLOR4D( BROWN ); // the color to draw selected items
79 
80 
81 // The constructor:
83 {
84  m_type = aType;
85  m_flags = 0;
86  m_RepeatCount = 1;
87  m_IncrementLabel = 1;
88  m_LineWidth = 0;
89 }
90 
91 
92 // move item to aPosition
93 // starting point is moved to aPosition
94 // the Ending point is moved to a position which keeps the item size
95 // (if both coordinates have the same corner reference)
96 // MoveToUi and MoveTo takes the graphic position (i.e relative to the left top
97 // paper corner
99 {
100  DPOINT pos_mm;
101  pos_mm.x = aPosition.x / m_WSunits2Iu;
102  pos_mm.y = aPosition.y / m_WSunits2Iu;
103 
104  MoveTo( pos_mm );
105 }
106 
107 
109 {
110  DPOINT vector = aPosition - GetStartPos();
111  DPOINT endpos = vector + GetEndPos();
112 
113  MoveStartPointTo( aPosition );
114  MoveEndPointTo( endpos );
115 }
116 
117 
118 /* move the starting point of the item to a new position
119  * aPosition = the new position of the starting point, in mm
120  */
122 {
123  DPOINT position;
124 
125  // Calculate the position of the starting point
126  // relative to the reference corner
127  // aPosition is the position relative to the right top paper corner
128  switch( m_Pos.m_Anchor )
129  {
130  case RB_CORNER:
131  position = m_RB_Corner - aPosition;
132  break;
133 
134  case RT_CORNER:
135  position.x = m_RB_Corner.x - aPosition.x;
136  position.y = aPosition.y - m_LT_Corner.y;
137  break;
138 
139  case LB_CORNER:
140  position.x = aPosition.x - m_LT_Corner.x;
141  position.y = m_RB_Corner.y - aPosition.y;
142  break;
143 
144  case LT_CORNER:
145  position = aPosition - m_LT_Corner;
146  break;
147  }
148 
149  m_Pos.m_Pos = position;
150 }
151 
152 
153 /* move the starting point of the item to a new position
154  * aPosition = the new position of the starting point in graphic units
155  */
157 {
158  DPOINT pos_mm;
159  pos_mm.x = aPosition.x / m_WSunits2Iu;
160  pos_mm.y = aPosition.y / m_WSunits2Iu;
161 
162  MoveStartPointTo( pos_mm );
163 }
164 
165 
173 {
174  DPOINT position;
175 
176  // Calculate the position of the starting point
177  // relative to the reference corner
178  // aPosition is the position relative to the right top paper corner
179  switch( m_End.m_Anchor )
180  {
181  case RB_CORNER:
182  position = m_RB_Corner - aPosition;
183  break;
184 
185  case RT_CORNER:
186  position.x = m_RB_Corner.x - aPosition.x;
187  position.y = aPosition.y - m_LT_Corner.y;
188  break;
189 
190  case LB_CORNER:
191  position.x = aPosition.x - m_LT_Corner.x;
192  position.y = m_RB_Corner.y - aPosition.y;
193  break;
194 
195  case LT_CORNER:
196  position = aPosition - m_LT_Corner;
197  break;
198  }
199 
200  // Modify m_End only for items having 2 coordinates
201  switch( GetType() )
202  {
203  case WS_SEGMENT:
204  case WS_RECT:
205  m_End.m_Pos = position;
206  break;
207 
208  default:
209  break;
210  }
211 }
212 
213 
214 /* move the ending point of the item to a new position
215  * has meaning only for items defined by 2 points
216  * (segments and rectangles)
217  * aPosition = the new position of the ending point in graphic units
218  */
220 {
221  DPOINT pos_mm;
222  pos_mm.x = aPosition.x / m_WSunits2Iu;
223  pos_mm.y = aPosition.y / m_WSunits2Iu;
224 
225  MoveEndPointTo( pos_mm );
226 }
227 
228 
230 {
231  DPOINT pos;
232  pos.x = m_Pos.m_Pos.x + ( m_IncrementVector.x * ii );
233  pos.y = m_Pos.m_Pos.y + ( m_IncrementVector.y * ii );
234 
235  switch( m_Pos.m_Anchor )
236  {
237  case RB_CORNER: // right bottom corner
238  pos = m_RB_Corner - pos;
239  break;
240 
241  case RT_CORNER: // right top corner
242  pos.x = m_RB_Corner.x - pos.x;
243  pos.y = m_LT_Corner.y + pos.y;
244  break;
245 
246  case LB_CORNER: // left bottom corner
247  pos.x = m_LT_Corner.x + pos.x;
248  pos.y = m_RB_Corner.y - pos.y;
249  break;
250 
251  case LT_CORNER: // left top corner
252  pos = m_LT_Corner + pos;
253  break;
254  }
255 
256  return pos;
257 }
258 
259 
261 {
262  DPOINT pos = GetStartPos( ii );
263  pos = pos * m_WSunits2Iu;
264  return wxPoint( KiROUND( pos.x ), KiROUND( pos.y ) );
265 }
266 
267 
269 {
270  DPOINT pos;
271  pos.x = m_End.m_Pos.x + ( m_IncrementVector.x * ii );
272  pos.y = m_End.m_Pos.y + ( m_IncrementVector.y * ii );
273 
274  switch( m_End.m_Anchor )
275  {
276  case RB_CORNER: // right bottom corner
277  pos = m_RB_Corner - pos;
278  break;
279 
280  case RT_CORNER: // right top corner
281  pos.x = m_RB_Corner.x - pos.x;
282  pos.y = m_LT_Corner.y + pos.y;
283  break;
284 
285  case LB_CORNER: // left bottom corner
286  pos.x = m_LT_Corner.x + pos.x;
287  pos.y = m_RB_Corner.y - pos.y;
288  break;
289 
290  case LT_CORNER: // left top corner
291  pos = m_LT_Corner + pos;
292  break;
293  }
294 
295  return pos;
296 }
297 
298 
300 {
301  DPOINT pos = GetEndPos( ii );
302  pos = pos * m_WSunits2Iu;
303  return wxPoint( KiROUND( pos.x ), KiROUND( pos.y ) );
304 }
305 
306 
308 {
309  DPOINT pos = GetStartPos( ii );
310 
311  for( int kk = 0; kk < 1; kk++ )
312  {
313  if( m_RB_Corner.x < pos.x || m_LT_Corner.x > pos.x )
314  return false;
315 
316  if( m_RB_Corner.y < pos.y || m_LT_Corner.y > pos.y )
317  return false;
318 
319  pos = GetEndPos( ii );
320  }
321 
322  return true;
323 }
324 
325 
326 const wxString WORKSHEET_DATAITEM::GetClassName() const
327 {
328  wxString name;
329 
330  switch( GetType() )
331  {
332  case WS_TEXT: name = wxT( "Text" ); break;
333  case WS_SEGMENT: name = wxT( "Line" ); break;
334  case WS_RECT: name = wxT( "Rect" ); break;
335  case WS_POLYPOLYGON: name = wxT( "Poly" ); break;
336  case WS_BITMAP: name = wxT( "Bitmap" ); break;
337  }
338 
339  return name;
340 }
341 
342 
343 /* return 0 if the item has no specific option for page 1
344  * 1 if the item is only on page 1
345  * -1 if the item is not on page 1
346  */
348 {
350  return -1;
351 
352  if(( m_flags & PAGE1OPTION) == PAGE1OPTION_PAGE1ONLY )
353  return 1;
354 
355  return 0;
356 }
357 
358 
359 /* Set the option for page 1
360  * aChoice = 0 if the item has no specific option for page 1
361  * > 0 if the item is only on page 1
362  * < 0 if the item is not on page 1
363  */
365 {
367 
368  if( aChoice > 0 )
370 
371  else if( aChoice < 0 )
373 
374 }
375 
376 
378  WORKSHEET_DATAITEM( WS_POLYPOLYGON )
379 {
380  m_Orient = 0.0;
381 }
382 
383 
385  int aRepeat ) const
386 {
387  DPOINT pos = m_Corners[aIdx];
388 
389  // Rotation:
390  RotatePoint( &pos.x, &pos.y, m_Orient * 10 );
391  pos += GetStartPos( aRepeat );
392  return pos;
393 }
394 
395 
397 {
398  if( m_Corners.size() == 0 )
399  {
400  m_minCoord.x = m_maxCoord.x = 0.0;
401  m_minCoord.y = m_maxCoord.y = 0.0;
402  return;
403  }
404 
405  DPOINT pos;
406  pos = m_Corners[0];
407  RotatePoint( &pos.x, &pos.y, m_Orient * 10 );
408  m_minCoord = m_maxCoord = pos;
409 
410  for( unsigned ii = 1; ii < m_Corners.size(); ii++ )
411  {
412  pos = m_Corners[ii];
413  RotatePoint( &pos.x, &pos.y, m_Orient * 10 );
414 
415  if( m_minCoord.x > pos.x )
416  m_minCoord.x = pos.x;
417 
418  if( m_minCoord.y > pos.y )
419  m_minCoord.y = pos.y;
420 
421  if( m_maxCoord.x < pos.x )
422  m_maxCoord.x = pos.x;
423 
424  if( m_maxCoord.y < pos.y )
425  m_maxCoord.y = pos.y;
426  }
427 }
428 
429 
431 {
432  DPOINT pos = GetStartPos( ii );
433  pos += m_minCoord; // left top pos of bounding box
434 
435  if( m_LT_Corner.x > pos.x || m_LT_Corner.y > pos.y )
436  return false;
437 
438  pos = GetStartPos( ii );
439  pos += m_maxCoord; // rignt bottom pos of bounding box
440 
441  if( m_RB_Corner.x < pos.x || m_RB_Corner.y < pos.y )
442  return false;
443 
444  return true;
445 }
446 
447 
449  int aRepeat ) const
450 {
451  DPOINT pos = GetCornerPosition( aIdx, aRepeat );
452  pos = pos * m_WSunits2Iu;
453  return wxPoint( int(pos.x), int(pos.y) );
454 }
455 
456 
458  WORKSHEET_DATAITEM( WS_TEXT )
459 {
460  m_TextBase = aTextBase;
461  m_IncrementLabel = 1;
464  m_Orient = 0.0;
465  m_LineWidth = 0.0; // 0.0 means use default value
466 }
467 
468 
470 {
471  aGText->SetHorizJustify( m_Hjustify ) ;
472  aGText->SetVertJustify( m_Vjustify );
473  aGText->SetTextAngle( m_Orient * 10 ); // graphic text orient unit = 0.1 degree
474 }
475 
476 
478 {
479  int last = m_TextBase.Len() -1;
480 
481  wxChar lbchar = m_TextBase[last];
483  m_FullText.RemoveLast();
484 
485  if( lbchar >= '0' && lbchar <= '9' )
486  // A number is expected:
487  m_FullText << (int)( aIncr + lbchar - '0' );
488  else
489  m_FullText << (wxChar) ( aIncr + lbchar );
490 }
491 
492 
493 // Replace the '\''n' sequence by EOL
494 // and the sequence '\''\' by only one '\' in m_FullText
495 // if m_FullText is a multiline text (i.e.contains '\n') return true
497 {
498  bool multiline = false;
499 
500  for( unsigned ii = 0; ii < m_FullText.Len(); ii++ )
501  {
502  if( m_FullText[ii] == '\n' )
503  multiline = true;
504 
505  else if( m_FullText[ii] == '\\' )
506  {
507  if( ++ii >= m_FullText.Len() )
508  break;
509 
510  if( m_FullText[ii] == '\\' )
511  {
512  // a double \\ sequence is replaced by a single \ char
513  m_FullText.Remove(ii, 1);
514  ii--;
515  }
516  else if( m_FullText[ii] == 'n' )
517  {
518  // Replace the "\n" sequence by a EOL char
519  multiline = true;
520  m_FullText[ii] = '\n';
521  m_FullText.Remove(ii-1, 1);
522  ii--;
523  }
524  }
525  }
526 
527  return multiline;
528 }
529 
530 
532 {
534 
535  if( m_ConstrainedTextSize.x == 0 )
537 
538  if( m_ConstrainedTextSize.y == 0 )
540 
542  {
543  // to know the X and Y size of the line, we should use
544  // EDA_TEXT::GetTextBox()
545  // but this function uses integers
546  // So, to avoid truncations with our unit in mm, use microns.
547  wxSize size_micron;
548  #define FSCALE 1000.0
549  int linewidth = 0;
550  size_micron.x = KiROUND( m_ConstrainedTextSize.x * FSCALE );
551  size_micron.y = KiROUND( m_ConstrainedTextSize.y * FSCALE );
553  wxPoint(0,0),
554  size_micron,
555  linewidth, BLACK,
556  IsItalic(), IsBold() ) );
557  dummy.SetMultilineAllowed( true );
558  TransfertSetupToGraphicText( &dummy );
559 
560  EDA_RECT rect = dummy.GetTextBox();
561  DSIZE size;
562  size.x = rect.GetWidth() / FSCALE;
563  size.y = rect.GetHeight() / FSCALE;
564 
565  if( m_BoundingBoxSize.x && size.x > m_BoundingBoxSize.x )
567 
568  if( m_BoundingBoxSize.y && size.y > m_BoundingBoxSize.y )
570  }
571 }
572 
573 
574 /* set the pixel scale factor of the bitmap
575  * this factor depend on the application internal unit
576  * and the PPI bitmap factor
577  * the pixel scale factor should be initialized before drawing the bitmap
578  */
580 {
581  if( m_ImageBitmap )
582  {
583  // m_WSunits2Iu is the page layout unit to application internal unit
584  // i.e. the mm to to application internal unit
585  // however the bitmap definition is always known in pixels per inches
586  double scale = m_WSunits2Iu * 25.4 / m_ImageBitmap->GetPPI();
588  }
589 }
590 
591 
592 /* return the PPI of the bitmap
593  */
595 {
596  if( m_ImageBitmap )
598 
599  return 300;
600 }
601 
602 
603 /*adjust the PPI of the bitmap
604  */
605 void WORKSHEET_DATAITEM_BITMAP::SetPPI( int aBitmapPPI )
606 {
607  if( m_ImageBitmap )
608  m_ImageBitmap->SetScale( (double) m_ImageBitmap->GetPPI() / aBitmapPPI );
609 }
void TransfertSetupToGraphicText(WS_DRAW_ITEM_TEXT *aGText)
transfert the text justification and orientation to aGText
static int KiROUND(double v)
KiROUND rounds a floating point number to an int using "round halfway cases away from zero"...
Definition: common.h:107
void SetBoundingBox()
calculate the bounding box of the set polygons
const DPOINT GetStartPos(int ii=0) const
void SetScale(double aScale)
#define TB_DEFAULT_TEXTSIZE
Class VECTOR2 defines a general 2D-vector/point.
Definition: vector2d.h:61
int GetHeight() const
#define FSCALE
bool IsInsidePage(int ii) const override
description of graphic items and texts to build a title block
void MoveEndPointTo(DPOINT aPosition)
move the ending point of the item to a new position has meaning only for items defined by 2 points (s...
virtual bool IsInsidePage(int ii) const
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:317
#define PAGE1OPTION_NOTONPAGE1
WORKSHEET_DATAITEM(WS_ItemType aType)
const wxPoint GetStartPosUi(int ii=0) const
void IncrementLabel(int aIncr)
Try to build text wihich is an increment of m_TextBase has meaning only if m_TextBase is a basic text...
void MoveStartPointTo(DPOINT aPosition)
move the starting point of the item to a new position
WORKSHEET_DATAITEM_TEXT(const wxString &aTextBase)
void MoveToUi(wxPoint aPosition)
move item to a new position
EDA_RECT GetTextBox(int aLine=-1, int aThickness=-1, bool aInvertY=false) const
Function GetTextBox useful in multiline texts to calculate the full text or a line area (for zones fi...
Definition: eda_text.cpp:102
void SetPixelScaleFactor()
set the pixel scale factor of the bitmap this factor depend on the application internal unit and the ...
void SetVertJustify(EDA_TEXT_VJUSTIFY_T aType)
Definition: eda_text.h:194
#define PAGE1OPTION_PAGE1ONLY
void MoveTo(DPOINT aPosition)
move item to a new position
const wxPoint GetEndPosUi(int ii=0) const
Definition: colors.h:60
double GetScale() const
void SetMultilineAllowed(bool aAllow)
Function SetMultiLineAllowed.
Definition: eda_text.h:187
void SetPixelScaleFactor(double aSF)
void SetPPI(int aBitmapPPI)
adjust the PPI of the bitmap
void SetTextAngle(double aAngle)
#define PAGE1OPTION
const wxPoint GetCornerPositionUi(unsigned aIdx, int aRepeat=0) const
const DPOINT GetEndPos(int ii=0) const
static double m_DefaultTextThickness
const int scale
int GetPPI() const
static LIB_PART * dummy()
Used when a LIB_PART is not found in library to draw a dummy shape This component is a 400 mils squar...
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Definition: eda_text.h:193
void SetConstrainedTextSize()
Calculates m_ConstrainedTextSize from m_TextSize to keep the X size and the full Y size of the text s...
WS_ItemType GetType() const
Class EDA_RECT handles the component boundary box.
int GetWidth() const
const char * name
This file is part of the common libary.
classes and function to generate graphics to plt or draw titles blocks and frame references ...
void MoveEndPointToUi(wxPoint aPosition)
move the ending point of the item to a new position has meaning only for items defined by 2 points (s...
Definition: colors.h:45
void SetPage1Option(int aChoice)
Set the option for page 1.
void MoveStartPointToUi(wxPoint aPosition)
move the starting point of the item to a new position
bool ReplaceAntiSlashSequence()
Replace the '\''n' sequence by EOL and the sequence '\''\' by only one '\' inside m_FullText...
const wxString GetClassName() const
const DPOINT GetCornerPosition(unsigned aIdx, int aRepeat=0) const
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39
Definition: colors.h:62