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/wfstream.h>
00022 #include <math.h>
00023
00024 #if wxART2D_USE_CANEXTOBJ
00025 #include "wx/canextobj/eval.h"
00026 #endif //wxART2D_USE_CANEXTOBJ
00027
00028 #include "wx/curves/meta.h"
00029
00030 #include "wx/canvas/canobj.h"
00031 #include "wx/canvas/candoc.h"
00032 #include "wx/canvas/drawer.h"
00033 #include "wx/canvas/canvas.h"
00034 #include "wx/canvas/cancom.h"
00035
00036 #if wxART2D_USE_EDITOR
00037 #include "wx/editor/edit.h"
00038 #endif //wxART2D_USE_EDITOR
00039
00040
00041
00042
00043
00044 IMPLEMENT_DYNAMIC_CLASS(a2dTicFormatter, a2dCanvasObject)
00045 IMPLEMENT_DYNAMIC_CLASS(a2dTimeTicFormatter, a2dTicFormatter)
00046 IMPLEMENT_DYNAMIC_CLASS(a2dCurveAxis, a2dCanvasObject)
00047 IMPLEMENT_DYNAMIC_CLASS(a2dCurveAxisLin, a2dCurveAxis)
00048 #if 0
00049 IMPLEMENT_DYNAMIC_CLASS(a2dCurveAxisArea, a2dCurveObject)
00050 #endif
00051
00052
00053
00054
00055
00056 a2dTicFormatter::a2dTicFormatter()
00057 :a2dCanvasObject()
00058 {
00059 m_format = _T("%3.0f");
00060 }
00061
00062 a2dTicFormatter::~a2dTicFormatter()
00063 {
00064 }
00065
00066 a2dTicFormatter::a2dTicFormatter( const a2dTicFormatter& other, CloneOptions options )
00067 :a2dCanvasObject( other, options )
00068 {
00069 m_format = other.m_format;
00070 }
00071
00072 a2dObject* a2dTicFormatter::Clone( CloneOptions options ) const
00073 {
00074 return new a2dTicFormatter( *this, options );
00075 }
00076
00077
00078 wxString a2dTicFormatter::GetTicText(double dTicValue) const
00079 {
00080 wxString strTicText;
00081
00082 strTicText.Printf(m_format, dTicValue);
00083 return strTicText;
00084 }
00085
00086
00087 a2dTimeTicFormatter::a2dTimeTicFormatter()
00088 :a2dTicFormatter()
00089 {
00090 m_format.empty();
00091 }
00092
00093 a2dTimeTicFormatter::~a2dTimeTicFormatter()
00094 {
00095 }
00096
00097 void a2dTimeTicFormatter::SetTicFormat( const wxString& format )
00098 {
00099 wxASSERT_MSG( format.IsEmpty(), wxT("format string not supported") );
00100 }
00101
00102 wxString a2dTimeTicFormatter::GetTicText(double dTicValue)
00103 {
00104 wxString strTicText;
00105 wxString str;
00106 wxChar cSeparator = _T('\0');
00107 int i, nDivisor[] = { 60, 60, 24 };
00108 int i0 = 0;
00109 wxUint32 ulTic = (wxUint32) dTicValue;
00110
00111
00112
00113
00114
00115
00116 i0 = 1, ulTic /= nDivisor[0];
00117
00118 strTicText.empty();
00119
00120 for (i = i0; i < 3; i++) {
00121 str.Printf(_T("%02lu%c"), ulTic % nDivisor[i], cSeparator);
00122 strTicText = str + strTicText;
00123 ulTic /= nDivisor[i];
00124 cSeparator = _T(':');
00125 }
00126
00127 if (ulTic > 0) {
00128 str.Printf(_T("%lu%c"), ulTic, cSeparator);
00129 strTicText = str + strTicText;
00130 }
00131 return strTicText;
00132 }
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 a2dCurveAxis::a2dCurveAxis( double length, bool yaxis )
00146 :a2dCurveObject()
00147 {
00148 m_length = length;
00149 m_yaxis = yaxis;
00150 m_showtics = true;
00151 m_tic = 0;
00152 m_ticheight = 0;
00153 m_stroketic = *a2dBLACK_STROKE;
00154 m_stroketictext = *a2dBLACK_STROKE;
00155 m_strokeunits = *a2dBLACK_STROKE;
00156
00157 SetStroke( *a2dBLACK_STROKE );
00158
00159 m_sidetic = true;
00160 m_inverttic = false;
00161 m_autosizedtic = false;
00162
00163 m_min = 0;
00164 m_max = 1000;
00165 m_ticmin = m_min;
00166 m_ticmax = m_max;
00167 m_position = 0;
00168
00169 m_pTicFormatter = new a2dTicFormatter();
00170 m_pTicFormatter->SetAxis(this);
00171
00172 m_font = a2dFont( 6, wxSWISS, wxITALIC );
00173 }
00174
00175 a2dCurveAxis::~a2dCurveAxis()
00176 {
00177 }
00178
00179 a2dObject* a2dCurveAxis::Clone( CloneOptions options ) const
00180 {
00181 return new a2dCurveAxis( *this, options );
00182 };
00183
00184 a2dCurveAxis::a2dCurveAxis( const a2dCurveAxis &other, CloneOptions options )
00185 :a2dCurveObject( other, options )
00186 {
00187 m_showtics = other.m_showtics;
00188 m_tic = other.m_tic;
00189 m_ticheight = other.m_ticheight;
00190 if( options & clone_members )
00191 {
00192 m_stroketic = other.m_stroketic;
00193 m_stroketictext = other.m_stroketictext;
00194 m_strokeunits = other.m_strokeunits;
00195 m_pTicFormatter = (a2dTicFormatter*) other.m_pTicFormatter->Clone( CloneOptions( options & ~ clone_seteditcopy ) );
00196 m_font = other.m_font;
00197 }
00198 else
00199 {
00200 m_stroketic = other.m_stroketic;
00201 m_stroketictext = other.m_stroketictext;
00202 m_strokeunits = other.m_strokeunits;
00203 m_pTicFormatter = other.m_pTicFormatter;
00204 m_font = other.m_font;
00205 }
00206 m_units = other.m_units;
00207 m_length = other.m_length;
00208 m_min = other.m_min;
00209 m_max = other.m_max;
00210 m_ticmin = other.m_ticmin;
00211 m_ticmax = other.m_ticmax;
00212 m_yaxis = other.m_yaxis;
00213
00214 m_sidetic = other.m_sidetic;
00215 m_inverttic = other.m_inverttic;
00216 m_position = other.m_position;
00217 m_autosizedtic = other.m_autosizedtic;
00218 m_commonTicFormat = other.m_commonTicFormat;
00219
00220 #if defined(_DEBUG) && defined (SMART_POINTER_DEBUG)
00221
00222 CurrentSmartPointerOwner = this;
00223 #endif
00224
00225 }
00226
00227 void a2dCurveAxis::SetBoundaries( double min, double max )
00228 {
00229 if(m_min != min || m_max != max)
00230 {
00231 if ( m_childobjects != wxNullCanvasObjectList )
00232 {
00233 forEachIn( a2dCanvasObjectList, m_childobjects )
00234 {
00235 a2dCanvasObject *obj = *iter;
00236 double curlength = m_length != 0 ? m_length : 1.;
00237 if(m_yaxis)
00238 {
00239 obj->SetPosXY(0,obj->GetPosY()/curlength*(m_max-m_min)+m_min);
00240 double val = obj->GetPosY();
00241 if(val < wxMin(min,max) || val > wxMax(min,max) )
00242 obj->SetVisible(false);
00243 else
00244 obj->SetVisible(true);
00245 obj->SetPosXY(0,(obj->GetPosY()-min)/(max-min)*curlength);
00246 }
00247 else
00248 {
00249 obj->SetPosXY(obj->GetPosX()/curlength*(m_max-m_min)+m_min,0);
00250 double val = obj->GetPosX();
00251 if(val < wxMin(min,max) || val > wxMax(min,max) )
00252 obj->SetVisible(false);
00253 else
00254 obj->SetVisible(true);
00255 obj->SetPosXY((obj->GetPosX()-min)/(max-min)*curlength,0);
00256 }
00257 }
00258 }
00259 if(m_min == m_ticmin && m_max == m_ticmax)
00260 {
00261 m_ticmin = min;
00262 m_ticmax = max;
00263 }
00264 m_min = min;
00265 m_max = max;
00266 SetPending(true);
00267 }
00268 }
00269
00270 void a2dCurveAxis::SetTicBoundaries( double min, double max )
00271 {
00272 if (m_ticmin != min || m_ticmax != max)
00273 {
00274 m_ticmin = min;
00275 m_ticmax = max;
00276 SetPending(true);
00277 }
00278 }
00279
00280 void a2dCurveAxis::SetLength( double length )
00281 {
00282 if (m_length != length)
00283 {
00284 if ( m_childobjects != wxNullCanvasObjectList )
00285 {
00286 forEachIn( a2dCanvasObjectList, m_childobjects )
00287 {
00288 a2dCanvasObject *obj = *iter;
00289 double curlength = m_length != 0 ? m_length : 1.;
00290 double newlength = length != 0 ? length : 1.;
00291 if (m_yaxis)
00292 {
00293 obj->SetPosXY(0,obj->GetPosY()/curlength*(m_max-m_min)+m_min);
00294 obj->SetPosXY(0,(obj->GetPosY()-m_min)/(m_max-m_min)*newlength);
00295 }
00296 else
00297 {
00298 obj->SetPosXY(obj->GetPosX()/curlength*(m_max-m_min)+m_min,0);
00299 obj->SetPosXY((obj->GetPosX()-m_min)/(m_max-m_min)*newlength,0);
00300 }
00301 }
00302 }
00303 m_length = length;
00304 SetPending(true);
00305 }
00306 }
00307
00308 #if wxART2D_USE_CVGIO
00309 void a2dCurveAxis::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
00310 {
00311 a2dCurveObject::DoSave( parent, out, xmlparts, towrite );
00312 if ( xmlparts == a2dXmlSer_attrib )
00313 {
00314 out.WriteAttribute( wxT("min") , m_min );
00315 out.WriteAttribute( wxT("max") , m_max );
00316 out.WriteAttribute( wxT("ticmin") , m_ticmin );
00317 out.WriteAttribute( wxT("ticmax") , m_ticmax );
00318 out.WriteAttribute( wxT("yaxis") , m_yaxis );
00319 out.WriteAttribute( wxT("showtics") , m_showtics );
00320 out.WriteNewLine();
00321 out.WriteAttribute( wxT("font"), m_font.CreateString() );
00322 out.WriteNewLine();
00323
00324 out.WriteAttribute( wxT("tic") , m_tic );
00325 out.WriteAttribute( wxT("ticheight") , m_ticheight );
00326 out.WriteAttribute( wxT("sidetic") , m_sidetic );
00327 out.WriteNewLine();
00328 out.WriteAttribute( wxT("position") , m_position );
00329 out.WriteAttribute( wxT("inverttic") , m_inverttic );
00330 out.WriteAttribute( wxT("autosizedtic") , m_autosizedtic );
00331 out.WriteNewLine();
00332 out.WriteAttribute( wxT("units") , m_units );
00333 out.WriteAttribute( wxT("commonFormat"), m_commonTicFormat);
00334
00335 out.WriteNewLine();
00336 }
00337 else
00338 {
00339 out.WriteStartElement( wxT("derived") );
00340
00341 m_stroketic.Save( this, out, towrite );
00342 m_stroketictext.Save( this, out, towrite );
00343 m_strokeunits.Save( this, out, towrite );
00344
00345 m_pTicFormatter->Save( this, out, towrite);
00346
00347 out.WriteEndElement();
00348 }
00349 }
00350
00351 void a2dCurveAxis::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
00352 {
00353 a2dCurveObject::DoLoad( parent, parser, xmlparts );
00354 if ( xmlparts == a2dXmlSer_attrib )
00355 {
00356 m_min = parser.RequireAttributeValueDouble( wxT("min") );
00357 m_max = parser.RequireAttributeValueDouble( wxT("max") );
00358 m_ticmin = parser.RequireAttributeValueDouble( wxT("ticmin") );
00359 m_ticmax = parser.RequireAttributeValueDouble( wxT("ticmax") );
00360 m_yaxis = parser.RequireAttributeValueBool( wxT("yaxis") );
00361 m_showtics = parser.RequireAttributeValueBool( wxT("showtics") );
00362 a2dFontInfo fontinfo;
00363 fontinfo.ParseString( parser.RequireAttributeValue( wxT("font")) );
00364 m_font = a2dFont::CreateFont( fontinfo );
00365
00366 m_tic = parser.RequireAttributeValueDouble( _T("tic") );
00367 m_ticheight = parser.RequireAttributeValueDouble( wxT("ticheight") );
00368 m_sidetic = parser.RequireAttributeValueBool( wxT("sidetic") );
00369 m_position = parser.GetAttributeValueDouble( wxT("position") );
00370 m_inverttic = parser.GetAttributeValueBool( wxT("inverttic") );
00371 m_autosizedtic = parser.GetAttributeValueBool( wxT("autosizedtic") );
00372
00373 m_units = parser.GetAttributeValue( wxT("units") );
00374 m_commonTicFormat = parser.GetAttributeValue( wxT("commonTicFormat") );
00375 }
00376 else
00377 {
00378 parser.Require( START_TAG, wxT("derived") );
00379 parser.Next();
00380
00381
00382 m_stroketic.UnRef();
00383 m_stroketictext.UnRef();
00384 m_strokeunits.UnRef();
00385
00386 m_stroketic.Load( parent, parser );
00387 parser.ResolveOrAdd( (a2dSmrtPtr<class a2dObject>*) &m_stroketic );
00388 m_stroketictext.Load( parent, parser );
00389 parser.ResolveOrAdd( (a2dSmrtPtr<class a2dObject>*) &m_stroketictext );
00390 m_strokeunits.Load( parent, parser );
00391 parser.ResolveOrAdd( (a2dSmrtPtr<class a2dObject>*) &m_strokeunits );
00392
00393 m_pTicFormatter->Load( parent, parser );
00394 parser.ResolveOrAdd( (a2dSmrtPtr<class a2dObject>*) &m_pTicFormatter );
00395
00396 parser.Require( END_TAG, wxT("derived") );
00397 parser.Next();
00398 }
00399 }
00400 #endif //wxART2D_USE_CVGIO
00401
00402 void a2dCurveAxis::SetTicStroke( const a2dStroke& stroke)
00403 {
00404 m_stroketic = stroke;
00405 SetPending(true);
00406 }
00407
00408 void a2dCurveAxis::SetTicTextStroke( const a2dStroke& stroke)
00409 {
00410 m_stroketictext = stroke;
00411 SetPending(true);
00412 }
00413
00414 void a2dCurveAxis::SetUnitsStroke( const a2dStroke& stroke)
00415 {
00416 m_strokeunits = stroke;
00417 SetPending(true);
00418 }
00419
00420 void a2dCurveAxis::SetUnitsStroke(const wxColour& color, double width, a2dStrokeStyle style )
00421 {
00422 m_strokeunits = a2dStroke( color, width, style );
00423 SetPending(true);
00424 }
00425
00426 void a2dCurveAxis::DoUpdateViewDependentObjects( a2dIterC& ic )
00427 {
00428 a2dCanvasObject::DoUpdateViewDependentObjects( ic );
00429 if(m_autosizedtic)
00430 {
00431 const a2dMatrixProperty * propSpec = PROPID_IntViewDependTransform->GetPropertyListOnly( this );
00432 if ( propSpec )
00433 {
00434 int clientw, clienth;
00435 ic.GetCanvasView()->GetCanvas()->GetClientSize( &clientw, &clienth );
00436
00437 if ( clientw == 0 ) clientw = 10;
00438 if ( clienth == 0 ) clienth = 10;
00439
00440 double w = fabs(ic.GetDrawer2D()->DeviceToWorldXRel(clientw));
00441 double h = fabs(ic.GetDrawer2D()->DeviceToWorldYRel(clienth));
00442 double relw = ic.GetInverseTransform().TransformDistance(w);
00443 double relh = ic.GetInverseTransform().TransformDistance(h);
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462 double worldtic = wxMin(relw,relh)/m_length*15;
00463 double tic = worldtic/m_length*( m_max - m_min );
00464 if(tic > 10) tic = int(tic+0.5);
00465
00466 if(m_tic != tic)
00467 {
00468 m_tic = tic;
00469 SetPending(true);
00470 }
00471 }
00472 }
00473 }
00474
00475 bool a2dCurveAxis::HasLevelMarkers() const
00476 {
00477 a2dCanvasObject* pObject = NULL;
00478 a2dAxisMarker* pMarker = NULL;
00479
00480 const_forEachIn( a2dCanvasObjectList, GetChildObjectList() )
00481 {
00482 pObject = *iter;
00483 pMarker = wxDynamicCast( pObject, a2dAxisMarker);
00484 if (pMarker)
00485 return TRUE;
00486 }
00487 return FALSE;
00488 }
00489
00490 a2dBoundingBox a2dCurveAxis::DoGetUnTransformedBbox( a2dBboxFlags flags ) const
00491 {
00492 a2dBoundingBox bbox;
00493
00494 #if 0
00495
00496
00497
00498 double tictextheight = GetTicTextHeight();
00499 double tictextheightX = tictextheight;
00500 double tictextheightY = tictextheight;
00501
00502 a2dNamedProperty* propSpec = PROPID_intViewDependTransform->GetPropertyListOnly( this );
00503 if ( propSpec )
00504 {
00505 a2dMatrixProperty* propMatrix = wxStaticCast(propSpec, a2dMatrixProperty);
00506 double scalex = propMatrix->GetValue().Get_scaleX();
00507 double scaley = propMatrix->GetValue().Get_scaleY();
00508 tictextheightX = tictextheightX * scalex;
00509 tictextheightY = tictextheightY * scaley;
00510
00511
00512 }
00513 #endif
00514
00515 a2dAffineMatrix internalTransform;
00516 const a2dNamedProperty* propSpec = PROPID_IntViewDependTransform->GetPropertyListOnly( this );
00517 if ( propSpec )
00518 {
00519 a2dMatrixProperty* propMatrix = wxStaticCast(propSpec, a2dMatrixProperty);
00520 internalTransform = propMatrix->GetValue();
00521 }
00522 double length = GetLength();
00523
00524 double sizeticstroke = m_stroketic.GetWidth();
00525 double ticheight = GetTicHeight();
00526 int hasLevels = HasLevelMarkers() ? 1 : 0;
00527
00528 if(!internalTransform.IsIdentity())
00529 {
00530 double scalex = internalTransform.Get_scaleX();
00531 double scaley = internalTransform.Get_scaleY();
00532 if (m_yaxis)
00533 {
00534 length = length / scaley;
00535 sizeticstroke = sizeticstroke / scaley;
00536
00537 }
00538 else
00539 {
00540 length = length / scalex;
00541 sizeticstroke = sizeticstroke / scalex;
00542
00543 }
00544 }
00545
00546 if(m_showtics)
00547 {
00548 wxString ticstr = m_commonTicFormat.IsEmpty() ?
00549 m_pTicFormatter->GetTicText( - wxMax( fabs(m_min),fabs(m_max) ) )
00550 : wxString::Format(m_commonTicFormat.c_str(), - wxMax( fabs(m_min),fabs(m_max) ) );
00551
00552
00553
00554
00555
00556
00557
00558 double xy = 0;
00559 double transX = 0, transY = 0;
00560
00561
00562 a2dBoundingBox bboxtic;
00563 a2dBoundingBox bboxunits;
00564
00565 a2dBoundingBox bboxtext;
00566 a2dBoundingBox bboxline;
00567
00568 if (m_sidetic)
00569 {
00570
00571
00572 double ticsize = ticheight*(1.1 + hasLevels);
00573 double textticpos = ticheight * (1.2 + hasLevels);
00574 if (m_yaxis)
00575 {
00576 bboxtext = m_font.GetTextExtent( ticstr, UNKNOWN_YAXIS, wxCENTER | wxBBOX | (m_inverttic ? wxLEFT : wxRIGHT));
00577 if (m_inverttic)
00578 {
00579 bboxline = a2dBoundingBox( -ticheight, xy, ticsize, xy );
00580 bboxtext.Translate( textticpos, xy );
00581 }
00582 else
00583 {
00584 bboxline = a2dBoundingBox( -ticsize, xy, ticheight, xy );
00585 bboxtext.Translate( -textticpos, xy );
00586 }
00587 transX = 0, transY = length;
00588 }
00589 else
00590 {
00591 bboxtext = m_font.GetTextExtent( ticstr, UNKNOWN_YAXIS, wxCENTER | wxBBOX | (m_inverttic ? wxBOTTOM : wxTOP));
00592 if (m_inverttic)
00593 {
00594 bboxline = a2dBoundingBox( xy, -ticheight, xy, ticsize );
00595 bboxtext.Translate( xy, textticpos );
00596 }
00597 else
00598 {
00599 bboxline = a2dBoundingBox( xy, -ticsize, xy, ticheight );
00600 bboxtext.Translate( xy, -textticpos );
00601 }
00602 transX = length, transY = 0;
00603 }
00604 bboxtic.Expand(bboxline);
00605 bboxtic.Expand(bboxtext);
00606
00607 if (!m_units.IsEmpty())
00608 {
00609 if (m_yaxis)
00610 {
00611 bboxunits = m_font.GetTextExtent( m_units, UNKNOWN_YAXIS, (m_inverttic ? wxLEFT : wxRIGHT ));
00612 if (m_inverttic)
00613 bboxunits.Translate( textticpos, m_max > m_min ? length: 0 );
00614 else
00615 bboxunits.Translate( -textticpos, m_max > m_min ?length : 0 );
00616 }
00617 else
00618 {
00619 bboxunits = m_font.GetTextExtent( m_units, UNKNOWN_YAXIS, (m_inverttic ? wxBOTTOM : wxTOP )|(m_max > m_min ? wxLEFT : wxRIGHT));
00620 if (m_inverttic)
00621 bboxunits.Translate( m_max > m_min ? length : 0, textticpos );
00622 else
00623 bboxunits.Translate( m_max > m_min ? length : 0, -textticpos );
00624 }
00625 }
00626
00627 }
00628 else
00629 {
00630
00631
00632
00633 double ticsize = ticheight*(2 + hasLevels);
00634 double textticpos = ticheight * (0.5+hasLevels);
00635 if (m_yaxis)
00636 {
00637 bboxtext = m_font.GetTextExtent( ticstr, UNKNOWN_YAXIS, wxBOTTOM | wxBBOX | (m_inverttic ? wxLEFT : wxRIGHT));
00638 if (m_inverttic)
00639 {
00640 bboxline = a2dBoundingBox( 0, xy, ticsize, xy );
00641 bboxtext.Translate( textticpos, xy+sizeticstroke);
00642 }
00643 else
00644 {
00645 bboxline = a2dBoundingBox( -ticsize, xy, 0, xy );
00646 bboxtext.Translate( -textticpos, xy+sizeticstroke );
00647 }
00648 transX = 0, transY = length;
00649 if(!m_units.IsEmpty())
00650 transY -= bboxtext.GetHeight();
00651 }
00652 else
00653 {
00654 bboxtext = m_font.GetTextExtent( ticstr, UNKNOWN_YAXIS, wxLEFT | wxBBOX | (m_inverttic ? wxBOTTOM : wxTOP));
00655 if (m_inverttic)
00656 {
00657 bboxline = a2dBoundingBox( xy, ticsize, xy, 0 );
00658 bboxtext.Translate( xy+sizeticstroke, textticpos );
00659 }
00660 else
00661 {
00662 bboxline = a2dBoundingBox( xy, -ticsize, xy, 0 );
00663 bboxtext.Translate( xy+sizeticstroke, -textticpos );
00664 }
00665 transX = length, transY = 0;
00666 if(!m_units.IsEmpty())
00667 transX -= bboxtext.GetWidth();
00668 }
00669 bboxtic.Expand(bboxline);
00670 bboxtic.Expand(bboxtext);
00671
00672 if (!m_units.IsEmpty())
00673 {
00674 if (m_yaxis)
00675 {
00676 bboxunits = m_font.GetTextExtent( m_units, UNKNOWN_YAXIS, wxBOTTOM | (m_inverttic ? wxLEFT : wxRIGHT ));
00677 if (m_inverttic)
00678 bboxunits.Translate( textticpos, (m_max > m_min ? length : 0)+sizeticstroke );
00679 else
00680 bboxunits.Translate( -textticpos, (m_max > m_min ? length : 0)+sizeticstroke );
00681 }
00682 else
00683 {
00684 bboxunits = m_font.GetTextExtent( m_units, UNKNOWN_YAXIS, (m_max > m_min ? wxLEFT : wxRIGHT) | (m_inverttic ? wxBOTTOM : wxTOP ));
00685 if (m_inverttic)
00686 bboxunits.Translate( (m_max > m_min ? length : 0) -sizeticstroke, textticpos );
00687 else
00688 bboxunits.Translate( (m_max > m_min ? length : 0) -sizeticstroke, -textticpos );
00689 }
00690 }
00691
00692 }
00693
00694 m_untransbboxtictext = bboxtext;
00695 bbox.Expand( bboxtic );
00696 bboxtic.Translate( transX, transY );
00697 bbox.Expand( bboxtic );
00698 bbox.Expand( bboxunits );
00699
00700 }
00701 else
00702 {
00703 bbox.Expand(0, 0);
00704 if (m_yaxis)
00705 bbox.Expand(0, length);
00706 else
00707 bbox.Expand(length, 0);
00708 }
00709
00710 if(!internalTransform.IsIdentity())
00711 {
00712 bbox.MapBbox(internalTransform);
00713 }
00714
00715 return bbox;
00716 }
00717
00718 double a2dCurveAxis::ConvertWorld2Axis( double RelativeWorldValue )
00719 {
00720 double curlength = m_length != 0 ? m_length : 1.;
00721 return RelativeWorldValue/curlength * ( m_max - m_min) + m_min;
00722 }
00723
00724 double a2dCurveAxis::ConvertAxis2World( double AxisValue )
00725 {
00726 double curlength = m_length != 0 ? m_length : 1.;
00727 return (AxisValue - m_min)/( m_max - m_min) * curlength;
00728 }
00729
00730 void a2dCurveAxis::AddLevel(const wxString& levelName, double val, a2dCanvasObject* object)
00731 {
00732 if ( !levelName.IsEmpty() )
00733 object->SetName( levelName );
00734 if (m_inverttic)
00735 {
00736 object->Mirror(!m_yaxis,m_yaxis);
00737 a2dBaseMarker *aMarker = wxDynamicCast(object, a2dBaseMarker);
00738 if (aMarker)
00739 {
00740 a2dText *aText = aMarker->GetPrompt();
00741 if (aText)
00742 aText->Mirror();
00743 }
00744 }
00745 Append( object );
00746 a2dBaseMarker* aMarker = wxDynamicCast(object, a2dBaseMarker);
00747 if(aMarker)
00748 aMarker->SetPosition(val);
00749
00750 if (val < wxMin(m_min,m_max) || val > wxMax(m_min, m_max) )
00751 object->SetVisible(false);
00752 else
00753 object->SetVisible(true);
00754 if (m_yaxis)
00755 object->SetPosXY( 0, ConvertAxis2World(val) );
00756 else
00757 object->SetPosXY( ConvertAxis2World(val), 0 );
00758 SetPending(true);
00759 }
00760
00761 a2dCanvasObject *a2dCurveAxis::GetLevel(const wxString& levelName)
00762 {
00763 a2dCanvasObjectList::iterator iter = GetChildObjectList()->begin();
00764 while( iter != GetChildObjectList()->end() )
00765 {
00766 if ( (*iter)->GetName() == levelName )
00767 return (a2dCanvasObject*) (*iter).Get();
00768 ++iter;
00769 }
00770 return NULL;
00771 }
00772
00773 bool a2dCurveAxis::GetLevelValue(const wxString& levelName, double& val )
00774 {
00775 a2dCanvasObjectList::iterator iter = GetChildObjectList()->begin();
00776 while( iter != GetChildObjectList()->end() )
00777 {
00778 if ( (*iter)->GetName() == levelName )
00779 {
00780 a2dCanvasObject* obj = ((a2dCanvasObject*) (*iter).Get());
00781 if (m_yaxis)
00782 val = ConvertWorld2Axis( obj->GetPosY() );
00783 else
00784 val = ConvertWorld2Axis( obj->GetPosX() );
00785 return true;
00786 }
00787 ++iter;
00788 }
00789 return false;
00790 }
00791
00792 void a2dCurveAxis::SetInvertTic(bool inverttic)
00793 {
00794 if(m_inverttic != inverttic)
00795 {
00796 MirrorLevels();
00797 m_inverttic = inverttic;
00798 SetPending(true);
00799 }
00800 }
00801
00802 void a2dCurveAxis::MirrorLevels()
00803 {
00804 if ( GetChildObjectList() != wxNullCanvasObjectList )
00805 {
00806 forEachIn( a2dCanvasObjectList, GetChildObjectList() )
00807 {
00808 a2dCanvasObject *obj = *iter;
00809 obj->Mirror(!m_yaxis,m_yaxis);
00810 a2dBaseMarker* aMarker = wxDynamicCast(obj,a2dBaseMarker);
00811 if (aMarker)
00812 {
00813 a2dText *aPrompt = aMarker->GetPrompt();
00814 if (aPrompt)
00815 aPrompt->Mirror();
00816 }
00817 }
00818 }
00819 }
00820
00821 void a2dCurveAxis::SetFormatter(a2dTicFormatter* pFormatter)
00822 {
00823 m_pTicFormatter = pFormatter;
00824 m_pTicFormatter->SetAxis(this);
00825 SetPending(TRUE);
00826 }
00827
00828 double a2dCurveAxis::GetTicStart() const
00829 {
00830 double tic = GetTic();
00831 double ticstart = floor( m_min / tic + 0.5) * tic;
00832 if ((tic > 0. && ticstart <= m_min) || (tic < 0. && ticstart >= m_min) )
00833 ticstart += tic;
00834 return ticstart;
00835 }
00836
00837
00838
00839
00840
00841
00842
00843 a2dCurveAxisLin::a2dCurveAxisLin( double length, bool yaxis )
00844 :a2dCurveAxis( length, yaxis )
00845 {
00846 }
00847
00848 a2dCurveAxisLin::~a2dCurveAxisLin()
00849 {
00850 }
00851
00852 a2dCurveAxisLin::a2dCurveAxisLin( const a2dCurveAxisLin &other, CloneOptions options )
00853 :a2dCurveAxis( other, options )
00854 {
00855 }
00856
00857 a2dObject* a2dCurveAxisLin::Clone( CloneOptions options ) const
00858 {
00859 return new a2dCurveAxisLin( *this, options );
00860 }
00861
00862 #if wxART2D_USE_CVGIO
00863 void a2dCurveAxisLin::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
00864 {
00865 a2dCurveAxis::DoSave( parent, out, xmlparts, towrite );
00866 if ( xmlparts == a2dXmlSer_attrib )
00867 {
00868 }
00869 else
00870 {
00871 }
00872 }
00873
00874 void a2dCurveAxisLin::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
00875 {
00876 a2dCurveAxis::DoLoad( parent, parser, xmlparts );
00877 if ( xmlparts == a2dXmlSer_attrib )
00878 {
00879 }
00880 else
00881 {
00882 }
00883 }
00884 #endif //wxART2D_USE_CVGIO
00885
00886
00887 #define BBOX2XYWH(bbox) (bbox).GetMinX(), (bbox).GetMinY(), (bbox).GetWidth(), (bbox).GetHeight()
00888
00889 void a2dCurveAxisLin::DoRender( a2dIterC& ic, OVERLAP WXUNUSED(clipparent) )
00890 {
00891 double tic;
00892 double ticheight;
00893 double tictextheight;
00894 double length;
00895 a2dAffineMatrix internalTransform;
00896
00897
00898
00899
00900
00901 double tictextsize = m_yaxis ? m_untransbboxtictext.GetHeight() : m_untransbboxtictext.GetWidth();
00902 tic = GetTic();
00903 ticheight = GetTicHeight();
00904 tictextheight = m_font.GetSize();
00905 length = GetLength();
00906
00907 double sizeticstroke = m_stroketic.GetWidth();
00908
00909 const a2dMatrixProperty * propSpec = PROPID_IntViewDependTransform->GetPropertyListOnly( this );
00910 if ( propSpec )
00911 {
00912 a2dMatrixProperty* propMatrix = wxStaticCast(propSpec, a2dMatrixProperty);
00913 internalTransform = propMatrix->GetValue();
00914 }
00915
00916
00917
00918
00919
00920
00921
00922
00923 double x;
00924
00925 if (m_yaxis)
00926 ic.GetDrawer2D()->DrawLine( 0, 0, 0, m_length );
00927 else
00928 ic.GetDrawer2D()->DrawLine( 0, 0, m_length, 0 );
00929
00930 if (m_showtics)
00931 {
00932 int hasLevels = HasLevelMarkers() ? 1 : 0;
00933
00934
00935
00936 if (!internalTransform.IsIdentity())
00937 {
00938 double scalex = internalTransform.Get_scaleX();
00939 double scaley = internalTransform.Get_scaleY();
00940 if (m_yaxis)
00941 {
00942 length = length / scaley;
00943 sizeticstroke = sizeticstroke / scaley;
00944 }
00945 else
00946 {
00947 length = length / scalex;
00948 sizeticstroke = sizeticstroke / scalex;
00949 }
00950 }
00951 a2dIterCU cu(ic, internalTransform);
00952
00953 double ticstart;
00954 ic.GetDrawer2D()->SetDrawerStroke( m_stroketictext );
00955 ic.GetDrawer2D()->SetDrawerFill(*a2dTRANSPARENT_FILL);
00956
00957 ticstart = floor( m_min / tic + 0.5) * tic;
00958 if ((tic > 0 && ticstart < m_min) || (tic < 0 && ticstart > m_min) )
00959 ticstart += tic;
00960
00961 ic.GetDrawer2D()->SetFont( m_font );
00962 if (m_sidetic)
00963 {
00964
00965 double textticpos = ticheight * (1.2 + hasLevels);
00966 double textmax = m_max;
00967 for ( x = ticstart; (tic > 0 && x <= textmax) || (tic < 0 && x >= textmax); x = x+tic)
00968 {
00969 double dTicValue;
00970 if (m_max != m_ticmax || m_min != m_ticmin)
00971 dTicValue = (x - m_min) / (m_max - m_min) * (m_ticmax - m_ticmin) + m_ticmin;
00972 else
00973 dTicValue = x;
00974
00975 double xy = (x - m_min) / ( m_max - m_min ) * length;
00976
00977 wxString ticstr = m_pTicFormatter->GetTicText(dTicValue);
00978
00979 if (m_yaxis)
00980 {
00981 if (m_inverttic)
00982 ic.GetDrawer2D()->DrawText( ticstr, textticpos, xy, wxLEFT );
00983 else
00984 ic.GetDrawer2D()->DrawText( ticstr, -textticpos, xy, wxRIGHT );
00985 }
00986 else
00987 {
00988 if (m_inverttic)
00989 ic.GetDrawer2D()->DrawText( ticstr, xy, textticpos, wxBOTTOM );
00990 else
00991 ic.GetDrawer2D()->DrawText( ticstr, xy, -textticpos, wxTOP );
00992 }
00993 }
00994 if (!m_units.IsEmpty())
00995 {
00996 ic.GetDrawer2D()->SetDrawerStroke( m_strokeunits );
00997 if (m_yaxis)
00998 {
00999 if (m_inverttic)
01000 ic.GetDrawer2D()->DrawText( m_units, textticpos, m_max > m_min ? length : 0, wxLEFT );
01001 else
01002 ic.GetDrawer2D()->DrawText( m_units, -textticpos, m_max > m_min ? length : 0, wxRIGHT );
01003 }
01004 else
01005 {
01006 if(m_inverttic)
01007 ic.GetDrawer2D()->DrawText( m_units, m_max > m_min ? length : 0, textticpos, wxBOTTOM | (m_max > m_min ? wxLEFT : wxRIGHT) );
01008 else
01009 ic.GetDrawer2D()->DrawText( m_units, m_max > m_min ? length : 0, -textticpos, wxTOP | (m_max > m_min ? wxLEFT : wxRIGHT) );
01010 }
01011 }
01012
01013 ic.GetDrawer2D()->SetDrawerStroke( m_stroketic );
01014
01015
01016 double ticsize = ticheight*(1.1 + hasLevels);
01017 for ( x = ticstart; (tic > 0 && x <= m_max) || (tic < 0 && x >= m_max); x = x+tic)
01018 {
01019 double xy = (x - m_min) / ( m_max - m_min ) * length;
01020 if (m_yaxis)
01021 {
01022 if (m_inverttic)
01023 ic.GetDrawer2D()->DrawLine( -ticheight, xy, ticsize, xy );
01024 else
01025 ic.GetDrawer2D()->DrawLine( -ticsize, xy, ticheight, xy );
01026 }
01027 else
01028 {
01029 if (m_inverttic)
01030 ic.GetDrawer2D()->DrawLine( xy, -ticheight, xy, ticsize );
01031 else
01032 ic.GetDrawer2D()->DrawLine( xy, -ticsize, xy, ticheight );
01033 }
01034 }
01035 }
01036 else
01037 {
01038 double textticpos = ticheight * (0.5+hasLevels);
01039 double textmax = m_max;
01040 double transformedTic = fabs(tic) / fabs( m_max - m_min ) * length;
01041 bool enDrawLastTic = transformedTic > (2*tictextsize + 3*sizeticstroke);
01042
01043 for ( x = ticstart; (tic > 0 && x <= textmax) || (tic < 0 && x >= textmax); x=x+tic)
01044 {
01045 double dTicValue;
01046 if (m_max != m_ticmax || m_min != m_ticmin)
01047 dTicValue = (x - m_min) / (m_max - m_min) * (m_ticmax - m_ticmin) + m_ticmin;
01048 else
01049 dTicValue = x;
01050
01051 double xy = (x - m_min) / ( m_max - m_min ) * length;
01052
01053 wxString ticstr = m_pTicFormatter->GetTicText(dTicValue);
01054
01055 bool notLastTic = fabs(xy - length) > tictextsize;
01056 if (m_yaxis)
01057 {
01058 if (m_units.IsEmpty() || notLastTic)
01059 {
01060 if (m_inverttic)
01061 ic.GetDrawer2D()->DrawText( ticstr, textticpos, xy+sizeticstroke, wxBOTTOM | wxLEFT );
01062 else
01063 ic.GetDrawer2D()->DrawText( ticstr, - textticpos, xy+sizeticstroke, wxBOTTOM | wxRIGHT );
01064 }
01065 else if(enDrawLastTic)
01066 {
01067 if (m_inverttic)
01068 ic.GetDrawer2D()->DrawText( ticstr, textticpos, xy-sizeticstroke, wxTOP | wxLEFT );
01069 else
01070 ic.GetDrawer2D()->DrawText( ticstr, - textticpos, xy-sizeticstroke, wxTOP | wxRIGHT );
01071 }
01072 }
01073 else
01074 {
01075 if(m_units.IsEmpty() || notLastTic)
01076 {
01077 if (m_inverttic)
01078 ic.GetDrawer2D()->DrawText( ticstr, xy+sizeticstroke, textticpos, wxLEFT | wxBOTTOM );
01079 else
01080 ic.GetDrawer2D()->DrawText( ticstr, xy+sizeticstroke, -textticpos, wxLEFT | wxTOP );
01081 }
01082 else if(enDrawLastTic)
01083 {
01084 if (m_inverttic)
01085 ic.GetDrawer2D()->DrawText( ticstr, xy-sizeticstroke, textticpos, wxRIGHT | wxBOTTOM );
01086 else
01087 ic.GetDrawer2D()->DrawText( ticstr, xy-sizeticstroke, -textticpos, wxRIGHT | wxTOP );
01088 }
01089 }
01090 }
01091 if (!m_units.IsEmpty())
01092 {
01093 ic.GetDrawer2D()->SetDrawerStroke( m_strokeunits );
01094 if (m_yaxis)
01095 {
01096 if (m_inverttic)
01097 ic.GetDrawer2D()->DrawText( m_units, textticpos, (m_max > m_min ? length : 0)+sizeticstroke , wxBOTTOM | wxLEFT );
01098 else
01099 ic.GetDrawer2D()->DrawText( m_units, -textticpos, (m_max > m_min ? length : 0)+sizeticstroke , wxBOTTOM | wxRIGHT );
01100 }
01101 else
01102 {
01103 if (m_inverttic)
01104 ic.GetDrawer2D()->DrawText( m_units, (m_max > m_min ? length : 0) - sizeticstroke, textticpos, (m_max > m_min ? wxLEFT : wxRIGHT) | wxBOTTOM );
01105 else
01106 ic.GetDrawer2D()->DrawText( m_units, (m_max > m_min ? length : 0) - sizeticstroke, -textticpos, (m_max > m_min ? wxLEFT : wxRIGHT) | wxTOP );
01107 }
01108 }
01109
01110 ic.GetDrawer2D()->SetDrawerStroke( m_stroketic );
01111
01112
01113 double ticsize = ticheight*(2 + hasLevels);
01114 for ( x = ticstart; (tic > 0 && x <= m_max) || (tic < 0 && x >= m_max); x = x+tic)
01115 {
01116 double xy = (x - m_min) / ( m_max - m_min ) * length;
01117 if (m_yaxis)
01118 {
01119 if (m_inverttic)
01120 ic.GetDrawer2D()->DrawLine( 0, xy, ticsize, xy );
01121 else
01122 ic.GetDrawer2D()->DrawLine( -ticsize, xy, 0, xy );
01123 }
01124 else
01125 {
01126 if (m_inverttic)
01127 ic.GetDrawer2D()->DrawLine( xy, ticsize, xy, 0 );
01128 else
01129 ic.GetDrawer2D()->DrawLine( xy, -ticsize, xy, 0 );
01130 }
01131 }
01132 }
01133 }
01134 }
01135
01136
01137
01138 #if 0
01139
01140
01141
01142
01143 a2dCurveAxisArea::a2dCurveAxisArea()
01144 :a2dCurveObject()
01145 {
01146 }
01147
01148 a2dCurveAxisArea::~a2dCurveAxisArea()
01149 {
01150 }
01151
01152 a2dObject* a2dCurveAxisArea::Clone( CloneOptions options ) const
01153 {
01154 return new a2dCurveAxisArea( *this, options );
01155 }
01156
01157 a2dCurveAxisArea::a2dCurveAxisArea( const a2dCurveAxisArea &other, CloneOptions options )
01158 :a2dCurveObject( other, options )
01159 {
01160 }
01161
01162 a2dCurveAxis* a2dCurveAxisArea::GetAxis( const wxString axisname )
01163 {
01164 a2dCanvasObjectList::iterator iter = GetChildObjectList()->begin();
01165 while( iter != GetChildObjectList()->end() )
01166 {
01167 if ( (*iter)->GetName() == axisname )
01168 return (a2dCurveAxis*) (*iter).Get();
01169 ++iter;
01170 }
01171 return NULL;
01172 }
01173
01174 a2dCurveAxis* a2dCurveAxisArea::GetAxis( int nIndex )
01175 {
01176 a2dCanvasObjectList::iterator iter = GetChildObjectList()->begin();
01177 int i = 0;
01178 while( (i <= nIndex) && (iter != GetChildObjectList()->end()) )
01179 {
01180 if ( i == nIndex )
01181 return (a2dCurveAxis*) (*iter).Get();
01182 ++iter;
01183 }
01184 return NULL;
01185 }
01186
01187 bool a2dCurveAxisArea::DoUpdate( UpdateMode mode, const a2dBoundingBox& childbox, const a2dBoundingBox& clipbox, const a2dBoundingBox& propbox )
01188 {
01189 a2dCurveAxis* pAxis;
01190 bool calc = FALSE;
01191 double dXPos = 0;
01192 double dYPos = 0;
01193 a2dPoint2D point;
01194 a2dBoundingBox bbox;
01195
01196 forEachIn( a2dCanvasObjectList, GetChildObjectList() )
01197 {
01198 a2dCanvasObject* pObject = *iter;
01199 pAxis = wxDynamicCast( pObject, a2dCurveAxis );
01200 if (pAxis) {
01201 point = pAxis->GetPosXY();
01202
01203 pAxis->SetPosXY( dXPos, dYPos );
01204 calc = TRUE;
01205
01206
01207 if (pAxis->IsYAxis())
01208 dXPos -= pAxis->GetBbox().GetWidth();
01209 else
01210 dYPos -= pAxis->GetBbox().GetHeight();
01211 }
01212 }
01213
01214 if ( !m_bbox.GetValid() || calc )
01215 {
01216 m_bbox = DoGetUnTransformedBbox();
01217 m_bbox.MapBbox(m_lworld);
01218
01219 return true;
01220 }
01221
01222 return false;
01223 }
01224
01225 a2dBoundingBox a2dCurveAxisArea::DoGetUnTransformedBbox( a2dBboxFlags flags ) const
01226 {
01227 a2dCurveAxis* pAxis;
01228 a2dBoundingBox bbox;
01229
01230 forEachIn( a2dCanvasObjectList, GetChildObjectList() )
01231 {
01232 a2dCanvasObject* pObject = *iter;
01233 pAxis = wxDynamicCast( pObject, a2dCurveAxis );
01234 if (pAxis)
01235 bbox.Expand( pAxis->GetBbox() );
01236 }
01237
01238 if ( !bbox.GetValid() )
01239 {
01240
01241 bbox.Expand( 0, 0 );
01242 }
01243
01244 return bbox;
01245 }
01246
01247 void a2dCurveAxisArea::DoRender( a2dIterC& ic, OVERLAP clipparent )
01248 {
01249 bool bShowBbox = TRUE;
01250 a2dCurveAxis* pAxis = NULL;
01251
01252 a2dCurveObject::DoRender( ic, clipparent );
01253
01254 if (bShowBbox) {
01255 ic.GetDrawer2D()->SetDrawerStroke( a2dStroke( wxColour(0xff0000), 2, a2dSTROKE_SOLID ) );
01256 ic.GetDrawer2D()->SetDrawerFill( a2dTRANSPARENT_FILL );
01257 forEachIn( a2dCanvasObjectList, GetChildObjectList() )
01258 {
01259 a2dCanvasObject* pObject = *iter;
01260 pAxis = wxDynamicCast( pObject, a2dCurveAxis );
01261 if (pAxis) {
01262 wxRect absareadev = pAxis->GetAbsoluteArea( ic );
01263 ic.GetDrawer2D()->PushIdentityTransform();
01264 ic.GetDrawer2D()->DrawRoundedRectangle( absareadev.x, absareadev.y, absareadev.width, absareadev.height,0);
01265 ic.GetDrawer2D()->PopTransform();
01266 }
01267 }
01268 }
01269 }
01270
01271 void a2dCurveAxisArea::SetLength( double length )
01272 {
01273 a2dCurveAxis* pAxis;
01274
01275 if (m_length != length)
01276 {
01277 forEachIn( a2dCanvasObjectList, GetChildObjectList() )
01278 {
01279 a2dCanvasObject* pObject = *iter;
01280 pAxis = wxDynamicCast( pObject, a2dCurveAxis );
01281 if (pAxis)
01282 pAxis->SetLength( length );
01283 }
01284 m_length = length;
01285 SetPending(true);
01286 }
01287 }
01288 #endif
01289