00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "a2dprec.h"
00012
00013 #ifdef __BORLANDC__
00014 #pragma hdrstop
00015 #endif
00016
00017 #ifndef WX_PRECOMP
00018 #include "wx/wx.h"
00019 #endif
00020
00021 #include <wx/clipbrd.h>
00022
00023 #include "wx/canvas/cantext.h"
00024 #include "wx/canvas/cancom.h"
00025 #include "wx/canvas/canglob.h"
00026
00027 IMPLEMENT_DYNAMIC_CLASS(a2dText, a2dCanvasObject)
00028
00029
00030
00031
00032
00033 #define DRAGRECTWIDTH 5
00034
00035 a2dPropertyIdFont* a2dText::PROPID_Font = NULL;
00036
00037 INITIALIZE_PROPERTIES( a2dText, a2dCanvasObject )
00038 {
00039 PROPID_Font = new a2dPropertyIdFont( wxT("Font"),
00040 a2dPropertyId::flag_transfer|a2dPropertyId::flag_clonedeep,
00041 *a2dNullFONT,
00042 static_cast < a2dPropertyIdFont::ConstGet >(&a2dText::MX_GetFont),
00043 static_cast < a2dPropertyIdFont::ConstSet >(&a2dText::MX_SetFont) );
00044 AddPropertyId( PROPID_Font );
00045
00046 return true;
00047 }
00048
00049 A2D_BEGIN_EVENT_TABLE( a2dText, a2dCanvasObject )
00050 A2D_EVT_CANVASOBJECT_MOUSE_EVENT(a2dText::OnCanvasObjectMouseEvent )
00051 A2D_EVT_CHAR( a2dText::OnChar )
00052 A2D_EVT_CANVASHANDLE_MOUSE_EVENT( a2dText::OnHandleEvent )
00053 A2D_END_EVENT_TABLE()
00054
00055 a2dText::a2dText( const wxString &text)
00056 {
00057 m_text = text;
00058 m_font = *a2dDEFAULT_CANVASFONT;
00059 m_alignment = a2dDEFAULT_ALIGNMENT;
00060 m_linespace = 1.0 / 10.0;
00061 m_caret = -1;
00062 m_selection_start_pos = m_selection_end_pos = 0;
00063 m_firsteditable = 0;
00064 m_textflags = a2dCANVASTEXT_DEFAULTFLAGS;
00065 m_utbbox_changed = true;
00066 }
00067
00068 a2dText::a2dText( const wxString &text, double x, double y,
00069 const a2dFont& font, double angle, bool up, int alignment )
00070 {
00071 m_text = text;
00072 m_font = font;
00073 m_alignment = alignment;
00074 m_linespace = font.GetSize() / 10.0;
00075 m_caret = -1;
00076 m_selection_start_pos = m_selection_end_pos = 0;
00077 m_firsteditable = 0;
00078 m_textflags = a2dCANVASTEXT_DEFAULTFLAGS;
00079 SetNextLineDirection( up );
00080 Rotate(angle);
00081 m_lworld.Translate(x, y);
00082 m_utbbox_changed = true;
00083 }
00084
00085 a2dText::a2dText( const a2dText &other, CloneOptions options )
00086 : a2dCanvasObject( other, options )
00087 {
00088 m_text = other.m_text;
00089 m_linespace = other.m_linespace;
00090 m_font = other.m_font;
00091 m_alignment = other.m_alignment;
00092 m_textflags = other.m_textflags;
00093 m_caret = -1;
00094 m_selection_start_pos = m_selection_end_pos = 0;
00095 m_firsteditable = other.m_firsteditable;
00096
00097
00098
00099
00100 m_untransbbox = other.m_untransbbox;
00101 m_utbbox_changed = other.m_utbbox_changed;
00102 }
00103
00104 a2dText::~a2dText()
00105 {
00106 }
00107
00108 a2dCanvasObjectList* a2dText::GetAsCanvasVpaths( bool transform )
00109 {
00110 a2dAffineMatrix pworld;
00111 if ( transform )
00112 pworld = m_lworld;
00113
00114 a2dCanvasObjectList* canpathlist = new a2dCanvasObjectList();
00115
00116
00117
00118
00119 int up = GetNextLineDirection() ? 1 : -1;
00120 size_t linestart;
00121 size_t lineend = (size_t) 0;
00122 size_t textlength = m_text.Length();
00123 int line = 0;
00124 wxString linetext;
00125 while ( lineend < textlength )
00126 {
00127 linestart = lineend;
00128 while ( lineend < textlength && m_text[lineend] != wxChar('\n') )
00129 lineend++;
00130 linetext = m_text.Mid( linestart, lineend - linestart );
00131
00132 a2dVpath* segments = new a2dVpath();
00133
00134 GetFont().GetVpath( linetext, *segments, 0.0, line * up * (GetLineHeight() + m_linespace), m_alignment, true, pworld );
00135
00136 a2dVectorPath* canpath = new a2dVectorPath( segments );
00137 canpath->SetStroke( this->GetStroke() );
00138 canpath->SetFill( this->GetFill() );
00139 canpath->SetLayer( m_layer );
00140 if ( m_font.GetType() == a2dFONT_STROKED )
00141 {
00142 canpath->SetContourWidth( m_font.GetStrokeWidth() );
00143 canpath->SetPathType( a2dPATH_END_ROUND );
00144 }
00145 canpathlist->push_back( canpath );
00146
00147 lineend++;
00148 line++;
00149 }
00150
00151 return canpathlist;
00152 }
00153
00154 int a2dText::GetAsArray( wxArrayString& array )
00155 {
00156 int lines = 0;
00157 if ( GetMultiLine() )
00158 {
00159 wxString line;
00160 size_t i = 0;
00161 while ( i < m_text.Length() )
00162 {
00163 if ( m_text[i] == '\n' )
00164 {
00165 array.Add( line );
00166 line.Empty();
00167 lines++;
00168 }
00169 else
00170 line += m_text[i];
00171 i++;
00172 }
00173 if ( !line.IsEmpty() )
00174 {
00175 array.Add( line );
00176 lines++;
00177 }
00178 }
00179 else
00180 {
00181 array.Add( m_text );
00182 lines++;
00183 }
00184 return lines;
00185 }
00186
00187 int a2dText::GetLines() const
00188 {
00189 int lines = 1;
00190 if ( GetMultiLine() )
00191 {
00192 size_t i = 0;
00193 while ( i < m_text.Length() )
00194 {
00195 if ( m_text[i] == '\n' )
00196 lines++;
00197 i++;
00198 }
00199 }
00200 return lines;
00201 }
00202
00203 wxString a2dText::GetLine(int n) const
00204 {
00205 wxString string;
00206
00207 size_t i = 0;
00208 int newlines = 0;
00209 while ( i < m_text.Length() && newlines < n )
00210 {
00211 if (m_text[i] == '\n' )
00212 newlines++;
00213 i++;
00214 }
00215 if ( i < m_text.Length() )
00216 {
00217 while ( i < m_text.Length() && m_text[i] != '\n' )
00218 {
00219 string += m_text[i];
00220 i++;
00221 }
00222 }
00223 return string;
00224 }
00225
00226 void a2dText::SetMultiLine( bool multiline )
00227 {
00228 if (multiline)
00229 m_textflags |= a2dCANOBJTEXT_MULTILINE;
00230 else
00231 m_textflags &= ~a2dCANOBJTEXT_MULTILINE;
00232 m_utbbox_changed = true;
00233 }
00234
00235 void a2dText::SetReadOnly( bool readonly )
00236 {
00237 if (readonly)
00238 m_textflags |= a2dCANOBJTEXT_READONLY;
00239 else
00240 m_textflags &= ~a2dCANOBJTEXT_READONLY;
00241 }
00242
00243 void a2dText::SetBackGround( bool background )
00244 {
00245 if (background)
00246 m_textflags |= a2dCANOBJTEXT_BACKGROUND;
00247 else
00248 m_textflags &= ~a2dCANOBJTEXT_BACKGROUND;
00249 }
00250
00251 void a2dText::SetDrawFrame( bool frame )
00252 {
00253 if (frame)
00254 m_textflags |= a2dCANOBJTEXT_FRAME;
00255 else
00256 m_textflags &= ~a2dCANOBJTEXT_FRAME;
00257 }
00258
00259
00260 bool a2dText::SetCaret( a2dIterC& ic, double x, double y )
00261 {
00262 a2dIterCU cu( ic, m_lworld );
00263
00264 a2dAffineMatrix inverse;
00265 if ( GetEngineeringText() )
00266 {
00267 inverse = ic.GetTransform() * GetEngineeringTransform( ic );
00268 inverse.Invert();
00269 }
00270 else
00271 inverse = ic.GetInverseTransform();
00272
00273 double xh,yh;
00274 inverse.TransformPoint( x, y, xh, yh );
00275
00276 SetCaretUntransformed( xh, yh );
00277 return true;
00278 }
00279
00280 void a2dText::SetCaretUntransformed( double xh, double yh )
00281 {
00282 m_caret = 0;
00283 int up = GetNextLineDirection() ? 1 : -1;
00284 a2dBoundingBox linebbox;
00285 size_t linestart;
00286 size_t lineend = (size_t) 0;
00287 size_t textlength = m_text.Length();
00288 int line = 0;
00289 wxString text;
00290 while ( lineend <= textlength )
00291 {
00292 linestart = lineend;
00293 while ( lineend < textlength && m_text[lineend] != wxChar('\n') )
00294 lineend++;
00295 text = m_text.Mid( linestart, lineend - linestart );
00296 linebbox = m_font.GetTextExtent( text, UNKNOWN_YAXIS, m_alignment );
00297 linebbox.Translate(0.0, line * up * (GetLineHeight() + m_linespace));
00298 if ( (yh >= linebbox.GetMinY() - m_linespace / 2.0)
00299 && (yh < linebbox.GetMaxY() + m_linespace / 2.0)
00300 || line == 0 && up == 1 && yh < linebbox.GetMaxY() + m_linespace / 2.0
00301 || line == 0 && up == -1 && yh >= linebbox.GetMinY() - m_linespace / 2.0 )
00302 {
00303 if ( !text.IsEmpty() )
00304 {
00305 double oldx, newx;
00306 double kerning = 0.0;
00307 oldx = newx = linebbox.GetMinX();
00308
00309 for( size_t i = 0; i < text.Length(); i++ )
00310 {
00311 newx += m_font.GetWidth( text[i] );
00312 if ( i > 0)
00313 kerning = m_font.GetKerning( text[i-1], text[i] );
00314 newx += kerning / 2.0;
00315
00316 if ( (oldx + newx) / 2.0 > xh)
00317 {
00318 m_caret = linestart + i;
00319 if ( m_caret < m_firsteditable)
00320 m_caret = m_firsteditable;
00321 return;
00322 }
00323
00324 oldx = newx;
00325 newx += kerning / 2.0;
00326 }
00327 }
00328 m_caret = lineend;
00329 break;
00330 }
00331 lineend++;
00332 line++;
00333 }
00334 if ( m_caret < m_firsteditable)
00335 m_caret = m_firsteditable;
00336 }
00337
00338 void a2dText::SetNextLineDirection( bool up )
00339 {
00340 if (up)
00341 m_textflags |= a2dCANOBJTEXT_NEXTLINEUP;
00342 else
00343 m_textflags &= ~a2dCANOBJTEXT_NEXTLINEUP;
00344 m_utbbox_changed = true;
00345 SetPending(true);
00346 }
00347
00348 void a2dText::SetEngineeringText( bool engineering )
00349 {
00350 if ( engineering )
00351 m_textflags |= a2dCANOBJTEXT_ENGINEERING;
00352 else
00353 m_textflags &= ~a2dCANOBJTEXT_ENGINEERING;
00354 m_utbbox_changed = true;
00355 SetPending(true);
00356 }
00357
00358 void a2dText::SetCaretShow( bool visible )
00359 {
00360 if (visible)
00361 m_textflags |= a2dCANOBJTEXT_CARETVISIBLE;
00362 else
00363 m_textflags &= ~a2dCANOBJTEXT_CARETVISIBLE;
00364 m_utbbox_changed = true;
00365 SetPending(true);
00366 }
00367
00368 void a2dText::SetFont( const a2dFont& font, double lineSpaceFactor )
00369 {
00370 m_font = font;
00371 m_linespace = font.GetSize() * lineSpaceFactor;
00372 m_utbbox_changed = true;
00373 SetPending(true);
00374 }
00375
00376 #if wxART2D_USE_CVGIO
00377 void a2dText::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
00378 {
00379 a2dCanvasObject::DoLoad( parent, parser, xmlparts );
00380 m_utbbox_changed = true;
00381 if ( xmlparts == a2dXmlSer_attrib )
00382 {
00383 m_linespace = parser.RequireAttributeValueDouble( wxT("linespace") );
00384 m_text = parser.RequireAttributeValue( wxT("text") );
00385 m_text.Replace( wxT("\\n"), wxT("\n") );
00386 m_textflags = parser.GetAttributeValueInt( wxT("textflags"),
00387 a2dCANOBJTEXT_MULTILINE
00388 | a2dCANOBJTEXT_CARETVISIBLE
00389 | a2dCANOBJTEXT_NEXTLINEUP);
00390 a2dFontInfo fontinfo;
00391 fontinfo.ParseString( parser.RequireAttributeValue( wxT("font")) );
00392 m_font = a2dFont::CreateFont( fontinfo );
00393
00394 wxString alignstring = parser.GetAttributeValue( wxT("alignment"), wxT("wxLEFT|wxTOP|wxBBOX") );
00395 m_alignment = wxCENTRE;
00396 if ( alignstring.Find( wxT("LEFT") ) != -1 )
00397 m_alignment |= wxLEFT;
00398 if ( alignstring.Find( wxT("RIGHT") ) != -1 )
00399 m_alignment |= wxRIGHT;
00400 if ( alignstring.Find( wxT("TOP") ) != -1 )
00401 m_alignment |= wxTOP;
00402 if ( alignstring.Find( wxT("BOTTOM") ) != -1 )
00403 m_alignment |= wxBOTTOM;
00404 if ( alignstring.Find( wxT("BBOX") ) != -1 )
00405 m_alignment |= wxBBOX;
00406
00407 m_firsteditable = parser.GetAttributeValueInt( wxT("firsteditable"), 0 );
00408 }
00409 else
00410 {
00411 }
00412 }
00413
00414 void a2dText::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
00415 {
00416 a2dCanvasObject::DoSave( parent, out, xmlparts, towrite );
00417 if ( xmlparts == a2dXmlSer_attrib )
00418 {
00419 out.WriteAttribute( wxT("linespace"), m_linespace );
00420 out.WriteNewLine();
00421
00422 wxString str = m_text;
00423 str.Replace( wxT("\n"), wxT("\\n") );
00424 out.WriteAttributeEnt( wxT("text"), str );
00425 out.WriteNewLine();
00426 out.WriteAttribute( wxT("textflags"), m_textflags );
00427 out.WriteAttribute( wxT("font"), m_font.CreateString() );
00428 out.WriteNewLine();
00429 out.WriteAttribute( wxT("firsteditable"), m_firsteditable );
00430
00431 wxString alignstring;
00432 if ( (m_alignment & ~wxBBOX) == wxCENTRE )
00433 alignstring += wxT("wxCENTRE|");
00434 else
00435 {
00436 if ( m_alignment & wxLEFT )
00437 alignstring += wxT("wxLEFT|");
00438 if ( m_alignment & wxTOP )
00439 alignstring += wxT("wxTOP|");
00440 if ( m_alignment & wxRIGHT )
00441 alignstring += wxT("wxRIGHT|");
00442 if ( m_alignment & wxBOTTOM )
00443 alignstring += wxT("wxBOTTOM|");
00444 }
00445 if ( m_alignment & wxBBOX )
00446 alignstring += wxT("wxBBOX");
00447 if ( alignstring.Last() == wxChar('|') )
00448 alignstring.RemoveLast();
00449 out.WriteAttribute( wxT("alignment"), alignstring );
00450 }
00451 else
00452 {
00453 }
00454 }
00455 #endif //wxART2D_USE_CVGIO
00456
00457 bool a2dText::DoIsHitWorld( a2dIterC& ic, a2dHitEvent& hitEvent )
00458 {
00459 double pw = ic.GetWorldStrokeExtend();
00460 double margin = ic.GetTransformedHitMargin();
00461
00462 double xmin = m_untransbbox.GetMinX();
00463 double ymin = m_untransbbox.GetMinY();
00464 double xmax = m_untransbbox.GetMaxX();
00465 double ymax = m_untransbbox.GetMaxY();
00466
00467 if ( m_flags.m_editingCopy )
00468 margin += m_pixelExtend;
00469
00470 hitEvent.m_how = HitTestRectangle( hitEvent.m_relx, hitEvent.m_rely, xmin, ymin, xmax, ymax, pw + margin );
00471
00472 if ( hitEvent.m_how.IsHit() )
00473 return hitEvent.m_how.IsHit();
00474 else
00475 return hitEvent.m_how.IsHit();
00476 }
00477
00478
00479 #define SIN100 0.9848077530
00480 #define COS100 -0.1736481776
00481
00482 a2dAffineMatrix a2dText::GetEngineeringTransform( a2dIterC& ic )
00483 {
00484 a2dAffineMatrix mod_affine =ic.GetTransform();
00485 a2dAffineMatrix eng_affine;
00486
00487 if ( eng_affine.GetDeterminant() < 0.0 )
00488 {
00489 eng_affine.Mirror( true, false );
00490 eng_affine.Translate( 0.0, m_untransbbox.GetMinY() + m_untransbbox.GetMaxY() );
00491 mod_affine *= eng_affine;
00492 }
00493
00494
00495
00496
00497 if ( ic.GetDrawer2D()->GetYaxis() && (mod_affine( 0, 0 ) * SIN100 < mod_affine( 0, 1 ) * COS100 )
00498 || !ic.GetDrawer2D()->GetYaxis() && (mod_affine( 0, 0 ) * SIN100 < -mod_affine( 0, 1 ) * COS100 ) )
00499 {
00500 a2dAffineMatrix rot;
00501 rot.Mirror( true, true );
00502 rot.Translate( m_untransbbox.GetMinX() + m_untransbbox.GetMaxX(), m_untransbbox.GetMinY() + m_untransbbox.GetMaxY() );
00503 eng_affine *= rot;
00504 }
00505 return eng_affine;
00506 }
00507
00508 #define BBOX2XYWH(bbox) (bbox).GetMinX(), (bbox).GetMinY(), (bbox).GetWidth(), (bbox).GetHeight()
00509
00510 void a2dText::DoRender( a2dIterC& ic, OVERLAP WXUNUSED(clipparent) )
00511 {
00512 ic.GetDrawer2D()->SetFont(m_font);
00513
00514
00515
00516
00517
00518 if(GetDrawFrame())
00519 ic.GetDrawer2D()->DrawRoundedRectangle(BBOX2XYWH(m_untransbbox), 0);
00520
00521 if ( GetEngineeringText() )
00522 ic.GetDrawer2D()->PushTransform( GetEngineeringTransform( ic ) );
00523
00524
00525 if (ic.GetDrawer2D()->GetDrawStyle() != a2dWIREFRAME_INVERT)
00526 {
00527 if ( !GetDrawFrame() && m_text.Length() == 0 )
00528 ic.GetDrawer2D()->DrawRoundedRectangle(BBOX2XYWH(m_untransbbox), 0);
00529
00530 int up = GetNextLineDirection() ? 1 : -1;
00531 size_t linestart;
00532 size_t lineend = (size_t) 0;
00533 size_t textlength = m_text.Length();
00534 int line = 0;
00535 wxString linetext;
00536 while ( lineend < textlength )
00537 {
00538 linestart = lineend;
00539 while ( lineend < textlength && m_text[lineend] != wxChar('\n') )
00540 lineend++;
00541 linetext = m_text.Mid( linestart, lineend - linestart );
00542
00543 if ((m_selection_start_pos == m_selection_end_pos)
00544 || ( m_selection_start_pos > lineend )
00545 || ( m_selection_end_pos < linestart ) )
00546 {
00547
00548 ic.GetDrawer2D()->DrawText( linetext, 0.0, line * up * (GetLineHeight() + m_linespace), m_alignment, !GetDrawFrame() && GetBackGround() );
00549 }
00550 else if ( m_selection_start_pos < linestart
00551 && m_selection_end_pos > lineend )
00552 {
00553
00554 ic.GetDrawer2D()->OverRuleFixedStyle();
00555 a2dStroke currentstroke = ic.GetDrawer2D()->GetDrawerStroke();
00556 ic.GetDrawer2D()->SetDrawerFill( a2dFill( currentstroke.GetColour() ) );
00557 wxColour col = currentstroke.GetColour();
00558 if (col.Red() + col.Green() + col.Blue() > 3 * 192)
00559 ic.GetDrawer2D()->SetDrawerStroke( *a2dBLACK_STROKE );
00560 else
00561 ic.GetDrawer2D()->SetDrawerStroke( *a2dWHITE_STROKE );
00562 ic.GetDrawer2D()->DrawText( linetext, 0.0, line * up * (GetLineHeight() + m_linespace), m_alignment, true );
00563 ic.GetDrawer2D()->ReStoreFixedStyle();
00564 }
00565 else
00566 {
00567 ic.GetDrawer2D()->OverRuleFixedStyle();
00568
00569 a2dBoundingBox bbox = m_font.GetTextExtent( linetext, ic.GetDrawer2D()->GetYaxis(), m_alignment );
00570 double x = bbox.GetMinX();
00571 double y = bbox.GetMaxY();
00572 double w;
00573
00574 wxString left, sel, right;
00575 if ( m_selection_start_pos > linestart )
00576 {
00577
00578 left = linetext.Left( m_selection_start_pos - linestart );
00579 ic.GetDrawer2D()->DrawText( left, x, y + line * up * (GetLineHeight() + m_linespace), m_alignment, !GetDrawFrame() && GetBackGround() );
00580 m_font.GetTextExtent( left, ic.GetDrawer2D()->GetYaxis(), wxLEFT|wxTOP|wxBBOX, &w );
00581 x += w;
00582 }
00583
00584 if ( m_selection_start_pos >= linestart )
00585 sel = linetext.Mid( m_selection_start_pos - linestart, m_selection_end_pos - m_selection_start_pos );
00586 else
00587 sel = linetext.Mid( 0, m_selection_end_pos - linestart );
00588 ic.GetDrawer2D()->SetDrawStyle( a2dFILLED );
00589 a2dStroke currentstroke = ic.GetDrawer2D()->GetDrawerStroke();
00590 ic.GetDrawer2D()->SetDrawerFill( a2dFill( currentstroke.GetColour() ) );
00591 wxColour col = currentstroke.GetColour();
00592 if (col.Red() + col.Green() + col.Blue() > 3 * 192)
00593 ic.GetDrawer2D()->SetDrawerStroke( *a2dBLACK_STROKE );
00594 else
00595 ic.GetDrawer2D()->SetDrawerStroke( *a2dWHITE_STROKE );
00596 if ( !left.IsEmpty() && ! sel.IsEmpty() )
00597 x += m_font.GetKerning( left.Last(), sel[(size_t) 0] );
00598 ic.GetDrawer2D()->DrawText( sel, x, y + line * up * (GetLineHeight() + m_linespace), m_alignment, true );
00599 m_font.GetTextExtent( sel, ic.GetDrawer2D()->GetYaxis(), wxLEFT|wxTOP|wxBBOX, &w);
00600 x += w;
00601 ic.GetDrawer2D()->ReStoreFixedStyle();
00602 if ( m_selection_end_pos < lineend )
00603 {
00604
00605 right = linetext.Right( lineend - m_selection_end_pos );
00606 if ( !sel.IsEmpty() && !right.IsEmpty() )
00607 x += m_font.GetKerning( sel.Last(), right[(size_t) 0] );
00608 ic.GetDrawer2D()->DrawText( right, x, y + line * up * (GetLineHeight() + m_linespace), m_alignment, !GetDrawFrame() && GetBackGround() );
00609 }
00610 }
00611 lineend++;
00612 line++;
00613 }
00614 }
00615 else
00616 {
00617 a2dSmrtPtr<a2dRect> tmp = new a2dRect(BBOX2XYWH(m_untransbbox));
00618 tmp->SetCanvasDocument(m_root);
00619 tmp->Update( updatemask_force );
00620 tmp->SetFill( *a2dTRANSPARENT_FILL );
00621 tmp->SetStroke( ic.GetDrawer2D()->GetDrawerStroke() );
00622 tmp->Render( ic, _ON );
00623 }
00624
00625
00626
00627 if (ic.GetDrawer2D()->GetDrawStyle() != a2dWIREFRAME_INVERT
00628 && GetCaretShow() && (m_caret != -1)
00629 && (m_selection_start_pos == m_selection_end_pos) )
00630 {
00631 ic.GetDrawer2D()->OverRuleFixedStyle();
00632
00633 a2dStroke tmp = a2dStroke( wxColour(0,0,0), 2 );
00634 ic.GetDrawer2D()->SetDrawerStroke( tmp );
00635 ic.GetDrawer2D()->DrawLine( m_XcaretinLine, m_YcaretinLine,
00636 m_XcaretinLine, m_YcaretinLine + GetLineHeight());
00637 ic.GetDrawer2D()->SetDrawerStroke( *a2dBLACK_STROKE );
00638
00639
00640
00641
00642 ic.GetDrawer2D()->ReStoreFixedStyle();
00643 }
00644
00645 ic.GetDrawer2D()->SetFont( *a2dNullFONT );
00646
00647 if ( m_flags.m_editingCopy )
00648 {
00649 ic.GetDrawer2D()->OverRuleFixedStyle();
00650 a2dSmrtPtr<a2dRect> around = new a2dRect(BBOX2XYWH(m_untransbbox));
00651
00652
00653 a2dStroke strokearound = a2dStroke( wxColour( 192, 192, 192 ) , DRAGRECTWIDTH, a2dSTROKE_CROSSDIAG_HATCH );
00654 strokearound.SetWidth( DRAGRECTWIDTH );
00655 strokearound.SetPixelStroke( true );
00656 around->SetStroke( strokearound );
00657
00658
00659
00660
00661 around->SetFill( *a2dTRANSPARENT_FILL );
00662 around->SetCanvasDocument(m_root);
00663 around->Update( updatemask_force );
00664 around->Render( ic, _ON );
00665 ic.GetDrawer2D()->SetDrawerStroke( *a2dBLACK_STROKE );
00666 ic.GetDrawer2D()->ReStoreFixedStyle();
00667 }
00668
00669
00670 if ( GetEngineeringText() )
00671 ic.GetDrawer2D()->PopTransform();
00672 }
00673
00674 bool a2dText::DoUpdate( UpdateMode mode, const a2dBoundingBox& childbox, const a2dBoundingBox& clipbox, const a2dBoundingBox& propbox )
00675 {
00676 if ( !m_bbox.GetValid() )
00677 {
00678 m_bbox = DoGetUnTransformedBbox();
00679
00680 if( GetCaretShow() )
00681 {
00682 if (m_text.Length() == 0)
00683 {
00684 m_XcaretinLine = m_untransbbox.GetMinX();
00685 m_YcaretinLine = m_untransbbox.GetMinY();
00686 }
00687 else
00688 {
00689 double wcaret = 0.0;
00690 int up = GetNextLineDirection() ? 1 : -1;
00691 size_t linestart;
00692 size_t lineend = (size_t) 0;
00693 size_t textlength = m_text.Length();
00694 int line = 0;
00695 wxString text;
00696 while ( lineend <= textlength )
00697 {
00698 linestart = lineend;
00699 while ( lineend < textlength && m_text[lineend] != wxChar('\n') )
00700 lineend++;
00701
00702 if ( lineend >= m_caret && linestart <= m_caret )
00703 {
00704 a2dBoundingBox linebbox;
00705 text = m_text.Mid( linestart, lineend - linestart );
00706 linebbox = m_font.GetTextExtent( text, UNKNOWN_YAXIS, m_alignment );
00707 linebbox.Translate(0.0, line * up * (GetLineHeight() + m_linespace));
00708
00709
00710 m_font.GetTextExtent(text.Left(m_caret - linestart), UNKNOWN_YAXIS, m_alignment, &wcaret );
00711
00712 if (m_caret - linestart > 1 && (size_t) (m_caret - linestart) <= text.Length())
00713
00714 wcaret += m_font.GetKerning( text[(size_t) (m_caret - linestart - 2)],
00715 text[(size_t) (m_caret - linestart -1 )] ) / 2;
00716 m_XcaretinLine = linebbox.GetMinX() + wcaret;
00717 m_YcaretinLine = linebbox.GetMinY();
00718
00719
00720 break;
00721 }
00722 lineend++;
00723 line++;
00724 }
00725 }
00726 }
00727 else
00728 {
00729 if (m_text.Length() == 0)
00730 {
00731 m_XcaretinLine = m_bbox.GetMinX();
00732 m_YcaretinLine = m_bbox.GetMinY();
00733 }
00734
00735 }
00736 if ( m_flags.m_editingCopy )
00737 {
00738 m_pixelExtend = DRAGRECTWIDTH/2;
00739 }
00740 m_bbox.MapBbox(m_lworld);
00741 return true;
00742 }
00743 return false;
00744 }
00745
00746 a2dBoundingBox a2dText::DoGetUnTransformedBbox( a2dBboxFlags WXUNUSED(flags) ) const
00747 {
00748 if( !m_utbbox_changed && GetCaretShow() )
00749 {
00750 return m_untransbbox;
00751 }
00752
00753 a2dBoundingBox bbox;
00754
00755
00756 if (m_text.Length() == 0)
00757 {
00758 bbox = m_font.GetTextExtent(wxT("|"), UNKNOWN_YAXIS, m_alignment );
00759 }
00760 else
00761 {
00762 double wcaret = 0.0;
00763 int up = GetNextLineDirection() ? 1 : -1;
00764 a2dBoundingBox linebbox;
00765 size_t linestart;
00766 size_t lineend = (size_t) 0;
00767 size_t textlength = m_text.Length();
00768 int line = 0;
00769 wxString text;
00770 while ( lineend <= textlength )
00771 {
00772 linestart = lineend;
00773 while ( lineend < textlength && m_text[lineend] != wxChar('\n') )
00774 lineend++;
00775 text = m_text.Mid( linestart, lineend - linestart );
00776
00777 linebbox = m_font.GetTextExtent( text, UNKNOWN_YAXIS, m_alignment );
00778 linebbox.Translate(0.0, line * up * (GetLineHeight() + m_linespace));
00779 bbox.Expand(linebbox);
00780 lineend++;
00781 line++;
00782 }
00783 }
00784 m_untransbbox = bbox;
00785 m_utbbox_changed = false;
00786 return bbox;
00787 }
00788
00789 bool a2dText::DoStartEdit( wxUint16 editmode, wxEditStyle editstyle )
00790 {
00791 if ( m_flags.m_editable )
00792 {
00793 SetCaretShow( true );
00794 m_caret = m_selection_start_pos = m_selection_end_pos = 0;
00795 a2dText* original = wxStaticCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dText );
00796 if ( editstyle & wxEDITSTYLE_COPY )
00797 original->SetVisible( false );
00798 if ( editmode == 1 )
00799 {
00800 m_flags.m_visiblechilds = true;
00801 m_flags.m_childrenOnSameLayer = true;
00802
00803
00804
00805 Update( updatemask_force );
00806
00807 SetPending( true );
00808 return true;
00809 }
00810 else
00811 {
00812 if ( m_font.GetType() != a2dFONT_WXDC )
00813 {
00814
00815 PROPID_IncludeChildren->SetPropertyToObject( this, false );
00816 PROPID_Allowrotation->SetPropertyToObject( this, true );
00817 PROPID_Allowskew->SetPropertyToObject( this, true );
00818
00819 return a2dCanvasObject::DoStartEdit( editmode, editstyle );
00820 }
00821 else
00822 {
00823 m_flags.m_visiblechilds = true;
00824 m_flags.m_childrenOnSameLayer = true;
00825
00826
00827 a2dBoundingBox untrans = GetUnTransformedBbox( a2dCANOBJ_BBOX_EDIT );
00828 if ( untrans.GetWidth() == 0 || untrans.GetWidth() == 0 )
00829 untrans = GetUnTransformedBbox( a2dCANOBJ_BBOX_CHILDREN | a2dCANOBJ_BBOX_EDIT );
00830
00831 double x,y,w,h;
00832 x = untrans.GetMinX();
00833 y = untrans.GetMinY();
00834 w = untrans.GetWidth();
00835 h = untrans.GetHeight();
00836
00837 int up = GetNextLineDirection() ? 1 : -1;
00838 a2dHandle* handle = NULL;
00839 Append( handle = new a2dHandle( this, 0, up * GetTextHeight(), wxT("__text_fontsize__") ));
00840 handle->SetLayer( m_layer );
00841
00842
00843 a2dSLine* rotline;
00844 if (m_alignment & wxRIGHT)
00845 rotline = new a2dSLine( 0, 0, -w/4, 0 );
00846 else
00847 rotline = new a2dSLine( 0, 0, w/4, 0 );
00848 rotline->SetStroke( *wxRED, 0 );
00849 rotline->SetPreRenderAsChild( false );
00850 rotline->SetSpecificFlags( true, a2dCanvasOFlags::BIN2 );
00851 rotline->SetHitFlags( a2dCANOBJ_EVENT_NON );
00852 rotline->SetLayer( m_layer );
00853 Append( rotline );
00854
00855 if (m_alignment & wxRIGHT)
00856 Append( handle = new a2dHandle( this, -w/4, 0, wxT("__text_rotate__") ));
00857 else
00858 Append( handle = new a2dHandle( this, w/4, 0, wxT("__text_rotate__") ));
00859 handle->SetLayer( m_layer );
00860
00861 m_childobjects->SetSpecificFlags( false, a2dCanvasOFlags::PRERENDERASCHILD, wxT("a2dHandle") );
00862 m_childobjects->SetSpecificFlags( true, a2dCanvasOFlags::BIN2, wxT("a2dHandle") );
00863
00864
00865
00866 Update( updatemask_force );
00867
00868 SetPending( true );
00869 return true;
00870 }
00871 }
00872 }
00873 return false;
00874 }
00875
00876 void a2dText::DoEndEdit()
00877 {
00878 m_caret = -1;
00879 m_selection_start_pos = m_selection_end_pos = 0;
00880 a2dText* original = wxStaticCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dText );
00881
00882 original->m_caret = 0;
00883 original->SetVisible( true );
00884 m_root->GetCommandProcessor()->Submit(new a2dCommand_ChangeText( original, m_text, m_caret, m_font, m_linespace, m_textflags ) );
00885 }
00886
00887 void a2dText::OnChar(wxKeyEvent& event)
00888 {
00889 if ( m_flags.m_editingCopy )
00890 {
00891 a2dText* original = wxStaticCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dText );
00892
00893 bool extend_selection;
00894 bool extend_start;
00895 bool changed = true;
00896 size_t initial_pos = m_caret;
00897
00898 extend_selection = event.ShiftDown();
00899 extend_start = FALSE;
00900
00901 if ( extend_selection )
00902 {
00903 if (m_selection_start_pos == m_selection_end_pos)
00904 {
00905 m_selection_start_pos = m_caret;
00906 m_selection_end_pos = m_caret;
00907 }
00908 extend_start = (m_caret == m_selection_start_pos);
00909 }
00910
00911 size_t textlength = m_text.Length();
00912 switch ( event.GetKeyCode() )
00913 {
00914 case WXK_HOME:
00915 if( event.ControlDown() )
00916
00917 m_caret = m_firsteditable;
00918 else
00919 {
00920
00921 while ( m_caret > m_firsteditable && m_text[ m_caret - 1 ] != wxChar('\n') )
00922 m_caret--;
00923 }
00924 break;
00925 case WXK_END:
00926 if( event.ControlDown() )
00927
00928 m_caret = textlength;
00929 else
00930
00931 while (m_caret < textlength && m_text[ m_caret] != wxChar('\n'))
00932 m_caret++;
00933 break;
00934
00935
00936
00937
00938
00939 case WXK_UP:
00940
00941 {
00942 double up = GetNextLineDirection() ? 1.0 : -1.0;
00943 SetCaretUntransformed( m_XcaretinLine, m_YcaretinLine + GetLineHeight() / 2 - up * ( GetLineHeight() + m_linespace ) );
00944 }
00945 break;
00946 case WXK_DOWN:
00947
00948 {
00949 double up = GetNextLineDirection() ? 1.0 : -1.0;
00950 SetCaretUntransformed( m_XcaretinLine, m_YcaretinLine + GetLineHeight() / 2 + up * ( GetLineHeight() + m_linespace ) );
00951 }
00952 break;
00953 case WXK_LEFT:
00954 if( event.ControlDown() )
00955 {
00956
00957 while (m_caret > m_firsteditable && (m_text[ m_caret - 1] == wxChar('\n')
00958 || m_text[ m_caret - 1] == wxChar(' ')) )
00959 m_caret--;
00960 while ( m_caret > m_firsteditable && m_text[ m_caret - 1 ] != wxChar('\n')
00961 && m_text[ m_caret - 1 ] != wxChar(' ') )
00962 m_caret--;
00963 }
00964 else
00965 {
00966
00967 if ( m_caret > m_firsteditable )
00968 m_caret--;
00969 }
00970 break;
00971 case WXK_RIGHT:
00972 if( event.ControlDown() )
00973 {
00974
00975 while (m_caret < textlength && m_text[m_caret] != wxChar('\n')
00976 && m_text[m_caret] != wxChar(' ') )
00977 m_caret++;
00978 while (m_caret < textlength && (m_text[m_caret] == wxChar('\n'))
00979 || (m_text[m_caret] == wxChar(' ')) )
00980 m_caret++;
00981 }
00982 else
00983
00984 if ( m_caret < textlength )
00985 m_caret++;
00986 break;
00987 case WXK_BACK:
00988 if ( m_selection_start_pos != m_selection_end_pos )
00989 {
00990
00991 extend_selection = FALSE;
00992 m_text = m_text.Left( m_selection_start_pos ) + m_text.Right( textlength - m_selection_end_pos );
00993 m_utbbox_changed = true;
00994 m_caret = m_selection_end_pos = m_selection_start_pos;
00995 }
00996 else if( event.ControlDown() )
00997 {
00998
00999 size_t curpos = m_caret;
01000 while (m_caret > m_firsteditable && (m_text[m_caret - 1] == wxChar('\n')
01001 || m_text[m_caret - 1] == wxChar(' ')) )
01002 m_caret--;
01003 while ( m_caret > m_firsteditable && m_text[ m_caret - 1 ] != wxChar('\n')
01004 && m_text[ m_caret - 1 ] != wxChar(' ') )
01005 m_caret--;
01006 m_text = m_text.Left( m_caret ) + m_text.Right( textlength - curpos );
01007 m_utbbox_changed = true;
01008 }
01009 else if ( m_caret > m_firsteditable )
01010 {
01011
01012 m_text = m_text.Left( m_caret-1 ) + m_text.Right( textlength - m_caret );
01013 m_utbbox_changed = true;
01014 m_caret--;
01015 }
01016 break;
01017 case WXK_CLEAR:
01018 {
01019
01020 while (m_caret < textlength && (m_text[m_caret] != wxChar('\n')) )
01021 m_caret++;
01022 size_t endline = m_caret;
01023 if (m_caret < textlength && (m_text[m_caret] == wxChar('\n')) )
01024 endline++;
01025 while ( m_caret > 0 && m_text[m_caret - 1 ] != wxChar('\n') )
01026 m_caret--;
01027 m_text = m_text.Left( m_caret ) + m_text.Right( textlength - endline );
01028 m_utbbox_changed = true;
01029 }
01030 case WXK_INSERT:
01031 if( event.ShiftDown() )
01032 {
01033
01034 extend_selection = false;
01035 changed = false;
01036 if (wxTheClipboard->Open())
01037 {
01038 if (wxTheClipboard->IsSupported( wxDF_TEXT ))
01039 {
01040 wxTextDataObject data;
01041 wxTheClipboard->GetData( data );
01042 m_text = m_text.Left( m_caret ) + data.GetText() + m_text.Right( textlength - m_caret );
01043 m_utbbox_changed = true;
01044 m_caret += data.GetText().Length();
01045 changed = true;
01046 }
01047 wxTheClipboard->Close();
01048 }
01049 }
01050 else if( event.ControlDown() )
01051 {
01052
01053 if ( m_selection_start_pos != m_selection_end_pos )
01054 {
01055
01056 if (wxTheClipboard->Open())
01057 {
01058 wxTheClipboard->SetData( new wxTextDataObject( m_text.Mid( m_selection_start_pos, m_selection_end_pos - m_selection_start_pos)) );
01059 wxTheClipboard->Close();
01060 }
01061 }
01062 changed = false;
01063 }
01064 else
01065 {
01066 changed = false;
01067
01068 }
01069 break;
01070 case WXK_DELETE:
01071 if ( m_selection_start_pos != m_selection_end_pos )
01072 {
01073 extend_selection = FALSE;
01074 if( event.ShiftDown() )
01075 {
01076
01077 if (wxTheClipboard->Open())
01078 {
01079 wxTheClipboard->SetData( new wxTextDataObject( m_text.Mid( m_selection_start_pos, m_selection_end_pos - m_selection_start_pos)) );
01080 wxTheClipboard->Close();
01081 }
01082 }
01083
01084 m_text = m_text.Left( m_selection_start_pos ) + m_text.Right( textlength - m_selection_end_pos );
01085 m_utbbox_changed = true;
01086 m_caret = m_selection_end_pos = m_selection_start_pos;
01087 }
01088 else if( event.ControlDown() )
01089 {
01090
01091 size_t curpos = m_caret;
01092 while (m_caret < textlength && m_text[m_caret] != wxChar('\n')
01093 && m_text[m_caret] != wxChar(' ') )
01094 m_caret++;
01095 while (m_caret < textlength && (m_text[m_caret] == wxChar('\n'))
01096 || (m_text[m_caret] == wxChar(' ')) )
01097 m_caret++;
01098 m_text = m_text.Left( curpos ) + m_text.Right( textlength - m_caret );
01099 m_utbbox_changed = true;
01100 m_caret = curpos;
01101 }
01102 else if ( m_caret < textlength )
01103 {
01104
01105 m_text = m_text.Left( m_caret ) + m_text.Right( textlength - (m_caret + 1) );
01106 m_utbbox_changed = true;
01107 }
01108 break;
01109 case WXK_TAB:
01110
01111 {
01112 changed = false;
01113 wxUint16* editmode = PROPID_Editmode->GetPropertyValuePtr( this );
01114 if ( editmode )
01115 {
01116 (*editmode)++;
01117 if ( (*editmode) > 1) (*editmode) = 0;
01118 ReStartEdit( (*editmode) );
01119 }
01120 }
01121 break;
01122 case WXK_RETURN:
01123
01124 if ( GetMultiLine() )
01125 {
01126 m_text = m_text.Left( m_caret ) + wxT("\n") + m_text.Right( textlength - m_caret );
01127 m_utbbox_changed = true;
01128 m_caret++;
01129 }
01130 else
01131 {
01132 changed = false;
01133 wxBell();
01134 }
01135 break;
01136 case WXK_ESCAPE:
01137 changed = false;
01138 break;
01139 default:
01140 if( event.ControlDown() )
01141 {
01142 switch( event.GetKeyCode() )
01143 {
01144 case 'A' - '@':
01145
01146 while ( m_caret > m_firsteditable && m_text[m_caret - 1 ] != wxChar('\n') )
01147 m_caret--;
01148 break;
01149 case 'B' - '@':
01150
01151 if ( m_caret > m_firsteditable )
01152 m_caret--;
01153 break;
01154 case 'C' - '@':
01155
01156 if ( m_selection_start_pos != m_selection_end_pos )
01157 {
01158
01159 if (wxTheClipboard->Open())
01160 {
01161 wxTheClipboard->SetData( new wxTextDataObject( m_text.Mid( m_selection_start_pos, m_selection_end_pos - m_selection_start_pos)) );
01162 wxTheClipboard->Close();
01163 }
01164 }
01165 changed = false;
01166 break;
01167 case 'D' - '@':
01168 if ( m_selection_start_pos != m_selection_end_pos )
01169 {
01170
01171 extend_selection = FALSE;
01172 m_text = m_text.Left( m_selection_start_pos ) + m_text.Right( textlength - m_selection_end_pos );
01173 m_utbbox_changed = true;
01174 m_caret = m_selection_end_pos = m_selection_start_pos;
01175 }
01176 else if ( m_caret < textlength )
01177 {
01178
01179 m_text = m_text.Left( m_caret ) + m_text.Right( textlength - (m_caret + 1) );
01180 m_utbbox_changed = true;
01181 }
01182 case 'E' - '@':
01183
01184 while (m_caret < textlength && m_text[m_caret] != wxChar('\n'))
01185 m_caret++;
01186 break;
01187 case 'F' - '@':
01188
01189 if ( m_caret < textlength )
01190 m_caret++;
01191 case 'H' - '@':
01192 if ( m_selection_start_pos != m_selection_end_pos )
01193 {
01194
01195 extend_selection = FALSE;
01196 m_text = m_text.Left( m_selection_start_pos ) + m_text.Right( textlength - m_selection_end_pos );
01197 m_utbbox_changed = true;
01198 m_caret = m_selection_end_pos = m_selection_start_pos;
01199 }
01200 else if ( m_caret > m_firsteditable )
01201 {
01202
01203 m_text = m_text.Left( m_caret-1 ) + m_text.Right( textlength - m_caret );
01204 m_utbbox_changed = true;
01205 m_caret--;
01206 }
01207 break;
01208 case 'K' - '@':
01209 if ( m_selection_start_pos != m_selection_end_pos )
01210 {
01211
01212 extend_selection = FALSE;
01213 m_text = m_text.Left( m_selection_start_pos ) + m_text.Right( textlength - m_selection_end_pos );
01214 m_utbbox_changed = true;
01215 m_caret = m_selection_end_pos = m_selection_start_pos;
01216 }
01217 else
01218 {
01219
01220 size_t curpos = m_caret;
01221 while (m_caret < textlength && (m_text[m_caret] != wxChar('\n')) )
01222 m_caret++;
01223 m_text = m_text.Left( curpos ) + m_text.Right( textlength - m_caret );
01224 m_utbbox_changed = true;
01225 m_caret = curpos;
01226 }
01227 break;
01228 case 'N' - '@':
01229
01230 while (m_caret < textlength && (m_text[m_caret] != wxChar('\n')) )
01231 m_caret++;
01232 if ( m_caret < textlength && m_text[m_caret] == wxChar('\n'))
01233 m_caret++;
01234 break;
01235 case 'P' - '@':
01236
01237 while ( m_caret > m_firsteditable && m_text[m_caret - 1 ] != wxChar('\n') )
01238 m_caret--;
01239 if ( m_caret > m_firsteditable && m_text[ m_caret - 1 ] == wxChar('\n') )
01240 m_caret--;
01241 while ( m_caret > m_firsteditable && m_text[ m_caret - 1 ] != wxChar('\n') )
01242 m_caret--;
01243 break;
01244 case 'U' - '@':
01245 if ( m_selection_start_pos != m_selection_end_pos )
01246 {
01247
01248 extend_selection = FALSE;
01249 m_text = m_text.Left( m_selection_start_pos ) + m_text.Right( textlength - m_selection_end_pos );
01250 m_utbbox_changed = true;
01251 m_caret = m_selection_end_pos = m_selection_start_pos;
01252 }
01253 else
01254 {
01255
01256 while (m_caret < textlength && (m_text[m_caret] != wxChar('\n')) )
01257 m_caret++;
01258 size_t endline = m_caret;
01259 if (m_caret < textlength && (m_text[m_caret] == wxChar('\n')) )
01260 endline++;
01261 while ( m_caret > 0 && m_text[ m_caret - 1 ] != wxChar('\n') )
01262 m_caret--;
01263 m_text = m_text.Left( m_caret ) + m_text.Right( textlength - endline );
01264 m_utbbox_changed = true;
01265 }
01266 break;
01267 case 'V' - '@':
01268
01269 extend_selection = false;
01270 changed = false;
01271 if (wxTheClipboard->Open())
01272 {
01273 if (wxTheClipboard->IsSupported( wxDF_TEXT ))
01274 {
01275 wxTextDataObject data;
01276 wxTheClipboard->GetData( data );
01277 m_text = m_text.Left( m_caret ) + data.GetText() + m_text.Right( textlength - m_caret );
01278 m_utbbox_changed = true;
01279 m_caret += data.GetText().Length();
01280 changed = true;
01281 }
01282 wxTheClipboard->Close();
01283 }
01284 break;
01285 case 'W' - '@':
01286 if ( m_selection_start_pos != m_selection_end_pos )
01287 {
01288
01289 extend_selection = FALSE;
01290 m_text = m_text.Left( m_selection_start_pos ) + m_text.Right( textlength - m_selection_end_pos );
01291 m_utbbox_changed = true;
01292 m_caret = m_selection_end_pos = m_selection_start_pos;
01293 }
01294 else
01295 {
01296
01297 size_t curpos = m_caret;
01298 while (m_caret > m_firsteditable && (m_text[m_caret - 1] == wxChar('\n')
01299 || m_text[m_caret - 1] == wxChar(' ')) )
01300 m_caret--;
01301 while ( m_caret > m_firsteditable && m_text[ m_caret - 1 ] != wxChar('\n')
01302 && m_text[ m_caret - 1 ] != wxChar(' ') )
01303 m_caret--;
01304 m_text = m_text.Left( m_caret ) + m_text.Right( textlength - curpos );
01305 m_utbbox_changed = true;
01306 }
01307 break;
01308 case 'X' - '@':
01309
01310 extend_selection = FALSE;
01311 if ( m_selection_start_pos != m_selection_end_pos )
01312 {
01313 if (wxTheClipboard->Open())
01314 {
01315 wxTheClipboard->SetData( new wxTextDataObject( m_text.Mid( m_selection_start_pos, m_selection_end_pos - m_selection_start_pos)) );
01316 wxTheClipboard->Close();
01317 }
01318 m_text = m_text.Left( m_selection_start_pos ) + m_text.Right( textlength - m_selection_end_pos );
01319 m_utbbox_changed = true;
01320 m_caret = m_selection_end_pos = m_selection_start_pos;
01321 }
01322 else
01323 changed = false;
01324 break;
01325 case WXK_NUMPAD1:
01326 SetAlignment( (m_alignment & wxBBOX) | wxRIGHT | wxBOTTOM );
01327 break;
01328 case WXK_NUMPAD2:
01329 SetAlignment( (m_alignment & wxBBOX) | wxBOTTOM);
01330 break;
01331 case WXK_NUMPAD3:
01332 SetAlignment( (m_alignment & wxBBOX) | wxLEFT | wxBOTTOM);
01333 break;
01334 case WXK_NUMPAD4:
01335 SetAlignment( (m_alignment & wxBBOX) | wxRIGHT);
01336 break;
01337 case WXK_NUMPAD5:
01338 SetAlignment( m_alignment & wxBBOX);
01339 break;
01340 case WXK_NUMPAD6:
01341 SetAlignment( (m_alignment & wxBBOX) | wxLEFT);
01342 break;
01343 case WXK_NUMPAD7:
01344 SetAlignment( (m_alignment & wxBBOX) | wxRIGHT | wxTOP);
01345 break;
01346 case WXK_NUMPAD8:
01347 SetAlignment( (m_alignment & wxBBOX) | wxTOP);
01348 break;
01349 case WXK_NUMPAD9:
01350 SetAlignment( (m_alignment & wxBBOX) | wxLEFT | wxTOP);
01351 break;
01352 case WXK_NUMPAD0:
01353 if (m_alignment & wxBBOX)
01354 SetAlignment( m_alignment & ~wxBBOX );
01355 else
01356 SetAlignment( m_alignment | wxBBOX );
01357 break;
01358 default:
01359 changed = false;
01360 }
01361 break;
01362 }
01363 if( event.AltDown() )
01364 {
01365 switch( event.GetKeyCode() )
01366 {
01367 case 'b': case 'B':
01368
01369 while (m_caret > m_firsteditable && (m_text[m_caret - 1] == wxChar('\n')
01370 || m_text[m_caret - 1] == wxChar(' ')) )
01371 m_caret--;
01372 while ( m_caret > m_firsteditable && m_text[ m_caret - 1 ] != wxChar('\n')
01373 && m_text[ m_caret - 1 ] != wxChar(' ') )
01374 m_caret--;
01375 break;
01376 case 'd': case 'D':
01377 if ( m_selection_start_pos != m_selection_end_pos )
01378 {
01379 extend_selection = FALSE;
01380 if( event.ShiftDown() )
01381 {
01382
01383 if (wxTheClipboard->Open())
01384 {
01385 wxTheClipboard->SetData( new wxTextDataObject( m_text.Mid( m_selection_start_pos, m_selection_end_pos - m_selection_start_pos)) );
01386 wxTheClipboard->Close();
01387 }
01388 }
01389
01390 m_text = m_text.Left( m_selection_start_pos ) + m_text.Right( textlength - m_selection_end_pos );
01391 m_utbbox_changed = true;
01392 m_caret = m_selection_end_pos = m_selection_start_pos;
01393 }
01394 else
01395 {
01396
01397 size_t curpos = m_caret;
01398 while (m_caret < textlength && m_text[m_caret] != wxChar('\n')
01399 && m_text[m_caret] != wxChar(' ') )
01400 m_caret++;
01401 while (m_caret < textlength && (m_text[m_caret] == wxChar('\n'))
01402 || (m_text[m_caret] == wxChar(' ')) )
01403 m_caret++;
01404 m_text = m_text.Left( curpos ) + m_text.Right( textlength - m_caret );
01405 m_utbbox_changed = true;
01406 m_caret = curpos;
01407 }
01408 break;
01409 case 'f': case 'F':
01410
01411 while (m_caret < textlength && m_text[m_caret] != wxChar('\n')
01412 && m_text[m_caret] != wxChar(' ') )
01413 m_caret++;
01414 while (m_caret < textlength && (m_text[m_caret] == wxChar('\n'))
01415 || (m_text[m_caret] == wxChar(' ')) )
01416 m_caret++;
01417 break;
01418 default:
01419 changed = false;
01420 }
01421 break;
01422 }
01423 else
01424 {
01425 extend_selection = false;
01426 if ( m_selection_start_pos != m_selection_end_pos )
01427 {
01428 m_text = m_text.Left( m_selection_start_pos ) + m_text.Right( textlength - m_selection_end_pos );
01429 m_utbbox_changed = true;
01430 m_caret = m_selection_start_pos;
01431 }
01432 wxChar h = event.GetKeyCode();
01433 m_text = m_text.Left( m_caret ) + h + m_text.Right( textlength - m_caret );
01434 m_utbbox_changed = true;
01435 m_caret++;
01436 }
01437 }
01438
01439 if (changed && (m_caret != initial_pos))
01440 {
01441 if (extend_selection)
01442 {
01443 if ( m_selection_start_pos == initial_pos )
01444 {
01445 m_selection_start_pos = m_selection_end_pos;
01446 m_selection_end_pos = initial_pos;
01447 }
01448 if ( m_selection_start_pos > m_caret )
01449 {
01450 m_selection_end_pos = m_selection_start_pos;
01451 m_selection_start_pos = m_caret;
01452 }
01453 else
01454 m_selection_end_pos = m_caret;
01455 }
01456 else
01457 m_selection_start_pos = m_selection_end_pos = m_caret;
01458 }
01459 if ( changed )
01460 {
01461 SetPending( true );
01462
01463
01464
01465 original->SetText( m_text );
01466 original->SetAlignment( m_alignment );
01467 }
01468 }
01469
01470
01471 }
01472
01473 void a2dText::OnCanvasObjectMouseEvent( a2dCanvasObjectMouseEvent& event )
01474 {
01475 a2dIterC* ic = event.GetIterC();
01476
01477 static bool busydrag = false;
01478
01479 if ( m_flags.m_editingCopy )
01480 {
01481
01482 wxMouseEvent mouseevent = event.GetMouseEvent();
01483
01484
01485 double xw,yw;
01486 xw = event.GetX();
01487 yw = event.GetY();
01488
01489 if (mouseevent.LeftDown() )
01490 {
01491 a2dCanvasObject* hitobject;
01492 a2dHitEvent hitevent = a2dHitEvent( xw, yw, false );
01493 hitobject = IsHitWorld( *ic, hitevent );
01494
01495 if ( hitobject && hitevent.m_how.IsStrokeHit() )
01496 {
01497 busydrag = true;
01498 event.Skip();
01499 }
01500 else if ( !mouseevent.ControlDown() )
01501 {
01502 if (hitobject )
01503 {
01504 SetCaret( *ic, xw, yw );
01505 m_selection_start_pos = m_selection_end_pos = m_caret;
01506 SetPending( true );
01507 }
01508 return;
01509 }
01510 }
01511 if (mouseevent.Dragging() )
01512 {
01513 if ( busydrag )
01514 event.Skip();
01515 else if ( mouseevent.LeftIsDown() && !mouseevent.ControlDown() )
01516 {
01517 a2dCanvasObject* hitobject;
01518 a2dHitEvent hitevent = a2dHitEvent( xw, yw, false );
01519 hitobject = IsHitWorld( *ic, hitevent );
01520 if (hitobject )
01521 {
01522 size_t initial_pos = m_caret;
01523 SetCaret( *ic, xw, yw );
01524 if ( m_selection_start_pos == initial_pos )
01525 {
01526 m_selection_start_pos = m_selection_end_pos;
01527 m_selection_end_pos = initial_pos;
01528 }
01529 if ( m_selection_start_pos > m_caret )
01530 {
01531 m_selection_end_pos = m_selection_start_pos;
01532 m_selection_start_pos = m_caret;
01533 }
01534 else
01535 m_selection_end_pos = m_caret;
01536 SetPending( true );
01537 }
01538 return;
01539 }
01540 }
01541 if (mouseevent.LeftUp() && busydrag)
01542 {
01543 busydrag = false;
01544 event.Skip();
01545 }
01546
01547 }
01548
01549 event.Skip();
01550 }
01551
01552 void a2dText::OnHandleEvent(a2dHandleMouseEvent &event)
01553 {
01554 a2dIterC* ic = event.GetIterC();
01555
01556 if ( m_flags.m_editingCopy )
01557 {
01558 a2dRestrictionEngine *restrict = a2dCanvasGlobals->GetRestrictionEngine();
01559 a2dHandle* draghandle = event.GetCanvasHandle();
01560
01561 wxUint16 editmode = PROPID_Editmode->GetPropertyValue( this );
01562 a2dAffineMatrix origworld = m_lworld;
01563
01564 if ( editmode == 0 && m_font.GetType() == a2dFONT_WXDC )
01565 {
01566 double xw,yw;
01567 xw = event.GetX();
01568 yw = event.GetY();
01569
01570 a2dAffineMatrix atWorld = ic->GetTransform();
01571 a2dAffineMatrix inverse = ic->GetInverseTransform();
01572
01573 double xwi;
01574 double ywi;
01575 inverse.TransformPoint( xw, yw, xwi, ywi );
01576
01577 a2dText* original = wxStaticCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dText );
01578
01579 a2dBoundingBox untrans = GetUnTransformedBbox( a2dCANOBJ_BBOX_EDIT );
01580
01581 double xmin,ymin,xmax,ymax,w,h;
01582 xmin = untrans.GetMinX();
01583 ymin = untrans.GetMinY();
01584 xmax = untrans.GetMaxX();
01585 ymax = untrans.GetMaxY();
01586 w = untrans.GetWidth();
01587 h = untrans.GetHeight();
01588
01589 if ( event.GetMouseEvent().LeftDown() )
01590 {
01591 }
01592 else if ( event.GetMouseEvent().LeftUp() )
01593 {
01594 if ( draghandle->GetName() == wxT("__text_fontsize__") )
01595 {
01596 original->SetTextHeight( GetTextHeight() );
01597 original->SetNextLineDirection( GetNextLineDirection() );
01598 }
01599 }
01600 else if ( event.GetMouseEvent().Dragging() )
01601 {
01602 if ( draghandle->GetName() == wxT("__text_fontsize__") )
01603 {
01604 SetTextHeight( fabs(ywi) );
01605 SetNextLineDirection( ywi < 0 );
01606 draghandle->SetPosXY(0, ywi);
01607 }
01608 else if ( draghandle->GetName() == wxT("__text_rotate__") )
01609 {
01610 if(restrict)
01611 restrict->RestrictPoint( xw, yw, a2dRestrictionEngine::snapToPointAngle );
01612
01613 double xr, yr;
01614 m_lworld.TransformPoint( 0,0, xr, yr );
01615
01616
01617 double dx,dy;
01618
01619 dx = xw - xr;
01620 dy = yw - yr;
01621 double angn;
01622 if (!dx && !dy)
01623 angn=0;
01624 else
01625 {
01626 if (m_alignment & wxRIGHT)
01627 angn= wxRadToDeg(atan2(-dy,-dx));
01628 else
01629 angn= wxRadToDeg(atan2(dy,dx));
01630 }
01631 m_lworld = m_lworld.Rotate(angn-m_lworld.GetRotation(), xr, yr );
01632 }
01633 else
01634 event.Skip();
01635 SetPending( true );
01636 }
01637 }
01638 else
01639 {
01640 event.Skip();
01641 }
01642 }
01643 else
01644 {
01645 event.Skip();
01646 }
01647 }
01648
01649 bool a2dText::GeneratePins( a2dPinClass* toConnectTo, a2dConnectTask task, double WXUNUSED(x), double WXUNUSED(y) )
01650 {
01651 a2dPinClass* toCreate;
01652 if ( GetGeneratePins() && (toCreate = toConnectTo->GetPinClassForTask( task, this )) )
01653 {
01654 double xmin = m_untransbbox.GetMinX();
01655 double ymin = m_untransbbox.GetMinY();
01656 double xmax = m_untransbbox.GetMaxX();
01657 double ymax = m_untransbbox.GetMaxY();
01658
01659 double midx = ( m_untransbbox.GetMaxX() + m_untransbbox.GetMinX() ) / 2;
01660 double midy = ( m_untransbbox.GetMaxY() + m_untransbbox.GetMinY() ) / 2;
01661
01662 m_flags.m_visiblechilds = true;
01663 a2dPin *newPin = NULL;
01664 if ( !HasPinNamed( wxT("pinc*"), true) )
01665 {
01666 newPin = AddPin( wxT("pinc"), midx, midy, a2dPin::temporaryObjectPin, toCreate );
01667 newPin->SetInternal( true );
01668 }
01669 if ( !HasPinNamed( wxT("pin1"), true) )
01670 AddPin( wxT("pin1"), xmin, ymin, a2dPin::temporaryObjectPin, toCreate );
01671 if ( !HasPinNamed( wxT("pin2"), true) )
01672 AddPin( wxT("pin2"), midx, ymin, a2dPin::temporaryObjectPin, toCreate );
01673 if ( !HasPinNamed( wxT("pin3"), true) )
01674 AddPin( wxT("pin3"), xmax, ymin, a2dPin::temporaryObjectPin, toCreate );
01675 if ( !HasPinNamed( wxT("pin4"), true) )
01676 AddPin( wxT("pin4"), xmax, midy, a2dPin::temporaryObjectPin, toCreate );
01677 if ( !HasPinNamed( wxT("pin5"), true) )
01678 AddPin( wxT("pin5"), xmax, ymax, a2dPin::temporaryObjectPin, toCreate );
01679 if ( !HasPinNamed( wxT("pin6"), true) )
01680 AddPin( wxT("pin6"), midx, ymax, a2dPin::temporaryObjectPin, toCreate );
01681 if ( !HasPinNamed( wxT("pin7"), true) )
01682 AddPin( wxT("pin7"), xmin, ymax, a2dPin::temporaryObjectPin, toCreate );
01683 if ( !HasPinNamed( wxT("pin8"), true) )
01684 AddPin( wxT("pin8"), xmin, midy, a2dPin::temporaryObjectPin, toCreate );
01685
01686 wxASSERT( HasPins(true) );
01687 m_childobjects->SetSpecificFlags( false, a2dCanvasOFlags::PRERENDERASCHILD, wxT("a2dPin") );
01688
01689 return true;
01690 }
01691 return false;
01692 }
01693
01694 bool a2dText::AdjustPinLocation()
01695 {
01696 if ( !HasPins() )
01697 return false;
01698
01699 DoGetUnTransformedBbox();
01700
01701 const double xmin = m_untransbbox.GetMinX();
01702 const double ymin = m_untransbbox.GetMinY();
01703 const double xmax = m_untransbbox.GetMaxX();
01704 const double ymax = m_untransbbox.GetMaxY();
01705 const double midx = ( m_untransbbox.GetMaxX() + m_untransbbox.GetMinX() ) / 2;
01706 const double midy = ( m_untransbbox.GetMaxY() + m_untransbbox.GetMinY() ) / 2;
01707
01708 a2dPin *pin = NULL;
01709 if ( ( pin = HasPinNamed( wxT("pinc*"), false ) ) != NULL )
01710 pin->SetPosXY( midx, midy );
01711 if ( ( pin = HasPinNamed( wxT("pin1"), false ) ) != NULL )
01712 pin->SetPosXY( xmin, ymin );
01713 if ( ( pin = HasPinNamed( wxT("pin2"), false ) ) != NULL )
01714 pin->SetPosXY( midx, ymin );
01715 if ( ( pin = HasPinNamed( wxT("pin3"), false ) ) != NULL )
01716 pin->SetPosXY( xmax, ymin );
01717 if ( ( pin = HasPinNamed( wxT("pin4"), false ) ) != NULL )
01718 pin->SetPosXY( xmax, midy );
01719 if ( ( pin = HasPinNamed( wxT("pin5"), false ) ) != NULL )
01720 pin->SetPosXY( xmax, ymax );
01721 if ( ( pin = HasPinNamed( wxT("pin6"), false ) ) != NULL )
01722 pin->SetPosXY( midx, ymax );
01723 if ( ( pin = HasPinNamed( wxT("pin7"), false ) ) != NULL )
01724 pin->SetPosXY( xmin, ymax );
01725 if ( ( pin = HasPinNamed( wxT("pin8"), false ) ) != NULL )
01726 pin->SetPosXY( xmin, midy );
01727
01728 return true;
01729 }
01730