wxArt2D
cantext.cpp
Go to the documentation of this file.
1 /*! \file canvas/src/cantext.cpp
2  \author Klaas Holwerda, Erik van der Wal
3 
4  Copyright: 2000-2004 (c) Klaas Holwerda
5 
6  Licence: wxWidgets Licence
7 
8  RCS-ID: $Id: cantext.cpp,v 1.56 2009/07/24 16:35:01 titato Exp $
9 */
10 
11 #include "a2dprec.h"
12 
13 #ifdef __BORLANDC__
14 #pragma hdrstop
15 #endif
16 
17 #ifndef WX_PRECOMP
18 #include "wx/wx.h"
19 #endif
20 
21 #include <wx/clipbrd.h>
22 
23 #include "wx/canvas/cantext.h"
24 #include "wx/canvas/drawer.h"
25 #include "wx/canvas/drawing.h"
26 #include "wx/canvas/canglob.h"
27 
28 IMPLEMENT_DYNAMIC_CLASS( a2dText, a2dCanvasObject )
29 
30 
31 //! convert alignment enum to a string
32 wxString TextAlignment2String( int alignment )
33 {
34  wxString alignstring;
35  if ( alignment & wxMINX )
36  alignstring += wxT( "wxMINX|" );
37  if ( alignment & wxMAXY )
38  alignstring += wxT( "wxMAXY|" );
39  if ( alignment & wxMAXX )
40  alignstring += wxT( "wxMAXX|" );
41  if ( alignment & wxMINY )
42  alignstring += wxT( "wxMINY|" );
43  if ( alignment & wxMIDX )
44  alignstring += wxT( "wxMIDX|" );
45  if ( alignment & wxMIDY )
46  alignstring += wxT( "wxMIDY|" );
47  if ( alignment & wxBASELINE )
48  alignstring += wxT( "wxBASELINE|" );
49  if ( alignment & wxBASELINE_CONTRA )
50  alignstring += wxT( "wxBASELINE_CONTRA|" );
51  if ( alignstring.Last() == wxChar( '|' ) )
52  alignstring.RemoveLast();
53 
54  return alignstring;
55 }
56 
57 //! convert a string to alignment enum
58 int AlignmentString2TextAlignment( const wxString& alignstring )
59 {
60  int alignment = 0;
61  if ( alignstring.Find( wxT( "wxMINX" ) ) != -1 )
62  alignment |= wxMINX;
63  if ( alignstring.Find( wxT( "wxMAXX" ) ) != -1 )
64  alignment |= wxMAXX;
65  if ( alignstring.Find( wxT( "wxMINY" ) ) != -1 )
66  alignment |= wxMINY;
67  if ( alignstring.Find( wxT( "wxMAXY" ) ) != -1 )
68  alignment |= wxMAXY;
69  if ( alignstring.Find( wxT( "wxMIDX" ) ) != -1 )
70  alignment |= wxMIDX;
71  if ( alignstring.Find( wxT( "wxMIDY" ) ) != -1 )
72  alignment |= wxMIDY;
73  if ( alignstring.Find( wxT( "wxBASELINE_CONTRA" ) ) != -1 )
74  alignment |= wxBASELINE_CONTRA;
75  else if ( alignstring.Find( wxT( "wxBASELINE" ) ) != -1 )
76  alignment |= wxBASELINE;
77 
78  return alignment;
79 }
80 
81 //----------------------------------------------------------------------------
82 // a2dText
83 //----------------------------------------------------------------------------
84 
85 #define DRAGRECTWIDTH 5
86 
87 a2dPropertyIdFont* a2dText::PROPID_Font = NULL;
89 
90 INITIALIZE_PROPERTIES( a2dText, a2dCanvasObject )
91 {
92  PROPID_Font = new a2dPropertyIdFont( wxT( "Font" ),
94  *a2dNullFONT,
95  static_cast < a2dPropertyIdFont::ConstGet >( &a2dText::MX_GetFont ),
96  static_cast < a2dPropertyIdFont::ConstSet >( &a2dText::MX_SetFont ) );
97  AddPropertyId( PROPID_Font );
98 
99  PROPID_PreEditText = new a2dPropertyIdString( wxT( "PreEditText" ), a2dPropertyId::flag_temporary, wxT("") );
100  AddPropertyId( PROPID_PreEditText );
101 
102  return true;
103 }
104 
105 BEGIN_EVENT_TABLE( a2dText, a2dCanvasObject )
106  EVT_CANVASOBJECT_MOUSE_EVENT( a2dText::OnCanvasObjectMouseEvent )
107  EVT_CHAR( a2dText::OnChar )
108  EVT_CANVASHANDLE_MOUSE_EVENT( a2dText::OnHandleEvent )
109 END_EVENT_TABLE()
110 
111 a2dText::a2dText( const wxString& text )
112 {
113  m_text = text;
114  m_font = *a2dDEFAULT_CANVASFONT;
115  m_alignment = a2dDEFAULT_ALIGNMENT;
116  m_linespace = 1.0 / 10.0;
117  m_caret = -1;
118  m_selection_start_pos = m_selection_end_pos = 0;
119  m_firsteditable = 0;
120  m_textflags = a2dCANVASTEXT_DEFAULTFLAGS;
121  m_utbbox_changed = true;
122  m_wrongLoad = false;
123 }
124 
125 a2dText::a2dText( const wxString& text, double x, double y,
126  const a2dFont& font, double angle, bool up, int alignment )
127 {
128  m_text = text;
129  m_font = font;
130  m_alignment = alignment;
131  m_linespace = font.GetSize() / 10.0;
132  m_caret = -1;
134  m_firsteditable = 0;
135  m_textflags = a2dCANVASTEXT_DEFAULTFLAGS;
136  SetNextLineDirection( up );
137  Rotate( angle );
138  m_lworld.Translate( x, y );
139  m_utbbox_changed = true;
140  m_wrongLoad = false;
141 }
142 
143 a2dText::a2dText( const a2dText& other, CloneOptions options, a2dRefMap* refs )
144  : a2dCanvasObject( other, options, refs )
145 {
146  m_text = other.m_text;
147  m_linespace = other.m_linespace;
148  m_font = other.m_font;
149  m_alignment = other.m_alignment;
150  m_textflags = other.m_textflags;
151  m_wrongLoad = other.m_wrongLoad;
152  m_fontinfo = other.m_fontinfo;
153 
154  m_caret = -1;
157 
158  //in a clone pending flag and bbox state is taken over, and therefore this
159  //box needs to be taken too, else it would not be calculated when an object
160  //its bbox is already valid via this clone.
163 }
164 
166 {
167 }
168 
170 {
171  return new a2dText( *this, options, refs );
172 }
173 
174 
176 {
177  a2dVpath* segments = new a2dVpath();
178  a2dVectorPath* snappath = new a2dVectorPath( segments );
179  a2dCanvasObjectList* snappathlist = new a2dCanvasObjectList();
180  snappathlist->push_back( snappath );
181 
182  if ( snapToWhat & a2dRestrictionEngine::snapToPins ||
184  )
185  {
187  {
189  {
190  a2dCanvasObject* obj = *iter;
191  a2dPin* pin = wxDynamicCast( obj, a2dPin );
192  if ( pin && !pin->GetRelease( ) )
193  {
194  if ( snapToWhat & a2dRestrictionEngine::snapToPins ||
195  ( snapToWhat & a2dRestrictionEngine::snapToPinsUnconnected && !pin->IsConnectedTo() )
196  )
197  {
198  a2dVpathSegment* seg = new a2dVpathSegment( pin->GetAbsX(), pin->GetAbsY(), a2dPATHSEG_MOVETO );
199  segments->Add( seg );
200  }
201  }
202  }
203  }
204  }
205  if ( snapToWhat & a2dRestrictionEngine::snapToObjectPos )
206  {
208  segments->Add( seg );
209  }
210 
212  {
214  if ( untrans.GetWidth() == 0 || untrans.GetWidth() == 0 )
216 
217  double x, y, w, h;
218  x = untrans.GetMinX();
219  y = untrans.GetMinY();
220  w = untrans.GetWidth();
221  h = untrans.GetHeight();
222 
223  double tx, ty;
224  m_lworld.TransformPoint( x , y, tx, ty );
225  segments->Add( new a2dVpathSegment( tx, ty, a2dPATHSEG_MOVETO ) );
226  m_lworld.TransformPoint( x , y + h, tx, ty );
227  segments->Add( new a2dVpathSegment( tx, ty, a2dPATHSEG_MOVETO ) );
228  m_lworld.TransformPoint( x + w , y + h, tx, ty );
229  segments->Add( new a2dVpathSegment( tx, ty, a2dPATHSEG_MOVETO ) );
230  m_lworld.TransformPoint( x + w , y + h, tx, ty );
231  segments->Add( new a2dVpathSegment( tx, ty, a2dPATHSEG_MOVETO ) );
232  m_lworld.TransformPoint( x + w , y, tx, ty );
233  segments->Add( new a2dVpathSegment( tx, ty, a2dPATHSEG_MOVETO ) );
234  m_lworld.TransformPoint( x , y + h / 2, tx, ty );
235  segments->Add( new a2dVpathSegment( tx, ty, a2dPATHSEG_MOVETO ) );
236  m_lworld.TransformPoint( x + w / 2 , y + h, tx, ty );
237  segments->Add( new a2dVpathSegment( tx, ty, a2dPATHSEG_MOVETO ) );
238  m_lworld.TransformPoint( x + w , y + h / 2, tx, ty );
239  segments->Add( new a2dVpathSegment( tx, ty, a2dPATHSEG_MOVETO ) );
240  m_lworld.TransformPoint( x + w / 2 , y, tx, ty );
241  segments->Add( new a2dVpathSegment( tx, ty, a2dPATHSEG_MOVETO ) );
242  }
243 
244  return snappathlist;
245 }
246 
248 {
249  a2dAffineMatrix pworld;
250  if ( transform )
251  pworld = m_lworld;
252 
253  a2dCanvasObjectList* canpathlist = new a2dCanvasObjectList();
254 
255  //if ( GetEngineeringText() )
256  // ic.GetDrawer2D()->PushTransform( GetEngineeringTransform( ic ) );
257 
258  int up = GetNextLineDirection() ? 1 : -1;
259  size_t linestart;
260  size_t lineend = ( size_t ) 0;
261  size_t textlength = m_text.Length();
262  int line = 0;
263  wxString linetext;
264  while ( lineend < textlength )
265  {
266  linestart = lineend;
267  while ( lineend < textlength && m_text[lineend] != wxChar( '\n' ) )
268  lineend++;
269  linetext = m_text.Mid( linestart, lineend - linestart );
270 
271  a2dVpath* segments = new a2dVpath();
272 
273  GetFont().GetVpath( linetext, *segments, 0.0, line * up * ( GetLineHeight() + m_linespace ), m_alignment, true, pworld );
274 
275  a2dVectorPath* canpath = new a2dVectorPath( segments );
276  canpath->SetStroke( this->GetStroke() );
277  canpath->SetFill( this->GetFill() );
278  canpath->SetLayer( m_layer );
279  if ( m_font.GetType() == a2dFONT_STROKED )
280  {
281  canpath->SetContourWidth( m_font.GetStrokeWidth() );
282  canpath->SetPathType( a2dPATH_END_ROUND );
283  }
284  canpathlist->push_back( canpath );
285 
286  lineend++;
287  line++;
288  }
289 
290  return canpathlist;
291 }
292 
293 int a2dText::GetAsArray( wxArrayString& array )
294 {
295  int lines = 0;
296  if ( GetMultiLine() )
297  {
298  wxString line;
299  size_t i = 0;
300  while ( i < m_text.Length() )
301  {
302  if ( m_text[i] == '\n' )
303  {
304  array.Add( line );
305  line.Empty();
306  lines++;
307  }
308  else
309  line += m_text[i];
310  i++;
311  }
312  if ( !line.IsEmpty() )
313  {
314  array.Add( line );
315  lines++;
316  }
317  }
318  else
319  {
320  array.Add( m_text );
321  lines++;
322  }
323  return lines;
324 }
325 
326 int a2dText::GetLines() const
327 {
328  int lines = 1;
329  if ( GetMultiLine() )
330  {
331  size_t i = 0;
332  while ( i < m_text.Length() )
333  {
334  if ( m_text[i] == '\n' )
335  lines++;
336  i++;
337  }
338  }
339  return lines;
340 }
341 
342 wxString a2dText::GetLine( int n ) const
343 {
344  wxString string;
345 
346  size_t i = 0;
347  int newlines = 0;
348  while ( i < m_text.Length() && newlines < n )
349  {
350  if ( m_text[i] == '\n' )
351  newlines++;
352  i++;
353  }
354  if ( i < m_text.Length() )
355  {
356  while ( i < m_text.Length() && m_text[i] != '\n' )
357  {
358  string += m_text[i];
359  i++;
360  }
361  }
362  return string;
363 }
364 
365 void a2dText::SetMultiLine( bool multiline )
366 {
367  if ( multiline )
369  else
371  m_utbbox_changed = true;
372 }
373 
374 void a2dText::SetReadOnly( bool readonly )
375 {
376  if ( readonly )
378  else
380 }
381 
382 void a2dText::SetBackGround( bool background )
383 {
384  if ( background )
386  else
388 }
389 
390 void a2dText::SetDrawFrame( bool frame )
391 {
392  if ( frame )
394  else
396 }
397 
398 wxString a2dText::GetSelectedText() const
399 {
401 }
402 
403 void a2dText::InsertTextAtCarret( const wxString& text )
404 {
405  size_t textlength = m_text.Length();
406  m_text = m_text.Left( m_caret ) + text + m_text.Right( textlength - m_caret );
407  m_utbbox_changed = true;
408  m_caret += text.Length();
410  SetPending( true );
411  if ( m_flags.m_editingCopy )
412  {
413  a2dText* original = wxStaticCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dText );
415  }
416 }
417 
418 // Set caret to closest character in string
419 bool a2dText::SetCaret( a2dIterC& ic, double x, double y )
420 {
421  a2dIterCU cu( ic, m_lworld );
422 
423  a2dAffineMatrix inverse;
424  if ( GetEngineeringText() )
425  {
426  inverse = ic.GetTransform() * GetEngineeringTransform( ic );
427  inverse.Invert();
428  }
429  else
430  inverse = ic.GetInverseTransform();
431 
432  double xh, yh;
433  inverse.TransformPoint( x, y, xh, yh );
434 
435  SetCaretUntransformed( xh, yh );
436  return true;
437 }
438 
439 void a2dText::SetCaretUntransformed( double xh, double yh )
440 {
441  m_caret = 0;
442  int up = GetNextLineDirection() ? 1 : -1;
443  a2dBoundingBox linebbox;
444  size_t linestart;
445  size_t lineend = ( size_t ) 0;
446  size_t textlength = m_text.Length();
447  int line = 0;
448  wxString text;
449  while ( lineend <= textlength )
450  {
451  linestart = lineend;
452  while ( lineend < textlength && m_text[lineend] != wxChar( '\n' ) )
453  lineend++;
454  text = m_text.Mid( linestart, lineend - linestart );
455  linebbox = m_font.GetTextExtent( text, m_alignment );
456  linebbox.Translate( 0.0, line * up * ( GetLineHeight() + m_linespace ) );
457  if ( ( yh >= linebbox.GetMinY() - m_linespace / 2.0 )
458  && ( yh < linebbox.GetMaxY() + m_linespace / 2.0 )
459  || line == 0 && up == 1 && yh < linebbox.GetMaxY() + m_linespace / 2.0
460  || line == 0 && up == -1 && yh >= linebbox.GetMinY() - m_linespace / 2.0 )
461  {
462  if ( !text.IsEmpty() )
463  {
464  double oldx, newx;
465  double kerning = 0.0;
466  oldx = newx = linebbox.GetMinX();
467 
468  for( size_t i = 0; i < text.Length(); i++ )
469  {
470  newx += m_font.GetWidth( text[i] );
471  if ( i > 0 )
472  kerning = m_font.GetKerning( text[i - 1], text[i] );
473  newx += kerning / 2.0;
474 
475  if ( ( oldx + newx ) / 2.0 > xh )
476  {
477  m_caret = linestart + i;
478  if ( m_caret < m_firsteditable )
480  return;
481  }
482 
483  oldx = newx;
484  newx += kerning / 2.0;
485  }
486  }
487  m_caret = lineend;
488  break;
489  }
490  lineend++;
491  line++;
492  }
493  if ( m_caret < m_firsteditable )
495 }
496 
498 {
499  if ( up )
501  else
503  m_utbbox_changed = true;
504  SetPending( true );
505 }
506 
507 void a2dText::SetEngineeringText( bool engineering )
508 {
509  if ( engineering )
511  else
513  m_utbbox_changed = true;
514  SetPending( true );
515 }
516 
517 void a2dText::SetCaretShow( bool visible )
518 {
519  if ( visible )
521  else
523  m_utbbox_changed = true;
524  SetPending( true );
525 }
526 
527 void a2dText::SetFont( const a2dFont& font, double lineSpaceFactor )
528 {
529  m_font = font;
530  m_linespace = font.GetSize() * lineSpaceFactor;
531  m_utbbox_changed = true;
532  SetPending( true );
533 }
534 
535 #if wxART2D_USE_CVGIO
536 void a2dText::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
537 {
538  a2dCanvasObject::DoLoad( parent, parser, xmlparts );
539  m_utbbox_changed = true;
540  if ( xmlparts == a2dXmlSer_attrib )
541  {
542  m_linespace = parser.RequireAttributeValueDouble( wxT( "linespace" ) );
543  m_text = parser.RequireAttributeValue( wxT( "text" ) );
544  m_text.Replace( wxT( "\\n" ), wxT( "\n" ) );
545  m_textflags = parser.GetAttributeValueInt( wxT( "textflags" ),
549  m_fontinfo.ParseString( parser.RequireAttributeValue( wxT( "font" ) ) );
550  m_font = a2dFont::CreateFont( m_fontinfo );
551  if ( !m_font.Ok() )
552  {
554  m_font.SetSize( m_fontinfo.GetSize() );
555  m_wrongLoad = true;
556  }
557  if ( parser.GetScale() != 1 )
558  m_font.SetSize( m_font.GetSize() * parser.GetScale() );
559 
560  m_alignment = AlignmentString2TextAlignment( parser.GetAttributeValue( wxT( "alignment" ), wxT( "wxMINX|wxMINY" ) ) );
561  m_firsteditable = parser.GetAttributeValueInt( wxT( "firsteditable" ), 0 );
562  }
563  else
564  {
565  }
566 }
567 
568 void a2dText::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
569 {
570  a2dCanvasObject::DoSave( parent, out, xmlparts, towrite );
571  if ( xmlparts == a2dXmlSer_attrib )
572  {
573  out.WriteAttribute( wxT( "linespace" ), m_linespace );
574  out.WriteNewLine();
575 
576  wxString str = m_text;
577  str.Replace( wxT( "\n" ), wxT( "\\n" ) );
578  out.WriteAttributeEnt( wxT( "text" ), str );
579  out.WriteNewLine();
580  out.WriteAttribute( wxT( "textflags" ), m_textflags );
581  if ( m_wrongLoad )
582  out.WriteAttribute( wxT( "font" ), m_fontinfo.CreateString() );
583  else
584  out.WriteAttribute( wxT( "font" ), m_font.CreateString() );
585  out.WriteNewLine();
586  out.WriteAttribute( wxT( "firsteditable" ), m_firsteditable );
587 
588  wxString alignstring = TextAlignment2String( m_alignment );
589  out.WriteAttribute( wxT( "alignment" ), alignstring );
590  }
591  else
592  {
593  }
594 }
595 #endif //wxART2D_USE_CVGIO
596 
598 {
599  double pw = ic.GetWorldStrokeExtend();
600  double margin = ic.GetTransformedHitMargin();
601 
602  double xmin = m_untransbbox.GetMinX();
603  double ymin = m_untransbbox.GetMinY();
604  double xmax = m_untransbbox.GetMaxX();
605  double ymax = m_untransbbox.GetMaxY();
606 
607  hitEvent.m_how = HitTestRectangle( hitEvent.m_relx, hitEvent.m_rely, xmin, ymin, xmax, ymax, pw + margin );
608 
609  if ( hitEvent.m_how.IsHit() )
610  return hitEvent.m_how.IsHit();
611  else
612  return hitEvent.m_how.IsHit();
613 }
614 
615 
616 #define SIN100 0.9848077530
617 #define COS100 -0.1736481776
618 
620 {
621  a2dAffineMatrix mod_affine = ic.GetTransform();
622  a2dAffineMatrix eng_affine;
623  // If text is mirrored, flip it, to be readible
624  if ( eng_affine.GetDeterminant() < 0.0 )
625  {
626  eng_affine.Mirror( true, false );
627  eng_affine.Translate( 0.0, m_untransbbox.GetMinY() + m_untransbbox.GetMaxY() );
628  mod_affine *= eng_affine;
629  }
630  // If text is not readible from the bottom right, rotate it 180 degrees.
631 // double angle = wxDegToRad( 100.0 );
632 // if ( ic.GetDrawer2D()->GetYaxis() && (eng_affine( 0, 0 ) * sin( angle ) < eng_affine( 0, 1 ) * cos( angle ) )
633 // || !ic.GetDrawer2D()->GetYaxis() && (eng_affine( 0, 0 ) * sin( angle ) < -eng_affine( 0, 1 ) * cos( angle ) ) )
634  if ( ic.GetDrawer2D()->GetYaxis() && ( mod_affine( 0, 0 ) * SIN100 < mod_affine( 0, 1 ) * COS100 )
635  || !ic.GetDrawer2D()->GetYaxis() && ( mod_affine( 0, 0 ) * SIN100 < -mod_affine( 0, 1 ) * COS100 ) )
636  {
637  a2dAffineMatrix rot;
638  rot.Mirror( true, true );
640  eng_affine *= rot;
641  }
642  return eng_affine;
643 }
644 
645 #define BBOX2XYWH(bbox) (bbox).GetMinX(), (bbox).GetMinY(), (bbox).GetWidth(), (bbox).GetHeight()
646 
647 void a2dText::DoRender( a2dIterC& ic, OVERLAP WXUNUSED( clipparent ) )
648 {
649  ic.GetDrawer2D()->SetFont( m_font );
650  ic.GetDrawer2D()->SetNormalizedFont( m_flags.m_editingCopy );//GetCaretShow() );
651 
652  // For debugging
653  //ic.GetDrawer2D()->SetDrawerFill(*a2dWHITE_FILL);
654  //ic.GetDrawer2D()->DrawRoundedRectangle(BBOX2XYWH(m_untransbbox), 0);
655 
656  if( GetDrawFrame() )
657  {
658  if ( !GetBackGround() )
659  {
660  a2dFill fillcurrent = ic.GetDrawer2D()->GetDrawerFill();
663  ic.GetDrawer2D()->SetDrawerFill( fillcurrent );
664  }
665  else
667  }
668 
669  if ( GetEngineeringText() )
671 
672  //invert style is not so good so a rectangle in that case
674  {
675  if ( !GetDrawFrame() && m_text.Length() == 0 )
677 
678  int up = GetNextLineDirection() ? 1 : -1;
679  size_t linestart;
680  size_t lineend = ( size_t ) 0;
681  size_t textlength = m_text.Length();
682  int line = 0;
683  wxString linetext;
684  while ( lineend < textlength )
685  {
686  linestart = lineend;
687  while ( lineend < textlength && m_text[lineend] != wxChar( '\n' ) )
688  lineend++;
689  linetext = m_text.Mid( linestart, lineend - linestart );
690 
692  || ( m_selection_start_pos > lineend )
693  || ( m_selection_end_pos < linestart ) )
694  {
695  // No selection on this line, so draw normal textline
696  ic.GetDrawer2D()->DrawText( linetext, 0.0, line * up * ( GetLineHeight() + m_linespace ), m_alignment, !GetDrawFrame() && GetBackGround() );
697  }
698  else if ( m_selection_start_pos < linestart
699  && m_selection_end_pos > lineend )
700  {
701  // Whole line selected, so draw inverted textline
703  a2dStroke currentstroke = ic.GetDrawer2D()->GetDrawerStroke();
704  ic.GetDrawer2D()->SetDrawerFill( a2dFill( currentstroke.GetColour() ) );
705  wxColour col = currentstroke.GetColour();
706  if ( col.Red() + col.Green() + col.Blue() > 3 * 192 )
708  else
710  ic.GetDrawer2D()->DrawText( linetext, 0.0, line * up * ( GetLineHeight() + m_linespace ), m_alignment, true );
712  }
713  else
714  {
716  // Draw some parts normal and some parts inverted
717  a2dBoundingBox bbox = m_font.GetTextExtent( linetext, m_alignment );
718  double x = bbox.GetMinX();
719  double y = bbox.GetMaxY();
720  double w;
721 
722  wxString left, sel, right;
723  if ( m_selection_start_pos > linestart )
724  {
725  // Draw unselected part left of selection.
726  left = linetext.Left( m_selection_start_pos - linestart );
727  ic.GetDrawer2D()->DrawText( left, x, y + line * up * ( GetLineHeight() + m_linespace ), m_alignment, !GetDrawFrame() && GetBackGround() );
728  m_font.GetTextExtent( left, wxMINX | wxMAXY, &w );
729  x += w;
730  }
731  // Draw selected part.
732  if ( m_selection_start_pos >= linestart )
733  sel = linetext.Mid( m_selection_start_pos - linestart, m_selection_end_pos - m_selection_start_pos );
734  else
735  sel = linetext.Mid( 0, m_selection_end_pos - linestart );
737  a2dStroke currentstroke = ic.GetDrawer2D()->GetDrawerStroke();
738  ic.GetDrawer2D()->SetDrawerFill( a2dFill( currentstroke.GetColour() ) );
739  wxColour col = currentstroke.GetColour();
740  if ( col.Red() + col.Green() + col.Blue() > 3 * 192 )
742  else
744  if ( !left.IsEmpty() && ! sel.IsEmpty() )
745  x += m_font.GetKerning( left.Last(), sel[( size_t ) 0] );
746  ic.GetDrawer2D()->DrawText( sel, x, y + line * up * ( GetLineHeight() + m_linespace ), m_alignment, true );
747  m_font.GetTextExtent( sel, wxMINX | wxMAXY, &w );
748  x += w;
750  if ( m_selection_end_pos < lineend )
751  {
752  // Draw unselected part right of selection.
753  right = linetext.Right( lineend - m_selection_end_pos );
754  if ( !sel.IsEmpty() && !right.IsEmpty() )
755  x += m_font.GetKerning( sel.Last(), right[( size_t ) 0] );
756  ic.GetDrawer2D()->DrawText( right, x, y + line * up * ( GetLineHeight() + m_linespace ), m_alignment, !GetDrawFrame() && GetBackGround() );
757  }
758  }
759  lineend++;
760  line++;
761  }
762  }
763  else
764  {
766  tmp->SetRoot( m_root, false );
767  tmp->Update( updatemask_force );
768  tmp->SetFill( *a2dTRANSPARENT_FILL );
769  tmp->SetStroke( ic.GetDrawer2D()->GetDrawerStroke() );
770  tmp->Render( ic, _ON );
771  }
772 
773  //now do the carret drawing (this is faster than combining with the text drawing itself.)
774  //i think because of the stroke change happening only once like this.
776  && GetCaretShow() && ( m_caret != -1 )
778  {
780 
781  a2dStroke tmp = a2dStroke( wxColour( 0, 0, 0 ), 2 );
782  ic.GetDrawer2D()->SetDrawerStroke( tmp );
786 
787  //wxLogDebug( "pending %d caret %d (a2dText*)0x%p", m_flags.m_pending, m_caret, this );
788  //wxLogDebug(wxT("xc=%12.6lf, yc=%12.6lf"),m_XcaretinLine,m_YcaretinLine);
789 
791  }
792 
793  ic.GetDrawer2D()->SetFont( *a2dNullFONT );
794 
795  if ( m_flags.m_editingCopy )
796  {
799  //a2dStroke strokearound = a2dStroke( GetHabitat()->GetArtProvider().GetImage( a2dBitmap_EditRectangleFill )
800  // , wxColour( 0, 0, 0 ), wxColour( 255, 0, 255 ), a2dSTROKE_STIPPLE );
801  a2dStroke strokearound = a2dStroke( wxColour( 192, 192, 192 ) , DRAGRECTWIDTH, a2dSTROKE_CROSSDIAG_HATCH );
802  strokearound.SetWidth( DRAGRECTWIDTH );
803  strokearound.SetPixelStroke( true );
804  around->SetStroke( strokearound );
805 
806  //a2dFill fillaround = a2dFill( GetHabitat()->GetArtProvider().GetImage( a2dBitmap_EditRectangleFill )
807  // , wxColour( 0, 0, 0 ), wxColour( 255, 0, 255 ), a2dFILL_STIPPLE_MASK_OPAQUE_TRANSPARENT );
808  //around->SetFill( fillaround );
809  around->SetFill( *a2dTRANSPARENT_FILL );
810  around->SetRoot( m_root, false );
811  around->Update( updatemask_force );
812  around->Render( ic, _ON );
815  }
816 
817  // Restore transform;
818  if ( GetEngineeringText() )
819  ic.GetDrawer2D()->PopTransform();
820 }
821 
822 bool a2dText::DoUpdate( UpdateMode mode, const a2dBoundingBox& childbox, const a2dBoundingBox& clipbox, const a2dBoundingBox& propbox )
823 {
824  if ( !m_bbox.GetValid() )
825  {
827 
828  if( GetCaretShow() )
829  {
830  if ( m_text.Length() == 0 )
831  {
834  }
835  else
836  {
837  double wcaret = 0.0;
838  int up = GetNextLineDirection() ? 1 : -1;
839  size_t linestart;
840  size_t lineend = ( size_t ) 0;
841  size_t textlength = m_text.Length();
842  int line = 0;
843  wxString text;
844  while ( lineend <= textlength )
845  {
846  linestart = lineend;
847  while ( lineend < textlength && m_text[lineend] != wxChar( '\n' ) )
848  lineend++;
849 
850  if ( lineend >= m_caret && linestart <= m_caret )
851  {
852  a2dBoundingBox linebbox;
853  text = m_text.Mid( linestart, lineend - linestart );
854  linebbox = m_font.GetTextExtent( text, m_alignment );
855  linebbox.Translate( 0.0, line * up * ( GetLineHeight() + m_linespace ) );
856 
857  // Get width of text left of cursor
858  m_font.GetTextExtent( text.Left( m_caret - linestart ), m_alignment, &wcaret );
859  // If previous character exists ...
860  if ( m_caret - linestart > 1 && ( size_t ) ( m_caret - linestart ) <= text.Length() )
861  // ... Put caret halfway the kerning value
862  wcaret += m_font.GetKerning( text[( size_t ) ( m_caret - linestart - 2 )],
863  text[( size_t ) ( m_caret - linestart - 1 )] ) / 2;
864  m_XcaretinLine = linebbox.GetMinX() + wcaret;
865  m_YcaretinLine = linebbox.GetMinY();
866 
867  //only this line where the caret is
868  break;
869  }
870  lineend++;
871  line++;
872  }
873  }
874  }
875  else
876  {
877  if ( m_text.Length() == 0 )
878  {
881  }
882 
883  }
884  if ( m_flags.m_editingCopy )
885  {
886  m_pixelExtend = DRAGRECTWIDTH / 2;
887  }
889  return true;
890  }
891  return false;
892 }
893 
894 a2dBoundingBox a2dText::DoGetUnTransformedBbox( a2dBboxFlags WXUNUSED( flags ) ) const
895 {
896  if( !m_utbbox_changed && GetCaretShow() )
897  {
898  return m_untransbbox;
899  }
900 
901  a2dBoundingBox bbox;
902 
903  // When no text, use a bounding box with the size of an '|'
904  if ( m_text.Length() == 0 )
905  {
906  bbox = m_font.GetTextExtent( wxT( "|" ), m_alignment );
907  }
908  else
909  {
910  double wcaret = 0.0;
911  int up = GetNextLineDirection() ? 1 : -1;
912  a2dBoundingBox linebbox;
913  size_t linestart;
914  size_t lineend = ( size_t ) 0;
915  size_t textlength = m_text.Length();
916  int line = 0;
917  wxString text;
918  while ( lineend <= textlength )
919  {
920  linestart = lineend;
921  while ( lineend < textlength && m_text[lineend] != wxChar( '\n' ) )
922  lineend++;
923  text = m_text.Mid( linestart, lineend - linestart );
924 
925  linebbox = m_font.GetTextExtent( text, m_alignment );
926  linebbox.Translate( 0.0, line * up * ( GetLineHeight() + m_linespace ) );
927  bbox.Expand( linebbox );
928  lineend++;
929  line++;
930  }
931  }
932  m_untransbbox = bbox;
933  m_utbbox_changed = false;
934  return bbox;
935 }
936 
937 bool a2dText::DoStartEdit( wxUint16 editmode, wxEditStyle editstyle )
938 {
939  if ( m_flags.m_editable )
940  {
941  SetCaretShow( true );
943  a2dText* original = wxStaticCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dText );
944  //save the text as is now, undo of the whole string is easy
946  if ( editstyle & wxEDITSTYLE_COPY )
947  original->SetVisible( false );
948  if ( editmode == 1 )
949  {
950  m_flags.m_visiblechilds = true;
952 
953  //calculate bbox's else mouse events may take place when first idle event is not yet
954  //processed to do this calculation.
956  //stil set it pending to do the redraw ( in place )
957  SetPending( true );
958  return true;
959  }
960  else
961  {
962  if ( m_font.GetType() != a2dFONT_WXDC )
963  {
964  // since this is not a dc-font, allow stretching etc.
965  PROPID_IncludeChildren->SetPropertyToObject( this, false );
966  PROPID_Allowrotation->SetPropertyToObject( this, true );
967  PROPID_Allowskew->SetPropertyToObject( this, true );
968 
969  return a2dCanvasObject::DoStartEdit( editmode, editstyle );
970  }
971  else
972  {
973  m_flags.m_visiblechilds = true;
975 
976  //add properties and handles
978  if ( untrans.GetWidth() == 0 || untrans.GetWidth() == 0 )
980 
981  double x, y, w, h;
982  x = untrans.GetMinX();
983  y = untrans.GetMinY();
984  w = untrans.GetWidth();
985  h = untrans.GetHeight();
986 
987  int up = GetNextLineDirection() ? 1 : -1;
988  a2dHandle* handle = NULL;
989  Append( handle = new a2dHandle( this, 0, up * GetTextHeight(), wxT( "__text_fontsize__" ) ) );
990  handle->SetLayer( m_layer );
991 
992  // show rotation
993  a2dSLine* rotline;
994  if ( m_alignment & wxMAXX )
995  rotline = new a2dSLine( 0, 0, -w / 4, 0 );
996  else
997  rotline = new a2dSLine( 0, 0, w / 4, 0 );
998  rotline->SetStroke( *wxRED, 0 );
999  rotline->SetPreRenderAsChild( false );
1000  rotline->SetSpecificFlags( true, a2dCanvasOFlags::BIN2 );
1001  rotline->SetHitFlags( a2dCANOBJ_EVENT_NON );
1002  rotline->SetLayer( m_layer );
1003  Append( rotline );
1004 
1005  if ( m_alignment & wxMAXX )
1006  Append( handle = new a2dHandle( this, -w / 4, 0, wxT( "__text_rotate__" ) ) );
1007  else
1008  Append( handle = new a2dHandle( this, w / 4, 0, wxT( "__text_rotate__" ) ) );
1009  handle->SetLayer( m_layer );
1010 
1011  m_childobjects->SetSpecificFlags( false, a2dCanvasOFlags::PRERENDERASCHILD, wxT( "a2dHandle" ) );
1012  m_childobjects->SetSpecificFlags( true, a2dCanvasOFlags::BIN2, wxT( "a2dHandle" ) );
1013 
1014  //calculate bbox's else mouse events may take place when first idle event is not yet
1015  //processed to do this calculation.
1017  //still set it pending to do the redraw ( in place )
1018  SetPending( true );
1019  return true;
1020  }
1021  }
1022  }
1023  return false;
1024 }
1025 
1027 {
1028  m_caret = -1;
1030  a2dText* original = wxStaticCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dText );
1031 
1032  original->m_caret = 0;
1033  original->SetCaretShow( false );
1034  original->SetVisible( true );
1035  //original->m_text = PROPID_PreEditText->GetPropertyValue( this );
1036  //m_root->GetCommandProcessor()->Submit( new a2dCommand_ChangeText( original, m_text, m_caret, m_font, m_linespace, m_textflags ) );
1037 }
1038 
1039 void a2dText::OnChar( wxKeyEvent& event )
1040 {
1041  if ( m_flags.m_editingCopy )
1042  {
1043  a2dText* original = wxStaticCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dText );
1044 
1045  bool extend_selection;
1046  bool extend_start;
1047  bool changed = true;
1048  size_t initial_pos = m_caret;
1049 
1050  extend_selection = event.ShiftDown();
1051  extend_start = FALSE;
1052 
1053  if ( extend_selection )
1054  {
1056  {
1059  }
1060  extend_start = ( m_caret == m_selection_start_pos );
1061  }
1062 
1063  size_t textlength = m_text.Length();
1064  switch ( event.GetKeyCode() )
1065  {
1066  case WXK_HOME:
1067  if( event.ControlDown() )
1068  // move to start of text
1070  else
1071  {
1072  // move to start of line
1073  while ( m_caret > m_firsteditable && m_text[ m_caret - 1 ] != wxChar( '\n' ) )
1074  m_caret--;
1075  }
1076  break;
1077  case WXK_END:
1078  if( event.ControlDown() )
1079  // move to end of text
1080  m_caret = textlength;
1081  else
1082  // move to end of line
1083  while ( m_caret < textlength && m_text[ m_caret] != wxChar( '\n' ) )
1084  m_caret++;
1085  break;
1086  // case GDK_KP_Page_Up:
1087  // case GDK_Page_Up: move_cursor_page_ver (text, -1); break;
1088  // case GDK_KP_Page_Down:
1089  // case GDK_Page_Down: move_cursor_page_ver (text, +1); break;
1090  /* CUA has Ctrl-Up/Ctrl-Down as paragraph up down */
1091  case WXK_UP:
1092  // move up one line
1093  {
1094  double up = GetNextLineDirection() ? 1.0 : -1.0;
1096  }
1097  break;
1098  case WXK_DOWN:
1099  // move down one line
1100  {
1101  double up = GetNextLineDirection() ? 1.0 : -1.0;
1103  }
1104  break;
1105  case WXK_LEFT:
1106  if( event.ControlDown() )
1107  {
1108  // move cursor to start of (previous) word
1109  while ( m_caret > m_firsteditable && ( m_text[ m_caret - 1] == wxChar( '\n' )
1110  || m_text[ m_caret - 1] == wxChar( ' ' ) ) )
1111  m_caret--;
1112  while ( m_caret > m_firsteditable && m_text[ m_caret - 1 ] != wxChar( '\n' )
1113  && m_text[ m_caret - 1 ] != wxChar( ' ' ) )
1114  m_caret--;
1115  }
1116  else
1117  {
1118  // move cursor left
1119  if ( m_caret > m_firsteditable )
1120  m_caret--;
1121  }
1122  break;
1123  case WXK_RIGHT:
1124  if( event.ControlDown() )
1125  {
1126  // move cursor to start of next word
1127  while ( m_caret < textlength && m_text[m_caret] != wxChar( '\n' )
1128  && m_text[m_caret] != wxChar( ' ' ) )
1129  m_caret++;
1130  while ( m_caret < textlength && ( m_text[m_caret] == wxChar( '\n' ) )
1131  || ( m_text[m_caret] == wxChar( ' ' ) ) )
1132  m_caret++;
1133  }
1134  else
1135  // move cursor right
1136  if ( m_caret < textlength )
1137  m_caret++;
1138  break;
1139  case WXK_BACK:
1141  {
1142  // delete selection
1143  extend_selection = FALSE;
1144  m_text = m_text.Left( m_selection_start_pos ) + m_text.Right( textlength - m_selection_end_pos );
1145  m_utbbox_changed = true;
1147  }
1148  else if( event.ControlDown() )
1149  {
1150  // delete to start of (previous) word
1151  size_t curpos = m_caret;
1152  while ( m_caret > m_firsteditable && ( m_text[m_caret - 1] == wxChar( '\n' )
1153  || m_text[m_caret - 1] == wxChar( ' ' ) ) )
1154  m_caret--;
1155  while ( m_caret > m_firsteditable && m_text[ m_caret - 1 ] != wxChar( '\n' )
1156  && m_text[ m_caret - 1 ] != wxChar( ' ' ) )
1157  m_caret--;
1158  m_text = m_text.Left( m_caret ) + m_text.Right( textlength - curpos );
1159  m_utbbox_changed = true;
1160  }
1161  else if ( m_caret > m_firsteditable )
1162  {
1163  // delete previous character
1164  m_text = m_text.Left( m_caret - 1 ) + m_text.Right( textlength - m_caret );
1165  m_utbbox_changed = true;
1166  m_caret--;
1167  }
1168  break;
1169  case WXK_CLEAR:
1170  {
1171  // delete line
1172  while ( m_caret < textlength && ( m_text[m_caret] != wxChar( '\n' ) ) )
1173  m_caret++;
1174  size_t endline = m_caret;
1175  if ( m_caret < textlength && ( m_text[m_caret] == wxChar( '\n' ) ) )
1176  endline++;
1177  while ( m_caret > 0 && m_text[m_caret - 1 ] != wxChar( '\n' ) )
1178  m_caret--;
1179  m_text = m_text.Left( m_caret ) + m_text.Right( textlength - endline );
1180  m_utbbox_changed = true;
1181  }
1182  case WXK_INSERT:
1183  if( event.ShiftDown() )
1184  {
1185  // insert text from clipboard
1186  extend_selection = false;
1187  changed = false;
1188  if ( wxTheClipboard->Open() )
1189  {
1190  if ( wxTheClipboard->IsSupported( wxDF_TEXT ) )
1191  {
1192  wxTextDataObject data;
1193  wxTheClipboard->GetData( data );
1194  m_text = m_text.Left( m_caret ) + data.GetText() + m_text.Right( textlength - m_caret );
1195  m_utbbox_changed = true;
1196  m_caret += data.GetText().Length();
1197  changed = true;
1198  }
1199  wxTheClipboard->Close();
1200  }
1201  }
1202  else if( event.ControlDown() )
1203  {
1204  // copy selection to clipboard
1206  {
1207  // Write some text to the clipboard
1208  if ( wxTheClipboard->Open() )
1209  {
1210  wxTheClipboard->SetData( new wxTextDataObject( m_text.Mid( m_selection_start_pos, m_selection_end_pos - m_selection_start_pos ) ) );
1211  wxTheClipboard->Close();
1212  }
1213  }
1214  changed = false;
1215  }
1216  else
1217  {
1218  changed = false;
1219  /* gtk_toggle_insert(text) -- IMPLEMENT */
1220  }
1221  break;
1222  case WXK_DELETE:
1224  {
1225  extend_selection = FALSE;
1226  if( event.ShiftDown() )
1227  {
1228  // copy selection to clipboard
1229  if ( wxTheClipboard->Open() )
1230  {
1231  wxTheClipboard->SetData( new wxTextDataObject( m_text.Mid( m_selection_start_pos, m_selection_end_pos - m_selection_start_pos ) ) );
1232  wxTheClipboard->Close();
1233  }
1234  }
1235  // delete selection
1236  m_text = m_text.Left( m_selection_start_pos ) + m_text.Right( textlength - m_selection_end_pos );
1237  m_utbbox_changed = true;
1239  }
1240  else if( event.ControlDown() )
1241  {
1242  // delete to start of next word
1243  size_t curpos = m_caret;
1244  while ( m_caret < textlength && m_text[m_caret] != wxChar( '\n' )
1245  && m_text[m_caret] != wxChar( ' ' ) )
1246  m_caret++;
1247  while ( m_caret < textlength && m_text[m_caret] != wxChar( '\n' )
1248  && m_text[m_caret] == wxChar( ' ' ) )
1249  m_caret++;
1250  m_text = m_text.Left( curpos ) + m_text.Right( textlength - m_caret );
1251  m_utbbox_changed = true;
1252  m_caret = curpos;
1253  }
1254  else if ( m_caret < textlength )
1255  {
1256  // delete next character
1257  m_text = m_text.Left( m_caret ) + m_text.Right( textlength - ( m_caret + 1 ) );
1258  m_utbbox_changed = true;
1259  }
1260  break;
1261  case WXK_TAB:
1262  //special meaning in wxArt2D: change edit mode
1263  {
1264  changed = false;
1265  wxUint16* editmode = PROPID_Editmode->GetPropertyValuePtr( this );
1266  if ( editmode )
1267  {
1268  ( *editmode )++;
1269  if ( ( *editmode ) > 1 ) ( *editmode ) = 0;
1270  ReStartEdit( ( *editmode ) );
1271  }
1272  }
1273  break;
1274  case WXK_RETURN:
1275  // start a new line
1276  if ( GetMultiLine() )
1277  {
1278  m_text = m_text.Left( m_caret ) + wxT( "\n" ) + m_text.Right( textlength - m_caret );
1279  m_utbbox_changed = true;
1280  m_caret++;
1281  }
1282  else
1283  {
1284  changed = false;
1285  wxBell();
1286  }
1287  break;
1288  case WXK_ESCAPE:
1289  changed = false;
1290  break;
1291  default:
1292  if( event.ControlDown() )
1293  {
1294  switch( event.GetKeyCode() )
1295  {
1296  case 'A' - '@':
1297  // move to start of line
1298  while ( m_caret > m_firsteditable && m_text[m_caret - 1 ] != wxChar( '\n' ) )
1299  m_caret--;
1300  break;
1301  case 'B' - '@':
1302  // move cursor left
1303  if ( m_caret > m_firsteditable )
1304  m_caret--;
1305  break;
1306  case 'C' - '@':
1307  // copy selection to clipboard
1309  {
1310  // Write some text to the clipboard
1311  if ( wxTheClipboard->Open() )
1312  {
1313  wxTheClipboard->SetData( new wxTextDataObject( m_text.Mid( m_selection_start_pos, m_selection_end_pos - m_selection_start_pos ) ) );
1314  wxTheClipboard->Close();
1315  }
1316  }
1317  changed = false;
1318  break;
1319  case 'D' - '@':
1321  {
1322  // delete selection
1323  extend_selection = FALSE;
1324  m_text = m_text.Left( m_selection_start_pos ) + m_text.Right( textlength - m_selection_end_pos );
1325  m_utbbox_changed = true;
1327  }
1328  else if ( m_caret < textlength )
1329  {
1330  // delete next character
1331  m_text = m_text.Left( m_caret ) + m_text.Right( textlength - ( m_caret + 1 ) );
1332  m_utbbox_changed = true;
1333  }
1334  break;
1335  case 'E' - '@':
1336  // move to end of line
1337  while ( m_caret < textlength && m_text[m_caret] != wxChar( '\n' ) )
1338  m_caret++;
1339  break;
1340  case 'F' - '@':
1341  // move cursor right
1342  if ( m_caret < textlength )
1343  m_caret++;
1344  break;
1345  case 'H' - '@':
1347  {
1348  // delete selection
1349  extend_selection = FALSE;
1350  m_text = m_text.Left( m_selection_start_pos ) + m_text.Right( textlength - m_selection_end_pos );
1351  m_utbbox_changed = true;
1353  }
1354  else if ( m_caret > m_firsteditable )
1355  {
1356  // delete previous character
1357  m_text = m_text.Left( m_caret - 1 ) + m_text.Right( textlength - m_caret );
1358  m_utbbox_changed = true;
1359  m_caret--;
1360  }
1361  break;
1362  case 'K' - '@':
1364  {
1365  // delete selection
1366  extend_selection = FALSE;
1367  m_text = m_text.Left( m_selection_start_pos ) + m_text.Right( textlength - m_selection_end_pos );
1368  m_utbbox_changed = true;
1370  }
1371  else
1372  {
1373  // delete to end of line
1374  size_t curpos = m_caret;
1375  while ( m_caret < textlength && ( m_text[m_caret] != wxChar( '\n' ) ) )
1376  m_caret++;
1377  m_text = m_text.Left( curpos ) + m_text.Right( textlength - m_caret );
1378  m_utbbox_changed = true;
1379  m_caret = curpos;
1380  }
1381  break;
1382  case 'N' - '@':
1383  // move to start of next line
1384  while ( m_caret < textlength && ( m_text[m_caret] != wxChar( '\n' ) ) )
1385  m_caret++;
1386  if ( m_caret < textlength && m_text[m_caret] == wxChar( '\n' ) )
1387  m_caret++;
1388  break;
1389  case 'P' - '@':
1390  // move to start of previous line
1391  while ( m_caret > m_firsteditable && m_text[m_caret - 1 ] != wxChar( '\n' ) )
1392  m_caret--;
1393  if ( m_caret > m_firsteditable && m_text[ m_caret - 1 ] == wxChar( '\n' ) )
1394  m_caret--;
1395  while ( m_caret > m_firsteditable && m_text[ m_caret - 1 ] != wxChar( '\n' ) )
1396  m_caret--;
1397  break;
1398  case 'U' - '@':
1400  {
1401  // delete selection
1402  extend_selection = FALSE;
1403  m_text = m_text.Left( m_selection_start_pos ) + m_text.Right( textlength - m_selection_end_pos );
1404  m_utbbox_changed = true;
1406  }
1407  else
1408  {
1409  // delete line
1410  while ( m_caret < textlength && ( m_text[m_caret] != wxChar( '\n' ) ) )
1411  m_caret++;
1412  size_t endline = m_caret;
1413  if ( m_caret < textlength && ( m_text[m_caret] == wxChar( '\n' ) ) )
1414  endline++;
1415  while ( m_caret > 0 && m_text[ m_caret - 1 ] != wxChar( '\n' ) )
1416  m_caret--;
1417  m_text = m_text.Left( m_caret ) + m_text.Right( textlength - endline );
1418  m_utbbox_changed = true;
1419  }
1420  break;
1421  case 'V' - '@':
1422  // insert text from clipboard
1423  extend_selection = false;
1424  changed = false;
1425  if ( wxTheClipboard->Open() )
1426  {
1427  if ( wxTheClipboard->IsSupported( wxDF_TEXT ) )
1428  {
1429  wxTextDataObject data;
1430  wxTheClipboard->GetData( data );
1431  m_text = m_text.Left( m_caret ) + data.GetText() + m_text.Right( textlength - m_caret );
1432  m_utbbox_changed = true;
1433  m_caret += data.GetText().Length();
1434  changed = true;
1435  }
1436  wxTheClipboard->Close();
1437  }
1438  break;
1439  case 'W' - '@':
1441  {
1442  // delete selection
1443  extend_selection = FALSE;
1444  m_text = m_text.Left( m_selection_start_pos ) + m_text.Right( textlength - m_selection_end_pos );
1445  m_utbbox_changed = true;
1447  }
1448  else
1449  {
1450  // delete to start of (previous) word
1451  size_t curpos = m_caret;
1452  while ( m_caret > m_firsteditable && ( m_text[m_caret - 1] == wxChar( '\n' )
1453  || m_text[m_caret - 1] == wxChar( ' ' ) ) )
1454  m_caret--;
1455  while ( m_caret > m_firsteditable && m_text[ m_caret - 1 ] != wxChar( '\n' )
1456  && m_text[ m_caret - 1 ] != wxChar( ' ' ) )
1457  m_caret--;
1458  m_text = m_text.Left( m_caret ) + m_text.Right( textlength - curpos );
1459  m_utbbox_changed = true;
1460  }
1461  break;
1462  case 'X' - '@':
1463  // cut selection to clipboard
1464  extend_selection = FALSE;
1466  {
1467  if ( wxTheClipboard->Open() )
1468  {
1469  wxTheClipboard->SetData( new wxTextDataObject( m_text.Mid( m_selection_start_pos, m_selection_end_pos - m_selection_start_pos ) ) );
1470  wxTheClipboard->Close();
1471  }
1472  m_text = m_text.Left( m_selection_start_pos ) + m_text.Right( textlength - m_selection_end_pos );
1473  m_utbbox_changed = true;
1475  }
1476  else
1477  changed = false;
1478  break;
1479  case WXK_NUMPAD1:
1480  SetAlignment( wxMINX | wxMINY );
1481  break;
1482  case WXK_NUMPAD2:
1483  SetAlignment( wxMINY );
1484  break;
1485  case WXK_NUMPAD3:
1486  SetAlignment( wxMAXX | wxMINY );
1487  break;
1488  case WXK_NUMPAD4:
1489  SetAlignment( wxMINX );
1490  break;
1491  case WXK_NUMPAD5:
1492  SetAlignment( 0 );
1493  break;
1494  case WXK_NUMPAD6:
1495  SetAlignment( wxMAXX );
1496  break;
1497  case WXK_NUMPAD7:
1498  SetAlignment( wxMINX | wxMAXY );
1499  break;
1500  case WXK_NUMPAD8:
1501  SetAlignment( wxMAXY );
1502  break;
1503  case WXK_NUMPAD9:
1504  SetAlignment( wxMAXX | wxMAXY );
1505  break;
1506  case WXK_NUMPAD0:
1507  SetAlignment( wxBASELINE );
1508  break;
1509  default:
1510  changed = false;
1511  }
1512  break;
1513  }
1514  if( event.AltDown() )
1515  {
1516  switch( event.GetKeyCode() )
1517  {
1518  case 'b': case 'B':
1519  // move cursor to start of (previous) word
1520  while ( m_caret > m_firsteditable && ( m_text[m_caret - 1] == wxChar( '\n' )
1521  || m_text[m_caret - 1] == wxChar( ' ' ) ) )
1522  m_caret--;
1523  while ( m_caret > m_firsteditable && m_text[ m_caret - 1 ] != wxChar( '\n' )
1524  && m_text[ m_caret - 1 ] != wxChar( ' ' ) )
1525  m_caret--;
1526  break;
1527  case 'd': case 'D':
1529  {
1530  extend_selection = FALSE;
1531  if( event.ShiftDown() )
1532  {
1533  // copy selection to clipboard
1534  if ( wxTheClipboard->Open() )
1535  {
1536  wxTheClipboard->SetData( new wxTextDataObject( m_text.Mid( m_selection_start_pos, m_selection_end_pos - m_selection_start_pos ) ) );
1537  wxTheClipboard->Close();
1538  }
1539  }
1540  // delete selection
1541  m_text = m_text.Left( m_selection_start_pos ) + m_text.Right( textlength - m_selection_end_pos );
1542  m_utbbox_changed = true;
1544  }
1545  else
1546  {
1547  // delete to start of next word
1548  size_t curpos = m_caret;
1549  while ( m_caret < textlength && m_text[m_caret] != wxChar( '\n' )
1550  && m_text[m_caret] != wxChar( ' ' ) )
1551  m_caret++;
1552  while ( m_caret < textlength && ( m_text[m_caret] == wxChar( '\n' ) )
1553  || ( m_text[m_caret] == wxChar( ' ' ) ) )
1554  m_caret++;
1555  m_text = m_text.Left( curpos ) + m_text.Right( textlength - m_caret );
1556  m_utbbox_changed = true;
1557  m_caret = curpos;
1558  }
1559  break;
1560  case 'f': case 'F':
1561  // move cursor to start of next word
1562  while ( m_caret < textlength && m_text[m_caret] != wxChar( '\n' )
1563  && m_text[m_caret] != wxChar( ' ' ) )
1564  m_caret++;
1565  while ( m_caret < textlength && ( m_text[m_caret] == wxChar( '\n' ) )
1566  || ( m_text[m_caret] == wxChar( ' ' ) ) )
1567  m_caret++;
1568  break;
1569  default:
1570  changed = false;
1571  }
1572  break;
1573  }
1574  else
1575  {
1576  extend_selection = false;
1578  {
1579  m_text = m_text.Left( m_selection_start_pos ) + m_text.Right( textlength - m_selection_end_pos );
1580  m_utbbox_changed = true;
1582  textlength = m_text.Length();
1583  }
1584  wxChar h = event.GetKeyCode();
1585  m_text = m_text.Left( m_caret ) + h + m_text.Right( textlength - m_caret );
1586  m_utbbox_changed = true;
1587  m_caret++;
1588  }
1589  } // switch ( event.GetKeyCode() );
1590 
1591  if ( changed && ( m_caret != initial_pos ) )
1592  {
1593  if ( extend_selection )
1594  {
1595  if ( m_selection_start_pos == initial_pos )
1596  {
1598  m_selection_end_pos = initial_pos;
1599  }
1601  {
1604  }
1605  else
1607  }
1608  else
1610  }
1611  if ( changed )
1612  {
1613  SetPending( true );
1615  //original->SetText( m_text );
1616  //original->SetAlignment( m_alignment );
1617  }
1618  }
1619 // else
1620 // event.Skip();
1621 }
1622 
1623 void a2dText::OnCanvasObjectMouseEvent( a2dCanvasObjectMouseEvent& event )
1624 {
1625  a2dIterC* ic = event.GetIterC();
1626 
1627  static bool busydrag = false;
1628 
1629  if ( m_flags.m_editingCopy )
1630  {
1631  a2dText* original = wxStaticCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dText );
1632  wxMouseEvent mouseevent = event.GetMouseEvent();
1633 
1634  //to world group coordinates to do hit test in world group coordinates
1635  double xw, yw;
1636  xw = event.GetX();
1637  yw = event.GetY();
1638 
1639  if ( mouseevent.LeftDown() )
1640  {
1642  matrix.Invert();
1643  double dragwidthworld = matrix.TransformDistance( DRAGRECTWIDTH );
1644  if ( GetBbox().PointOnBox( xw, yw, dragwidthworld ) )
1645  {
1646  busydrag = true;
1647  event.Skip();
1648  }
1649  else if ( !mouseevent.ControlDown() )
1650  {
1651  if ( GetBbox().PointInBox( xw, yw, dragwidthworld ) )
1652  {
1653  SetCaret( *ic, xw, yw );
1655  //just to remember caret change, also at start
1658 
1659  SetPending( true );
1660  }
1661  return;
1662  }
1663  }
1664  if ( event.GetMouseEvent().Moving() && !busydrag )
1665  {
1667  matrix.Invert();
1668  double dragwidthworld = matrix.TransformDistance( DRAGRECTWIDTH );
1669  if ( GetBbox().PointOnBox( xw, yw, dragwidthworld ) )
1670  {
1671  ic->GetDrawingPart()->PushCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_Move ) );
1672  //event.Skip();
1673  return;
1674  }
1675  }
1676  if ( mouseevent.Dragging() )
1677  {
1678  if ( busydrag )
1679  event.Skip();
1680  else if ( mouseevent.LeftIsDown() && !mouseevent.ControlDown() )
1681  {
1682  a2dCanvasObject* hitobject;
1683  a2dHitEvent hitevent = a2dHitEvent( xw, yw, false );
1684  hitobject = IsHitWorld( *ic, hitevent );
1685  if ( hitobject )
1686  {
1687  size_t initial_pos = m_caret;
1688  SetCaret( *ic, xw, yw );
1689  if ( m_selection_start_pos == initial_pos )
1690  {
1692  m_selection_end_pos = initial_pos;
1693  }
1695  {
1698  }
1699  else
1701  SetPending( true );
1702  }
1703  return;
1704  }
1705  }
1706  if ( mouseevent.LeftUp() && busydrag )
1707  {
1708  busydrag = false;
1709  event.Skip();
1710  }
1711 // a2dCanvasObject::OnCanvasObjectMouseEvent( event );
1712  }
1713 // else
1714  event.Skip();
1715 }
1716 
1717 void a2dText::OnHandleEvent( a2dHandleMouseEvent& event )
1718 {
1719  a2dIterC* ic = event.GetIterC();
1720 
1721  if ( m_flags.m_editingCopy )
1722  {
1723  a2dRestrictionEngine* restrict = GetHabitat()->GetRestrictionEngine();
1724  a2dHandle* draghandle = event.GetCanvasHandle();
1725 
1726  wxUint16 editmode = PROPID_Editmode->GetPropertyValue( this );
1727  a2dAffineMatrix origworld = m_lworld;
1728 
1729  if ( editmode == 0 && m_font.GetType() == a2dFONT_WXDC )
1730  {
1731  double xw, yw;
1732  xw = event.GetX();
1733  yw = event.GetY();
1734 
1735  a2dAffineMatrix atWorld = ic->GetTransform();
1736  a2dAffineMatrix inverse = ic->GetInverseTransform();
1737 
1738  double xwi;
1739  double ywi;
1740  inverse.TransformPoint( xw, yw, xwi, ywi );
1741 
1742  a2dText* original = wxStaticCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dText );
1743 
1745 
1746  double xmin, ymin, xmax, ymax, w, h;
1747  xmin = untrans.GetMinX();
1748  ymin = untrans.GetMinY();
1749  xmax = untrans.GetMaxX();
1750  ymax = untrans.GetMaxY();
1751  w = untrans.GetWidth();
1752  h = untrans.GetHeight();
1753 
1754  if ( event.GetMouseEvent().LeftDown() )
1755  {
1756  }
1757  else if ( event.GetMouseEvent().LeftUp() )
1758  {
1759  if ( draghandle->GetName() == wxT( "__text_fontsize__" ) )
1760  {
1761  original->SetTextHeight( GetTextHeight() );
1763  }
1764  }
1765  else if ( event.GetMouseEvent().Dragging() )
1766  {
1767  if ( draghandle->GetName() == wxT( "__text_fontsize__" ) )
1768  {
1769  SetTextHeight( fabs( ywi ) );
1770  SetNextLineDirection( ywi < 0 );
1771  draghandle->SetPosXY( 0, ywi );
1772  }
1773  else if ( draghandle->GetName() == wxT( "__text_rotate__" ) )
1774  {
1775  if( restrict )
1776  restrict->RestrictPoint( xw, yw, a2dRestrictionEngine::snapToPointAngle );
1777 
1778  double xr, yr;
1779  m_lworld.TransformPoint( 0, 0, xr, yr );
1780 
1781  //modify object
1782  double dx, dy;
1783 
1784  dx = xw - xr;
1785  dy = yw - yr;
1786  double angn;
1787  if ( !dx && !dy )
1788  angn = 0;
1789  else
1790  {
1791  if ( m_alignment & wxMAXX )
1792  angn = wxRadToDeg( atan2( -dy, -dx ) );
1793  else
1794  angn = wxRadToDeg( atan2( dy, dx ) );
1795  }
1796  m_lworld = m_lworld.Rotate( angn - m_lworld.GetRotation(), xr, yr );
1797  }
1798  else
1799  event.Skip();
1800  SetPending( true );
1801  }
1802  }
1803  else
1804  {
1805  event.Skip();
1806  }
1807  }
1808  else
1809  {
1810  event.Skip();
1811  }
1812 }
1813 
1814 bool a2dText::GeneratePins( a2dPinClass* toConnectTo, a2dConnectTask task, double WXUNUSED( x ), double WXUNUSED( y ), double WXUNUSED(margin) )
1815 {
1816  a2dPinClass* toCreate;
1817  if ( GetGeneratePins() && ( toCreate = toConnectTo->GetPinClassForTask( task, this ) ) )
1818  {
1819  double xmin = m_untransbbox.GetMinX();
1820  double ymin = m_untransbbox.GetMinY();
1821  double xmax = m_untransbbox.GetMaxX();
1822  double ymax = m_untransbbox.GetMaxY();
1823 
1824  double midx = ( m_untransbbox.GetMaxX() + m_untransbbox.GetMinX() ) / 2;
1825  double midy = ( m_untransbbox.GetMaxY() + m_untransbbox.GetMinY() ) / 2;
1826 
1827  m_flags.m_visiblechilds = true;
1828  a2dPin* newPin = NULL;
1829  if ( !HasPinNamed( wxT( "pinc*" ), true ) )
1830  {
1831  newPin = AddPin( wxT( "pinc" ), midx, midy, a2dPin::temporaryObjectPin, toCreate );
1832  newPin->SetInternal( true );
1833  }
1834  if ( !HasPinNamed( wxT( "pin1" ), true ) )
1835  AddPin( wxT( "pin1" ), xmin, ymin, a2dPin::temporaryObjectPin, toCreate );
1836  if ( !HasPinNamed( wxT( "pin2" ), true ) )
1837  AddPin( wxT( "pin2" ), midx, ymin, a2dPin::temporaryObjectPin, toCreate );
1838  if ( !HasPinNamed( wxT( "pin3" ), true ) )
1839  AddPin( wxT( "pin3" ), xmax, ymin, a2dPin::temporaryObjectPin, toCreate );
1840  if ( !HasPinNamed( wxT( "pin4" ), true ) )
1841  AddPin( wxT( "pin4" ), xmax, midy, a2dPin::temporaryObjectPin, toCreate );
1842  if ( !HasPinNamed( wxT( "pin5" ), true ) )
1843  AddPin( wxT( "pin5" ), xmax, ymax, a2dPin::temporaryObjectPin, toCreate );
1844  if ( !HasPinNamed( wxT( "pin6" ), true ) )
1845  AddPin( wxT( "pin6" ), midx, ymax, a2dPin::temporaryObjectPin, toCreate );
1846  if ( !HasPinNamed( wxT( "pin7" ), true ) )
1847  AddPin( wxT( "pin7" ), xmin, ymax, a2dPin::temporaryObjectPin, toCreate );
1848  if ( !HasPinNamed( wxT( "pin8" ), true ) )
1849  AddPin( wxT( "pin8" ), xmin, midy, a2dPin::temporaryObjectPin, toCreate );
1850 
1851  wxASSERT( HasPins( true ) );
1853 
1854  return true;
1855  }
1856  return false;
1857 }
1858 
1860 {
1861  if ( !HasPins() )
1862  return false;
1863 
1865 
1866  const double xmin = m_untransbbox.GetMinX();
1867  const double ymin = m_untransbbox.GetMinY();
1868  const double xmax = m_untransbbox.GetMaxX();
1869  const double ymax = m_untransbbox.GetMaxY();
1870  const double midx = ( m_untransbbox.GetMaxX() + m_untransbbox.GetMinX() ) / 2;
1871  const double midy = ( m_untransbbox.GetMaxY() + m_untransbbox.GetMinY() ) / 2;
1872 
1873  a2dPin* pin = NULL;
1874  if ( ( pin = HasPinNamed( wxT( "pinc*" ), false ) ) != NULL )
1875  pin->SetPosXY( midx, midy );
1876  if ( ( pin = HasPinNamed( wxT( "pin1" ), false ) ) != NULL )
1877  pin->SetPosXY( xmin, ymin );
1878  if ( ( pin = HasPinNamed( wxT( "pin2" ), false ) ) != NULL )
1879  pin->SetPosXY( midx, ymin );
1880  if ( ( pin = HasPinNamed( wxT( "pin3" ), false ) ) != NULL )
1881  pin->SetPosXY( xmax, ymin );
1882  if ( ( pin = HasPinNamed( wxT( "pin4" ), false ) ) != NULL )
1883  pin->SetPosXY( xmax, midy );
1884  if ( ( pin = HasPinNamed( wxT( "pin5" ), false ) ) != NULL )
1885  pin->SetPosXY( xmax, ymax );
1886  if ( ( pin = HasPinNamed( wxT( "pin6" ), false ) ) != NULL )
1887  pin->SetPosXY( midx, ymax );
1888  if ( ( pin = HasPinNamed( wxT( "pin7" ), false ) ) != NULL )
1889  pin->SetPosXY( xmin, ymax );
1890  if ( ( pin = HasPinNamed( wxT( "pin8" ), false ) ) != NULL )
1891  pin->SetPosXY( xmin, midy );
1892 
1893  return true;
1894 }
1895 
1896 //----------------------------------------------------------------------------
1897 // a2dTextGDS
1898 //----------------------------------------------------------------------------
1899 
1900 IMPLEMENT_DYNAMIC_CLASS( a2dTextGDS, a2dText )
1901 
1902 double a2dTextGDS::m_fontScaleFactor = 1.0;
1903 
1904 a2dTextGDS::a2dTextGDS( a2dFontType fontType, const wxString& text, double height, short int presentation )
1905  : a2dText( text, 0.0, 0.0, *a2dNullFONT )
1906 {
1907  m_alignment = 0;
1908  m_presentationflags.total = presentation;
1909  SetHorizontal( m_presentationflags.bits.m_horizontal );
1910  SetVertical( m_presentationflags.bits.m_vertical );
1911 
1912  m_fontType = fontType;
1913  if ( m_fontType == a2dFONT_STROKED )
1914  {
1915  //we choose a precentage instead of another font.
1916  int weight = 2;
1917  switch( m_presentationflags.bits.m_font )
1918  {
1919  default:
1920  case 0 : weight = 2;
1921  break;
1922  case 1 : weight = 4;
1923  break;
1924  case 2 : weight = 8;
1925  break;
1926  case 3 : weight = 12;
1927  break;
1928  }
1929  a2dText::SetFont( a2dFont( wxT( "nen.chr" ), height, m_monoSpaced, weight ) );
1930  }
1931  if ( m_fontType == a2dFONT_WXDC )
1932  {
1933  int FontFamily = wxMODERN; //default does not rotate if to small
1934  switch( m_presentationflags.bits.m_font )
1935  {
1936  case 0 : FontFamily = wxDEFAULT; break;
1937  case 1 : FontFamily = wxROMAN; break;
1938  case 2 : FontFamily = wxSWISS; break;
1939  case 3 : FontFamily = wxDECORATIVE; break;
1940  default: FontFamily = wxMODERN; break;
1941  }
1942  a2dText::SetFont( a2dFont( height, FontFamily, wxNORMAL ) );
1943  }
1944 
1945  // a2dFont( wxT("nen.chr"), 0, true );
1946  //: a2dText( text, 0.0,0.0, a2dFont( 1.0, wxSWISS ) )
1947  //: a2dText( text, 0.0,0.0, a2dFont( 1.0, wxMODERN ) )
1948  //: a2dText( text, 0.0,0.0, a2dFont( wxT("LiberationSans-Regular.ttf" ) ) )
1949 
1950  m_texttype = 0;
1951  m_pathtype = TEXT_PATH_END_SQAURE;
1952  m_width = 0;
1953  m_monoSpaced = true;
1954  SetBackGround( false );
1955 }
1956 
1958  : a2dText( other, options, refs )
1959 {
1960  m_presentationflags.total = other.m_presentationflags.total;
1961  m_texttype = other.m_texttype;
1962  m_pathtype = other.m_pathtype;
1963  m_monoSpaced = other.m_monoSpaced;
1964  m_width = other.m_width;
1965 }
1966 
1968 {
1969  return new a2dTextGDS( *this, options, refs );
1970 };
1971 
1972 void a2dTextGDS::SetFontGDS( char nw_font )
1973 {
1974  double h = GetTextHeight();
1975  if ( m_fontType == a2dFONT_STROKED )
1976  {
1977  m_font = a2dFont( wxT( "nen.chr" ), 0, m_monoSpaced );
1978  m_presentationflags.bits.m_font = nw_font;
1979  //we choose a precentage instead of another font.
1980  switch( nw_font )
1981  {
1982  default:
1983  case 0 : m_font.SetWeight( 2 );
1984  break;
1985  case 1 : m_font.SetWeight( 4 );
1986  break;
1987  case 2 : m_font.SetWeight( 8 );
1988  break;
1989  case 3 : m_font.SetWeight( 12 );
1990  break;
1991  }
1992  SetTextHeight( h );
1993  }
1994  if ( m_fontType == a2dFONT_WXDC )
1995  {
1996  int FontFamily = wxMODERN; //default does not rotate if to small
1997  switch( nw_font )
1998  {
1999  case 0 : FontFamily = wxDEFAULT; break;
2000  case 1 : FontFamily = wxROMAN; break;
2001  case 2 : FontFamily = wxSWISS; break;
2002  case 3 : FontFamily = wxDECORATIVE; break;
2003  default: FontFamily = wxMODERN; break;
2004  }
2005  a2dText::SetFont( a2dFont( 1, FontFamily, wxNORMAL, wxNORMAL ) );
2006  SetTextHeight( h );
2007  }
2008 }
2009 
2010 void a2dTextGDS::SetVertical( char nw_vertical )
2011 {
2012  m_presentationflags.bits.m_vertical = nw_vertical;
2013  switch ( m_presentationflags.bits.m_horizontal )
2014  {
2015  case 0 :
2016  default:
2017  m_alignment = wxMINY | m_alignment;
2018  break;
2019  case 1 :
2020  m_alignment = wxMIDY | m_alignment;
2021  break;
2022  case 2 :
2023  m_alignment = wxMAXY | m_alignment;
2024  break;
2025  }
2026 }
2027 
2028 
2029 void a2dTextGDS::SetHorizontal( char nw_horizontal )
2030 {
2031  m_presentationflags.bits.m_horizontal = nw_horizontal;
2032  switch ( m_presentationflags.bits.m_horizontal )
2033  {
2034  case 0 :
2035  default:
2036  m_alignment = wxMINX | m_alignment;
2037  break;
2038  case 1 :
2039  m_alignment = wxMIDX | m_alignment;
2040  break;
2041  case 2 :
2042  m_alignment = wxMAXX | m_alignment;
2043  break;
2044  }
2045 }
2046 
2047 
2048 short int a2dTextGDS::GetFontGDS()
2049 {
2050  return ( short int ) m_presentationflags.bits.m_font;
2051 }
2052 
2053 
2054 short int a2dTextGDS::GetVertical()
2055 {
2056  return ( short int ) m_presentationflags.bits.m_vertical;
2057 }
2058 
2059 
2060 short int a2dTextGDS::GetHorizontal()
2061 {
2062  return ( short int ) m_presentationflags.bits.m_horizontal;
2063 }
2064 
2065 void a2dTextGDS::SetPresentationFlags( short int the_total )
2066 {
2067  m_presentationflags.total = the_total;
2068  SetHorizontal( m_presentationflags.bits.m_horizontal );
2069  SetVertical( m_presentationflags.bits.m_vertical );
2070  SetFontGDS( m_presentationflags.bits.m_font );
2071 }
2072 
2073 short int a2dTextGDS::GetPresentationFlags( )
2074 {
2075  return m_presentationflags.total;
2076 }
2077 
2078 #if wxART2D_USE_CVGIO
2079 void a2dTextGDS::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
2080 {
2081  a2dText::DoLoad( parent, parser, xmlparts );
2082  m_utbbox_changed = true;
2083  if ( xmlparts == a2dXmlSer_attrib )
2084  {
2085  m_texttype = parser.GetAttributeValueInt( wxT( "texttype" ), 0 );
2086  m_pathtype = ( TEXT_PATHTYPE ) parser.GetAttributeValueInt( wxT( "pathtype" ), 0 );
2087  m_presentationflags.total = 0;
2088  SetVertical( parser.GetAttributeValueInt( wxT( "vertical" ), 0 ) );
2089  SetHorizontal( parser.GetAttributeValueInt( wxT( "horizontal" ), 0 ) );
2090  SetFontGDS( parser.GetAttributeValueInt( wxT( "fontgds" ), 0 ) );
2091  }
2092  else
2093  {
2094  }
2095 }
2096 
2097 void a2dTextGDS::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
2098 {
2099  a2dText::DoSave( parent, out, xmlparts, towrite );
2100  if ( xmlparts == a2dXmlSer_attrib )
2101  {
2102  out.WriteAttribute( wxT( "texttype" ), m_texttype );
2103  out.WriteAttribute( wxT( "pathtype" ), m_pathtype );
2104  if ( GetPresentationFlags() )
2105  {
2106  // write only when a_presentation isn't default
2107  if ( GetHorizontal() != DEFAULT_PRESENTATION_HORIZONTAL )
2108  {
2109  out.WriteAttribute( wxT( "horizontal" ), GetHorizontal() );
2110  }
2111  // write only when a_presentation isn't default
2112  if ( GetVertical() != DEFAULT_PRESENTATION_VERTICAL )
2113  {
2114  out.WriteAttribute( wxT( "vertical" ), GetVertical() );
2115  }
2116  // write only when a_presentation isn't default
2117  if ( GetFontGDS() != DEFAULT_PRESENTATION_FONT )
2118  {
2119  out.WriteAttribute( wxT( "fontgds" ), GetFontGDS() );
2120  }
2121  }
2122  out.WriteNewLine();
2123  }
2124  else
2125  {
2126  }
2127 }
2128 #endif //wxART2D_USE_CVGIO
2129 
2130 
2131 
2132 //===========================================================================
2133 // a2dTextChanges
2134 //===========================================================================
2135 
2136 a2dFontInfoList a2dTextChanges::m_fontlist;
2137 a2dFontInfoList a2dTextChanges::m_alreadyusedfonts;
2138 
2139 a2dTextChanges::a2dTextChanges()
2140  :
2141  m_Font(),
2142  m_bType( false ),
2143  m_bFont( false ),
2144  m_bStyle( false ),
2145  m_bSize( false ),
2146  m_textflags( a2dText::a2dCANVASTEXT_DEFAULTFLAGS ),
2147  m_btextflags( false ),
2148  m_alignment( a2dDEFAULT_ALIGNMENT ),
2149  m_balignment( false )
2150 {
2151  m_alreadyusedfonts.Clear();
2152 }
2153 
2154 a2dTextChanges::a2dTextChanges(const a2dFont& font, unsigned int textflags, int alignment )
2155 {
2156  Set( font, textflags, alignment );
2157 }
2158 
2159 // Creates the list of available fonts once
2160 // Optional: filter fonts, if a filled filterlist and filtertype is passed
2161 void a2dTextChanges::InitialiseFontList(const wxArrayString &filterlist, const wxString filtertype)
2162 {
2163  if(m_fontlist.GetCount()==0)
2164  {
2165  m_fontlist.DeleteContents( true );
2166  a2dFont::GetInfoList( m_fontlist );
2167 
2168  // optional filtering
2169  if( filterlist.GetCount() > 0 && filtertype != wxT( "" ) )
2170  {
2171  a2dFontInfoList reduced_list;
2172  for ( size_t i = 0; i < m_fontlist.GetCount(); i++ )
2173  {
2174  wxString fontname = m_fontlist.Item( i )->GetData()->GetName();
2175  wxString fonttype = m_fontlist.Item( i )->GetData()->GetType();
2176 
2177  for(int u = 0; u < filterlist.GetCount(); u++)
2178  {
2179  if ( ( fonttype == filtertype ) && fontname == filterlist[u] )
2180  {
2181  reduced_list.Append( new a2dFontInfo( *m_fontlist.Item( i )->GetData() ) );
2182  }
2183  }
2184  }
2185  m_fontlist.Clear();
2186  m_fontlist.insert( m_fontlist.end(), reduced_list.begin(), reduced_list.end() ); //copy reduced (filtered) list on member fontlist
2187  }
2188  }
2189 }
2190 
2191 // Initialises with <font>.
2192 void a2dTextChanges::Set(const a2dFont& font, unsigned int textflags, int alignment, bool wrongloadflag )
2193 {
2194  m_Font = font;
2195  m_bType = true;
2196  m_bFont = true;
2197  m_bName = true;
2198  m_bStyle = true;
2199  m_bSize = true;
2200  m_textflags = textflags;
2201  m_btextflags = true;
2202  m_alignment = alignment;
2203  m_balignment = true;
2204 
2205  if( wrongloadflag == false )
2206  {
2207  m_commonstyle.Clear();
2208 
2209  //start the list of common styles
2210  for ( size_t i = 0; i < m_fontlist.GetCount(); i++ )
2211  {
2212  wxString fontname = m_fontlist.Item( i )->GetData()->GetName();
2213  wxString fonttype = m_fontlist.Item( i )->GetData()->GetType();
2214  if ( ( fonttype == m_Font.GetFontInfo().GetType() || m_Font.GetFontInfo().GetType() == _( "* (All types)" ) )
2215  && fontname == m_Font.GetFontInfo().GetName() )
2216  {
2217  wxString fontstyle = m_fontlist.Item( i )->GetData()->GetStyle();
2218  size_t j;
2219  for ( j = 0; j < m_commonstyle.GetCount(); j++ )
2220  {
2221  if ( m_commonstyle.Item( j ) == fontstyle )
2222  break;
2223  }
2224  if ( j == m_commonstyle.GetCount() )
2225  m_commonstyle.Add( fontstyle );
2226  }
2227  }
2228  }
2229 }
2230 
2231 // Compares with <font> and sets to invalid if unequal.
2232 void a2dTextChanges::Mix(const a2dFont& font, unsigned int textflags, int alignment )
2233 {
2234  if( m_bType && (font.GetFontInfo().GetType() != m_Font.GetFontInfo().GetType()) ) m_bType = false;
2235  if( m_bFont && (font.GetFontInfo().GetName() != m_Font.GetFontInfo().GetName()) )
2236  {
2237  m_bName = false;
2238 
2239  // -----------generate a list of common styles, when font is not the same-------------
2240  wxArrayString fonts1;
2241 
2242  //for speed optimization, search in list of already used fonts first
2243  for ( size_t i = 0; i < m_alreadyusedfonts.GetCount(); i++ )
2244  {
2245  wxString fontname = m_alreadyusedfonts.Item( i )->GetData()->GetName();
2246  wxString fonttype = m_alreadyusedfonts.Item( i )->GetData()->GetType();
2247  if ( ( fonttype == font.GetFontInfo().GetType() || font.GetFontInfo().GetType() == _( "* (All types)" ) )
2248  && fontname == font.GetFontInfo().GetName() )
2249  {
2250  wxString fontstyle = m_alreadyusedfonts.Item( i )->GetData()->GetStyle();
2251  size_t j;
2252  for ( j = 0; j < fonts1.GetCount(); j++ )
2253  {
2254  if ( fonts1.Item( j ) == fontstyle )
2255  break;
2256  }
2257  if ( j == fonts1.GetCount() )
2258  fonts1.Add( fontstyle );
2259  }
2260  }
2261 
2262  if( fonts1.GetCount() == 0 )
2263  {
2264  for ( size_t i = 0; i < m_fontlist.GetCount(); i++ )
2265  {
2266  wxString fontname = m_fontlist.Item( i )->GetData()->GetName();
2267  wxString fonttype = m_fontlist.Item( i )->GetData()->GetType();
2268  if ( ( fonttype == font.GetFontInfo().GetType() || font.GetFontInfo().GetType() == _( "* (All types)" ) )
2269  && fontname == font.GetFontInfo().GetName() )
2270  {
2271  wxString fontstyle = m_fontlist.Item( i )->GetData()->GetStyle();
2272  size_t j;
2273  for ( j = 0; j < fonts1.GetCount(); j++ )
2274  {
2275  if ( fonts1.Item( j ) == fontstyle )
2276  break;
2277  }
2278  if ( j == fonts1.GetCount() )
2279  {
2280  fonts1.Add( fontstyle );
2281  m_alreadyusedfonts.push_back( m_fontlist.Item( i )->GetData() );
2282  }
2283  }
2284  }
2285  }
2286  wxArrayString commonstyle_temp;
2287  for( int i = 0; i < fonts1.GetCount(); i++ )
2288  {
2289  for( int u = 0; u < m_commonstyle.GetCount(); u++ )
2290  {
2291  if( fonts1[i] == m_commonstyle[u])
2292  {
2293  commonstyle_temp.Add(fonts1[i]);
2294  break;
2295  }
2296  }
2297  }
2298  m_commonstyle=commonstyle_temp;
2299  }
2300  // -----------------------------------------------------------------------------------
2301 
2302  if( m_bStyle && (font.GetFontInfo().GetStyle() != m_Font.GetFontInfo().GetStyle()) ) m_bStyle = false;
2303  if( m_bSize && (font.GetFontInfo().GetSize() != m_Font.GetFontInfo().GetSize()) ) m_bSize = false;
2304 
2305  if( m_balignment && (m_alignment != alignment) ) m_balignment = false;
2306  if( m_btextflags && (m_textflags != textflags) ) m_btextflags = false;
2307 }
2308 
2309 a2dFont a2dTextChanges::GetFont(const a2dFont& font, wxArrayString valid_styles, wxArrayString valid_extras ) const
2310 {
2311  a2dFont mixed=font;
2312  a2dFontInfo fontinfo=mixed.GetFontInfo();
2313 
2314  wxString valid_style="", valid_extra;
2315  if( m_bType && (mixed.GetFontInfo().GetType() != m_Font.GetFontInfo().GetType()) )
2316  {
2317  fontinfo.SetType( m_Font.GetFontInfo().GetType() );
2318  }
2319  if( m_bName && (mixed.GetFontInfo().GetName() != m_Font.GetFontInfo().GetName()) )
2320  {
2321  fontinfo.SetName( m_Font.GetFontInfo().GetName() );
2322 
2323  // When style is invalid (e.g. the new font doesn't support the given style), choose "Regular" or the first one in the list
2324  if( !m_bStyle )
2325  {
2326  for( int i = 0; i < valid_styles.GetCount() ; i++ )
2327  {
2328  if( ( valid_style == "" && valid_styles[i] == wxT( "Regular" ) ) || fontinfo.GetStyle() == valid_styles[i] )
2329  {
2330  valid_style = valid_styles[i];
2331  valid_extra = valid_extras[i];
2332  }
2333  }
2334  fontinfo.SetStyle( valid_style );
2335  fontinfo.SetExtra( valid_extra );
2336  }
2337  }
2338  if( m_bStyle && ( (mixed.GetFontInfo().GetStyle() != m_Font.GetFontInfo().GetStyle()) || (mixed.GetFontInfo().GetExtra() != m_Font.GetFontInfo().GetExtra()) ) )
2339  {
2340  fontinfo.SetStyle( m_Font.GetFontInfo().GetStyle() );
2341  if( m_bName )
2342  fontinfo.SetExtra( m_Font.GetFontInfo().GetExtra() );
2343  else
2344  {
2345  fontinfo.SetExtra( "" );
2346 
2347  //for speed optimization, search in list of already used fonts first
2348  for ( size_t i = 0; i < m_alreadyusedfonts.GetCount(); i++ )
2349  {
2350  wxString fonttype = m_alreadyusedfonts.Item( i )->GetData()->GetType();
2351  wxString fontname = m_alreadyusedfonts.Item( i )->GetData()->GetName();
2352  wxString fontstyle = m_alreadyusedfonts.Item( i )->GetData()->GetStyle();
2353 
2354  if ( ( fonttype == fontinfo.GetType() || fontinfo.GetType() == _( "* (All types)" ) )
2355  && fontname == fontinfo.GetName() && fontstyle == m_Font.GetFontInfo().GetStyle() )
2356  {
2357  fontinfo.SetExtra( m_alreadyusedfonts.Item( i )->GetData()->GetExtra() ); //used when font-name was not changed -> only style was mixed
2358  break;
2359  }
2360  }
2361 
2362  if( fontinfo.GetExtra() == "" )
2363  {
2364  for ( size_t i = 0; i < m_fontlist.GetCount(); i++ )
2365  {
2366  wxString fonttype = m_fontlist.Item( i )->GetData()->GetType();
2367  wxString fontname = m_fontlist.Item( i )->GetData()->GetName();
2368  wxString fontstyle = m_fontlist.Item( i )->GetData()->GetStyle();
2369 
2370  if ( ( fonttype == fontinfo.GetType() || fontinfo.GetType() == _( "* (All types)" ) )
2371  && fontname == fontinfo.GetName() && fontstyle == m_Font.GetFontInfo().GetStyle() )
2372  {
2373  fontinfo.SetExtra( m_fontlist.Item( i )->GetData()->GetExtra() ); //used when font-name was not changed -> only style was mixed
2374  m_alreadyusedfonts.push_back( m_fontlist.Item( i )->GetData() );
2375  break;
2376  }
2377  }
2378  }
2379  }
2380  }
2381  if( m_bSize && (mixed.GetFontInfo().GetSize() != m_Font.GetFontInfo().GetSize()) )
2382  {
2383  fontinfo.SetSize( m_Font.GetFontInfo().GetSize() );
2384  }
2385 
2386  mixed=a2dFont::CreateFont( fontinfo );
2387  return mixed;
2388 }
2389 
2390 int a2dTextChanges::GetAlignment( int Alignment ) const
2391 {
2392  if(m_balignment) return m_alignment;
2393  return Alignment;
2394 }
2395 
2396 unsigned int a2dTextChanges::GetTextFlags( unsigned int textflags ) const
2397 {
2398  if(m_btextflags) return m_textflags;
2399  return textflags;
2400 }
2401 
2402 
2403 wxUint32 SetTextChanges( a2dTextChanges& returned, a2dCanvasObjectList* objects, a2dCanvasObjectFlagsMask mask, a2dLayers* layersetup )
2404 {
2405  int nr = 0;
2406  forEachIn( a2dCanvasObjectList, objects )
2407  {
2408  a2dCanvasObject* obj = *iter;
2409  a2dText* text = wxDynamicCast( obj, a2dText );
2410 
2411  if ( obj->GetFixedStyle() || obj->GetRelease() || !obj->CheckMask( mask ) || !text )
2412  continue;
2413 
2414  obj->SetBin2( true );
2415 
2416  a2dFont font = text->GetFont();
2417 
2418  if ( !nr )
2419  {
2420  returned.Set( font, text->GetTextFlags(), text->GetAlignment() );
2421  }
2422  else
2423  returned.Mix( font, text->GetTextFlags(), text->GetAlignment() );
2424  nr++;
2425  }
2426  return nr;
2427 }
a2dHit m_how
return in which way the object was hit (stroke, fill, ...)
Definition: canobj.h:301
void PushCursor(const wxCursor &cursor)
push a cursor on the cursor stack, and set display cursor to new back being cursor.
Definition: drawer.cpp:1052
bool DoUpdate(UpdateMode mode, const a2dBoundingBox &childbox, const a2dBoundingBox &clipbox, const a2dBoundingBox &propbox)
Update derived Object specific things ( mainly boundingbox)
Definition: cantext.cpp:822
perform snapping to boundingbox of objects
Definition: restrict.h:137
int GetAlignment() const
Get the position of the anchor point w.r.t the text.
Definition: cantext.h:647
double m_relx
(world coordinates) hit point x relative to the canvas object its parent object(s) ...
Definition: canobj.h:289
a2dAffineMatrix & Mirror(bool y=true, bool x=false)
mirror a matrix in x, y
Definition: afmatrix.cpp:396
double GetHeight() const
returns height of the boundingbox
Definition: bbox.cpp:334
a2dText derived from a2dCanvasObject, holds multiline text
virtual void Render(a2dIterC &ic, OVERLAP clipparent)
Render this object to the active a2dDrawingPart.
Definition: canobj.cpp:4712
double GetAbsY() const
get absolute Y position of the pin ( after applying the parent&#39;s matrix and its own matrix ) ...
Definition: canpin.cpp:966
double GetSize() const
Get the font size.
Definition: stylebase.cpp:2917
bool SetSpecificFlags(bool setOrClear, a2dCanvasObjectFlagsMask which, const wxString &classname=wxT(""), a2dCanvasObjectFlagsMask whichobjects=a2dCanvasOFlags::ALL, const a2dBoundingBox &bbox=wxNonValidBbox, const a2dAffineMatrix &tworld=a2dIDENTITY_MATRIX)
set all given bit flags at once recursive for all objects in given boundingbox
Definition: objlist.cpp:519
double GetStrokeWidth() const
Get stroke width.
Definition: stylebase.cpp:2931
#define wxDynamicCast(obj, className)
Define wxDynamicCast so that it will give a compiler error for unrelated types.
Definition: gen.h:75
Base class for all types of strokes, understood by a2dDrawer2D classes.
Definition: stylebase.h:378
void SetRoot(a2dDrawing *root, bool recurse=true)
Sets this object to a a2dCanvasDocument.
Definition: canobj.cpp:5933
bool GetGeneratePins() const
get the GeneratePins flag
Definition: canobj.h:2289
wxString TextAlignment2String(int alignment)
convert alignment enum to a string
Definition: cantext.cpp:32
const wxString & GetName() const
Get name of font, e.g. Arial.
Definition: stylebase.h:717
a2dHandle is used inside editing versions of a certain objects.
Definition: canpin.h:30
mouse event sent from a2dCanvasObject to itself
Definition: canglob.h:223
Text is always readible from the bottom right.
Definition: cantext.h:107
a2dConnectTask
flags for searching a connecting a2dpinClass, for the connecting task at hand.
Definition: connectgen.h:40
void SetAlignment(int alignment)
Set the position of the anchor point w.r.t the text.
Definition: cantext.h:294
void SetDrawStyle(a2dDrawStyle drawstyle)
set drawstyle to use for drawing,
Definition: drawer2d.cpp:557
const a2dStroke * a2dBLACK_STROKE
global a2dStroke stock object for BLACK stroking
Font info class, used as a single element for enumerating fonts.
Definition: stylebase.h:686
virtual void PopTransform(void)
Recall the previously saved user-to-world transform off the matrix stack.
Definition: drawer2d.cpp:480
a2dTextGDS text based on wxDC text drawing.
Definition: cantext.h:467
disable background drawing
Definition: cantext.h:109
void ParseString(wxString string)
Fill this class from a string.
Definition: stylebase.cpp:120
class to map references to objects stored in XML, in order to make the connection later on...
Definition: gen.h:3462
a2dDrawing * m_root
root group for rendering and accessing the canvas&#39;s also contains layer settings
Definition: canobj.h:2525
int m_alignment
Alignment.
Definition: cantext.h:410
next line is higher in Y if set
Definition: cantext.h:105
a2dPropertyIdTyped< wxString, a2dStringProperty > a2dPropertyIdString
property of this type
Definition: id.h:665
transfer this property via a command processor
Definition: id.h:169
a2dCanvasOFlags m_flags
holds flags for objects
Definition: canobj.h:2528
const wxString & GetExtra() const
Get the extra information ( e.g. the filename of the font )
Definition: stylebase.h:744
const a2dAffineMatrix & GetInverseTransform() const
Inverse of GetTransform()
Definition: canobj.cpp:699
static const a2dCanvasObjectFlagsMask BIN2
Definition: candefs.h:193
void SetPixelStroke(bool pixelstroke)
set pixelstoke flag, stroke width is defined in pixels else in worldcoordinates
Definition: stylebase.cpp:6316
double m_linespace
space between the lines
Definition: cantext.h:378
a2dPin is used in a2dCanvasObject to add pins to it.
Definition: canpin.h:233
This is a class/type description for a2dPin&#39;s.
Definition: canpin.h:628
Ref Counted base object.
Definition: gen.h:1045
double GetSize() const
Get size of the font.
Definition: stylebase.h:727
bool Rotate(double angle)
Rotate clockwise by the given number of degrees:
Definition: afmatrix.cpp:432
allow draw a frame rect around a text
Definition: cantext.h:111
bool GetMultiLine() const
True if multiple lines of text are allowed.
Definition: cantext.h:200
void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)
Load object specific CVG data.
Definition: cantext.cpp:536
void SetNextLineDirection(bool up)
next line is higher in Y if true or lower if false
Definition: cantext.cpp:497
When cloning, and this flag is set, the property is cloned deep, else not.
Definition: id.h:196
basetype * GetPropertyValuePtr(a2dObject *obj) const
Get a pointer to the property value in obj.
Definition: id.inl:366
bool GetBackGround() const
Definition: cantext.h:230
bool IsHit() const
true if this is a hit
Definition: polyver.h:107
virtual bool Update(UpdateMode mode)
Update the state of the object according to its current position etc.
Definition: canobj.cpp:5149
wxString CreateString()
Create a string description of the font.
Definition: stylebase.cpp:2887
unsigned int GetTextFlags() const
Get the text flags.
Definition: cantext.h:642
int GetAttributeValueInt(const wxString &attrib, int defaultv=0)
Returns the integer value of an attribute.
Definition: genxmlpars.cpp:495
int m_caret
position of caret within text string
Definition: cantext.h:387
bool AdjustPinLocation()
Allow change in pin location when wiring things up.
Definition: cantext.cpp:1859
#define EVT_CANVASHANDLE_MOUSE_EVENT(func)
static event table macro for a2dHandle mouse event
Definition: canglob.h:318
void SetDrawerStroke(const a2dStroke &stroke)
Used to set the current stroke.
Definition: drawer2d.cpp:565
Defines a font to be set to a2dDrawer2D or stored in a2dCanvsObject etc.
Definition: stylebase.h:779
Input and output handler for the XmlSer format.
Definition: genxmlpars.h:819
UpdateMode
Various mode flags for Update.
Definition: canobj.h:1091
snap to pins in other objects when not connected
Definition: restrict.h:112
~a2dText()
Destructor.
Definition: cantext.cpp:165
int GetLines() const
get the number of lines in the text
Definition: cantext.cpp:326
virtual void SetPending(bool pending)
set this object pending for update
Definition: canobj.cpp:2585
void SetNormalizedFont(bool forceNormalizedFont)
Use a fixed device height for drawing text.
Definition: drawer2d.h:566
OVERLAP
Result of a a2dBoundingBox intersection or hittest.
Definition: bbox.h:24
int AlignmentString2TextAlignment(const wxString &alignstring)
convert a string to alignment enum
Definition: cantext.cpp:58
bool m_visiblechilds
child objects are visible or not
Definition: candefs.h:292
bool GetYaxis() const
get y axis orientation
Definition: drawer2d.h:280
virtual bool DoStartEdit(wxUint16 editmode, wxEditStyle editstyle)
only used for editable objects and under control of a editing tool.
Definition: cantext.cpp:937
a2dPin * IsConnectedTo(a2dPin *pin=a2dAnyPin) const
Return the pin to which this pin is connected.
Definition: canpin.cpp:751
bool m_hasPins
true if this object does have a2dPin&#39;s as children
Definition: candefs.h:323
double GetTransformedHitMargin()
transformed to object its coordinate system
Definition: canobj.cpp:616
void SetFont(const a2dFont &font)
set font to use for drawing text
Definition: drawer2d.cpp:722
wxUint16 m_layer
layer of object, default wxLAYER_DEFAULT
Definition: canobj.h:2556
a2dTextGDS(a2dFontType fontType=a2dFONT_STROKED, const wxString &text=wxT("not specified"), double height=1.0, short int presentation=0)
constructor
Definition: cantext.cpp:1904
virtual void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)
load object specific CVG data
Definition: canobj.cpp:5728
void ReStoreFixedStyle()
when fixed drawing style is set, it can be overruled.
Definition: drawer2d.cpp:711
a2dCanvasObject is the base class for Canvas Objects.
Definition: canobj.h:371
wxColour GetColour() const
return colour 1
Definition: stylebase.cpp:6131
void SetSize(double size)
Set the font size.
Definition: stylebase.cpp:2909
void SetBackGround(bool background=true)
Set if a background will be drawn.
Definition: cantext.cpp:382
bool GetCaretShow() const
return true if caret is visible
Definition: cantext.h:270
bool GetVpath(wxChar c, a2dVpath &glyph, const a2dAffineMatrix &affine=a2dIDENTITY_MATRIX)
Get the glyph of a single character as a vpath.
Definition: stylebase.cpp:3111
void ReStartEdit(wxUint16 editmode)
to restart editing in a different mode
Definition: canobj.cpp:1693
void TransformPoint(double x, double y, double &tx, double &ty) const
Transform a point.
Definition: afmatrix.cpp:559
double GetRotation() const
return rotation
Definition: afmatrix.cpp:799
wxString GetName() const
get the name given to the handle.
Definition: canpin.h:56
static a2dPropertyIdString * PROPID_PreEditText
old Text property, to return text as it was before editing (use in Undo)
Definition: cantext.h:326
double TransformDistance(double distance) const
Transform a distance.
Definition: afmatrix.cpp:616
return to contain edit bbox, suitable for editing matrix of object
Definition: canobj.h:666
a2dBoundingBox GetTextExtent(const wxString &string, int alignment=wxMINX|wxMINY, double *w=NULL, double *h=NULL, double *descent=NULL, double *externalLeading=NULL) const
Get the dimensions in world coordinates of the string.
Definition: stylebase.cpp:3044
union a2dTextGDS::@5 m_presentationflags
presentation flags
double m_YcaretinLine
Y position of caret in world coordinate in line.
Definition: cantext.h:393
a2dDrawStyle GetDrawStyle() const
get drawstyle used for drawing.
Definition: drawer2d.h:693
a2dFont GetFont() const
get font for text
Definition: cantext.h:251
void SetStyle(const wxString &style)
Set style of font, e.g. Bold.
Definition: stylebase.h:724
a2dAffineMatrix m_lworld
used for positioning the object (x,y,ang,scale etc.)
Definition: canobj.h:2559
size_t m_firsteditable
The first editable character, usually 0, but may be different for a2dVisibleProperty.
Definition: cantext.h:407
void SetCaretShow(bool visible=true)
set caret on or off
Definition: cantext.cpp:517
wxUint64 a2dCanvasObjectFlagsMask
mask flags for a2dCanvasObject
Definition: candefs.h:152
void SetInternal(bool internal)
set when pin is within the border of its parent
Definition: canpin.h:444
void SetDrawerFill(const a2dFill &fill)
Used to set the current fill.
Definition: drawer2d.cpp:621
bool Ok() const
Check font validity.
Definition: stylebase.cpp:2894
void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)
Load object specific CVG data.
Definition: cantext.cpp:2079
void SetDrawFrame(bool frame=true)
Set if a frame rect will be drawn.
Definition: cantext.cpp:390
wxMouseEvent & GetMouseEvent()
return the original mouse event that was redirected to the a2dHandle
Definition: canglob.h:290
snap to other objects its vertexes, which are decided in a2dCanvasObject::RestrictToObject() ...
Definition: restrict.h:116
void SetWidth(float width)
Set width of stroke in world coordinates.
Definition: stylebase.cpp:6262
void WriteNewLine()
Writes a new line and takes care of indentation.
Definition: genxmlpars.cpp:890
virtual void PushTransform()
Save the current user-to-world transform on the affine stack.
Definition: drawer2d.cpp:452
double GetWidth(wxChar c)
Get width of a single character.
Definition: stylebase.cpp:3106
a2dText is an abstract base class.
Definition: cantext.h:93
a2dCanvasObjectList * wxNullCanvasObjectList
define a NON a2dCanvasObjectList
Definition: objlist.cpp:53
bool GetValid() const
returns true if boundingbox is calculated properly and therefore its valid flag is set...
Definition: bbox.cpp:299
const wxString & GetType() const
Get type of font, e.g. Freetype or Stroke.
Definition: stylebase.h:712
void Expand(const a2dPoint2D &, const a2dPoint2D &)
expand boundingbox width two points
Definition: bbox.cpp:155
const a2dBoundingBox & Translate(a2dPoint2D &)
translate with given vector
Definition: bbox.cpp:370
virtual a2dBoundingBox GetUnTransformedBbox(a2dBboxFlags flags=a2dCANOBJ_BBOX_CHILDREN) const
Get boundingbox without the affine matrix transform included.
Definition: canobj.cpp:5036
double GetMinX() const
get minimum X of the boundingbox
Definition: bbox.cpp:304
virtual void DrawRoundedRectangle(double x, double y, double width, double height, double radius, bool pixelsize=false)
Draw RoundedRectangle in world coordinates.
Definition: drawer2d.cpp:2048
a2dCanvasObjectList * m_childobjects
holds child objects
Definition: canobj.h:2562
void SetFont(const a2dFont &font, double lineSpaceFactor=0.1)
set font for text
Definition: cantext.cpp:527
#define forEachIn(listtype, list)
easy iteration for a2dlist
Definition: a2dlist.h:111
static void GetInfoList(a2dFontInfoList &list)
Append fonts of this type to the list.
Definition: stylebase.cpp:3156
const a2dFont * a2dNullFONT
global a2dFont stock object for NO font
void SetPropertyToObject(a2dObject *obj, const basetype &value, SetFlags setflags=set_none) const
Set the property in obj to value.
Definition: id.inl:238
void SetWeight(double weight)
Set the weight of the font.
Definition: stylebase.cpp:3295
double GetPosX() const
get x position from affine matrix
Definition: canobj.h:527
a2dDrawer2D * GetDrawer2D() const
get current a2dDrawer2D
Definition: canobj.cpp:636
Normal straight line segment in a2dVpath.
Definition: polyver.h:878
#define wxStaticCast(obj, className)
The wxWindows 2.4.2 wxStaticCast is buggy. It evaluates its argument twice.
Definition: gen.h:123
bool m_editable
object can be edited
Definition: candefs.h:295
double wxRadToDeg(double rad)
conversion from radians to degrees
Definition: artglob.cpp:31
void SetSpecificFlags(bool setOrClear, a2dCanvasObjectFlagsMask which)
set all bit flags in object that or true in mask to true or false
Definition: canobj.cpp:2645
#define EVT_CANVASOBJECT_MOUSE_EVENT(func)
static event table macro for a2dCanvasObject mouse event
Definition: canglob.h:312
a2dSLine
Definition: canprim.h:987
void SetContourWidth(double width)
Definition: vpath.h:155
Definition: bbox.h:27
static a2dFont CreateFont(const a2dFontInfo &info, bool force=false)
Create the font from a fontinfo description.
Definition: stylebase.cpp:3163
void SetTextHeight(double height)
set text height in world coordinates
Definition: cantext.h:173
virtual void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)
write object specific CVGL data
Definition: canobj.cpp:5569
const a2dAffineMatrix & GetUserToDeviceTransform() const
get matrix which transforms directly from relative world coordinates to device
Definition: canobj.cpp:626
general event sent from a2dHandle to its parent a2dCanvasObject
Definition: canglob.h:273
a2dCanvasObjectList * GetAsCanvasVpaths(bool transform=true) const
return text as a vector path, where text outline is converted to polyline or polygons.
Definition: cantext.cpp:247
double GetLineHeight() const
Height in world coordinates of one line.
Definition: cantext.h:179
void Add(a2dVpathSegment *seg)
add a segment
Definition: polyver.h:1240
Restriction engine for editing restrictions like snapping.
Definition: restrict.h:88
bool m_childrenOnSameLayer
Definition: candefs.h:311
bool GetNextLineDirection() const
next line is higher in Y if true or lower if false
Definition: cantext.h:212
bool HasPins(bool realcheck=false)
are there a2dPin derived children
Definition: canobj.cpp:6414
virtual void DrawLine(double x1, double y1, double x2, double y2)
Draw line in world coordinates.
Definition: drawer2d.cpp:2167
Input and output handler for the XmlSer format.
Definition: genxmlpars.h:862
bool CheckMask(a2dCanvasObjectFlagsMask mask) const
Compares all flags in object to the given mask and return true is the same.
Definition: canobj.cpp:2665
a2dPin * AddPin(const wxString name, double x, double y, wxUint32 a2dpinFlags, a2dPinClass *pinClass, bool undo=false)
add a a2dPin as child
Definition: canobj.cpp:6474
size_t m_selection_start_pos
Selection starting position.
Definition: cantext.h:402
double GetTextHeight() const
get text height in world coordinates
Definition: cantext.h:176
void SetPathType(a2dPATH_END_TYPE pathtype)
Set when m_contourwidth != 0 what is the end of the lines should be.
Definition: vpath.h:169
bool GetDrawFrame() const
Definition: cantext.h:239
int GetAsArray(wxArrayString &array)
get lines into array, return number of lines
Definition: cantext.cpp:293
wxString RequireAttributeValue(const wxString &attrib)
Forces an attribute and returns its string value.
Definition: genxmlpars.cpp:461
virtual bool DoIsHitWorld(a2dIterC &ic, a2dHitEvent &hitEvent)
Does hit test on the object (exclusif child objects)
Definition: cantext.cpp:597
the property is temporary and never saved
Definition: id.h:163
Contains a2dDrawing Class to hold a drawing.
Allows multiple lines of text.
Definition: cantext.h:99
virtual a2dBoundingBox DoGetUnTransformedBbox(a2dBboxFlags flags=a2dCANOBJ_BBOX_NON) const
Get boundingbox without the affine matrix transform included.
Definition: cantext.cpp:894
wxUint32 a2dSnapToWhatMask
mask for a2dSnapToWhat flags
Definition: restrict.h:26
bool PointInBox(const a2dPoint2D &, double Marge=0) const
is the point within the boundingbox
Definition: bbox.cpp:256
no hit will be reported
Definition: canobj.h:160
virtual bool Submit(a2dCommand *command, bool storeIt=true)
next to the base class submit, it sets a2DocumentCommandProcessor for a2dCommand
Definition: comevt.cpp:842
bool GetEngineeringText() const
Is text always readible from the bottom right.
Definition: cantext.h:218
virtual void DrawText(const wxString &text, double x, double y, int alignment=wxMINX|wxMINY, bool Background=true)
Draw text in user coordinates.
Definition: drawer2d.cpp:2329
void SetVisible(bool visible)
set if this object will visible (be rendered or not)
Definition: canobj.h:1303
virtual bool DoStartEdit(wxUint16 editmode, wxEditStyle editstyle)
only used for editable objects and under control of a editing tool.
Definition: canobj.cpp:1739
unsigned int GetTextFlags() const
Get the text flags.
Definition: cantext.h:195
A 2x3 affine matrix class for 2D transformations.
Definition: afmatrix.h:53
wxMouseEvent & GetMouseEvent()
return the original mouse event that was redirected to the a2dCanvasObject
Definition: canglob.h:243
a2dStroke GetDrawerStroke() const
get the current stroke
Definition: drawer2d.h:548
wxUint16 m_pixelExtend
Pixel extend.
Definition: canobj.h:2553
double GetMaxX() const
get maximum X of the boundingbox
Definition: bbox.cpp:316
a2dPin * HasPinNamed(const wxString pinName, bool NotConnected=false)
are there a2dPin derived children which matches the given pin name?
Definition: canobj.cpp:6436
bool GetFixedStyle() const
Get object fixed style setting.
Definition: canobj.h:1590
double GetPosY() const
get y position from affine matrix
Definition: canobj.h:530
double GetWorldStrokeExtend()
Definition: canobj.h:3403
void SetName(const wxString &name)
Set name of font, e.g. Arial.
Definition: stylebase.h:719
const a2dStroke * a2dWHITE_STROKE
global a2dStroke stock object for WHITE stroking
a2dBoundingBox m_untransbbox
Untransformed bounding box.
Definition: cantext.h:396
while iterating a a2dCanvasDocument, this holds the context.
Definition: canobj.h:3212
void SetExtra(const wxString &extra)
Set the extra information ( e.g. the filename of the font )
Definition: stylebase.h:747
void SetMultiLine(bool multiline=true)
Set if multiple lines of text are allowed.
Definition: cantext.cpp:365
virtual a2dObject * DoClone(CloneOptions options, a2dRefMap *refs) const
Clone this object and return a pointer to the new object.
Definition: cantext.cpp:169
All updates of these modes force an update (e.g. update non-pending valid bounding boxes) ...
Definition: canobj.h:1107
void MapBbox(const a2dAffineMatrix &matrix)
Definition: bbox.cpp:445
a2dCommandProcessor * GetCommandProcessor() const
Returns a pointer to the command processor associated with this document.
Definition: drawing.h:549
const a2dFont * a2dDEFAULT_CANVASFONT
global a2dFont stock object for default font
virtual void DoRender(a2dIterC &ic, OVERLAP clipparent)
Render derived object.
Definition: cantext.cpp:647
void SetSize(double size)
Set size of the font.
Definition: stylebase.h:735
void SetStroke(const wxColour &strokecolor, double width=0, a2dStrokeStyle style=a2dSTROKE_SOLID)
Set a stroke for the object which will be used instead of the layer stroke.
Definition: canobj.cpp:2924
virtual void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)
Write object specific CVG data.
Definition: cantext.cpp:568
wxString GetAttributeValue(const wxString &attrib, const wxString &defaultv=wxT(""))
Returns the value of an attribute.
Definition: genxmlpars.cpp:450
a2dRestrictionEngine * GetRestrictionEngine()
Get restriction engine (grid snapping)
Definition: canglob.cpp:934
void SetCaretUntransformed(double xh, double yh)
Set caret to the character closest to the position.
Definition: cantext.cpp:439
a2dAffineMatrix GetEngineeringTransform(a2dIterC &ic)
Calculate a new affine, so text is always readible from the bottom right.
Definition: cantext.cpp:619
bool GetRelease() const
get release flag
Definition: gen.h:1350
double GetMaxY() const
get maximum Y of the boundingbox
Definition: bbox.cpp:322
double GetWidth() const
returns width of the boundingbox
Definition: bbox.cpp:328
An object of this class will update a a2dIterC with the required information.
Definition: canobj.h:3123
const wxString & GetStyle() const
Get style of font, e.g. Bold.
Definition: stylebase.h:722
wxUint16 m_texttype
GDSII compatible to sub identify types of text.
Definition: cantext.h:527
return to contain children bbox
Definition: canobj.h:667
size_t m_selection_end_pos
Selection end position.
Definition: cantext.h:404
void SetPosXY(double x, double y, bool restrict=false)
set position to x,y
Definition: canobj.cpp:1624
bool Translate(double x, double y)
Translate by dx, dy:
Definition: afmatrix.cpp:420
double GetKerning(wxChar c1, wxChar c2) const
Get kerning space between two characters.
Definition: stylebase.cpp:2924
void SetEngineeringText(bool engineering=true)
Keep text readible from the bottom right.
Definition: cantext.cpp:507
wxString CreateString() const
Assemble a string containing this class in a readable format.
Definition: stylebase.cpp:108
bool m_editingCopy
true if the object needs to be rendered in edit mode.
Definition: candefs.h:304
bool m_utbbox_changed
Untransformed bounding box changed.
Definition: cantext.h:399
a2dFill GetDrawerFill() const
get the current fill
Definition: drawer2d.h:557
wxString GetLine(int line) const
get the number of lines in the text
Definition: cantext.cpp:342
double m_XcaretinLine
X position of caret in world coordinate in line.
Definition: cantext.h:390
a2dRect
Definition: canprim.h:440
a2dCanvasObject * IsHitWorld(a2dIterC &ic, a2dHitEvent &hitEvent)
If the position (x,y) is within the object return this.
Definition: canobj.cpp:3415
A list used for enumerating fonts.
The a2dBoundingBox class stores one a2dBoundingBox of a a2dCanvasObject.
Definition: bbox.h:39
bool Invert(void)
Invert matrix.
Definition: afmatrix.cpp:197
void Rotate(double rotation)
Rotates this object clockwise.
Definition: canobj.cpp:2615
double GetDeterminant() const
Calculate the determinat of the linear transformation.
Definition: afmatrix.cpp:825
unsigned int m_textflags
contains several text flags.
Definition: cantext.h:384
void SetType(const wxString &type)
Set type of font, e.g. Freetype or Stroke.
Definition: stylebase.h:714
double GetMinY() const
get minimum Y of the boundingbox
Definition: bbox.cpp:310
virtual a2dCanvasObjectList * GetSnapVpath(a2dSnapToWhatMask snapToWhat)
return a vectorpath indicating on which point/segments the object likes to be snapped.
Definition: cantext.cpp:175
the a2dDrawingPart is a a2dView specially designed for displaying parts of a a2dDrawing. It uses a a2dDrawer2D to actually redraw things from the document, by giving that a2dDrawer2D as drawing context to the document, and telling the document to redraw a certain rectangular area. At that last is what this class is for. It optimizes the areas to be redrawn after object in the document were changed. To do that it combines redraw areas to a minimal set of redrawing areas. All the administration for this and the way things will be redrawn is from this view.
void SetCaret(int position)
set position of caret (-1 means off)
Definition: cantext.h:254
basetype GetPropertyValue(const a2dObject *obj) const
Get the property value in obj.
Definition: id.inl:325
a2dCanvasGlobal * a2dCanvasGlobals
global a2dCanvasGlobal to have easy access to global settings
Definition: canglob.cpp:1234
a2dCanvasObject for a Vector Path
Definition: vpath.h:55
bool GeneratePins(a2dPinClass *toConnectTo, a2dConnectTask task, double x, double y, double margin=0)
create pins in derived objects.
Definition: cantext.cpp:1814
a2dDrawingPart * GetDrawingPart() const
get current a2dDrawingPart
Definition: canobj.cpp:631
int GetAlignment() const
Get the position of the anchor point w.r.t the text.
Definition: cantext.h:304
This template class is for property ids with a known data type.
Definition: id.h:477
double GetScale()
See GetScale()
Definition: genxmlpars.h:545
a2dBoundingBox m_bbox
boundingbox in world coordinates
Definition: canobj.h:2539
Vector Path.
Definition: polyver.h:1211
double RequireAttributeValueDouble(const wxString &attrib)
Forces an attribute and returns its double value.
Definition: genxmlpars.cpp:487
Todo: The text will not be user-editable, but is selectable.
Definition: cantext.h:101
const a2dFontInfo & GetFontInfo() const
Get fontinfo of the font.
Definition: stylebase.cpp:2901
double GetAbsX() const
get absolute X position of the pin ( after applying the parent&#39;s matrix and its own matrix ) ...
Definition: canpin.cpp:959
a2dText(const wxString &text=wxT("not specified"))
constructor
Definition: cantext.cpp:111
void Append(a2dCanvasObject *obj)
append a a2dCanvasObject to the childobjects
Definition: canobj.cpp:6224
wxString m_text
the text to display
Definition: cantext.h:381
void SetReadOnly(bool readonly=true)
Set if text is readonly.
Definition: cantext.cpp:374
const a2dAffineMatrix & GetTransform() const
Get the accumulated transform up to and including m_lworld of the current object. ...
Definition: canobj.cpp:663
virtual a2dObject * DoClone(CloneOptions options, a2dRefMap *refs) const
Clone this object and return a pointer to the new object.
Definition: cantext.cpp:1967
virtual void SetLayer(wxUint16 layer)
set layer index where this object is drawn upon.
Definition: canobj.cpp:5920
used to change text and caret of canvas text objects in a a2dCanvasDocument
Definition: drawing.h:2167
list of a2dObject&#39;s
Definition: gen.h:3157
double m_rely
(world coordinates) hit point y relative to the canvas object its parent object(s) ...
Definition: canobj.h:291
#define BBOX2XYWH(bbox)
expand a2dBoundingBox to x,y,w,h
Definition: axis.cpp:885
A pointer class, that automatically calls SmrtPtrOwn/SmrtPtrRelease.
Definition: a2dlist.h:20
edit a copy of the original object
Definition: canobj.h:132
CloneOptions
options for cloning
Definition: gen.h:1200
void SetHitFlags(a2dCanvasObjectHitFlags mask)
set hit flags
Definition: canobj.cpp:2670
virtual void DoEndEdit()
only used for editable objects and under control of a editing tool.
Definition: cantext.cpp:1026
void SetPreRenderAsChild(bool prerender)
If set, this object has a higher priority in rendering than other children objects.
Definition: canobj.h:1469
a2dBoundingBox & GetBbox()
get boundingbox in world coordinates exclusive stroke width relative to its parent ...
Definition: canobj.cpp:3175
structure to give as parameter to member functions of a2dCanvasObject
Definition: canobj.h:252
virtual bool RestrictPoint(double &x, double &y, wxUint32 sourceRequired=snapToAll, bool ignoreEngine=false)
Restrict a single point of a line or polyline.
Definition: restrict.cpp:227
void SetFill(const a2dFill &fill)
Set a fill for the object which will be used instead of the layer fill.
Definition: canobj.cpp:2874
virtual void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)
Write object specific CVG data.
Definition: cantext.cpp:2097
snap to pins in other objects
Definition: restrict.h:111
a2dFont m_font
font
Definition: cantext.h:371
const a2dFill * a2dTRANSPARENT_FILL
global a2dFill stock object for TRANSPARENT filling
static const a2dCanvasObjectFlagsMask PRERENDERASCHILD
Definition: candefs.h:198
general canvas module declarations and classes
wxEditStyle
Definition: canobj.h:109
void OverRuleFixedStyle()
id style is FIXED, saves current style and sets style to a2dFILLED
Definition: drawer2d.cpp:697
cantext.cpp Source File -- Sun Oct 12 2014 17:04:14 -- Sun Oct 12 2014 -- 1.8.5 -- wxArt2D -- . -- Main Page Reference Documentation