00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "a2dprec.h"
00013
00014 #ifdef __BORLANDC__
00015 #pragma hdrstop
00016 #endif
00017
00018 #ifndef WX_PRECOMP
00019 #include "wx/wx.h"
00020 #endif
00021
00022 #include "wx/canvas/canobj.h"
00023
00024 #include "wx/canvas/canwidget.h"
00025
00026 #include "wx/canvas/candoc.h"
00027 #include "wx/canvas/cancom.h"
00028 #include "wx/canvas/drawer.h"
00029 #include "wx/canvas/canglob.h"
00030 #include "wx/canvas/algos.h"
00031
00032 IMPLEMENT_CLASS( a2dWidgetButton, a2dWindowMM )
00033 IMPLEMENT_CLASS( a2dWidgetButtonGroup, a2dCanvasObject )
00034 IMPLEMENT_CLASS( a2dWidgetButtonCommand, a2dWidgetButton )
00035
00036 A2D_BEGIN_EVENT_TABLE( a2dWidgetButton, a2dWindowMM )
00037 A2D_EVT_CANVASOBJECT_MOUSE_EVENT( a2dWidgetButton::OnCanvasObjectMouseEvent )
00038 A2D_EVT_CANVASOBJECT_ENTER_EVENT( a2dWidgetButton::OnEnterObject )
00039 A2D_EVT_CANVASOBJECT_LEAVE_EVENT( a2dWidgetButton::OnLeaveObject )
00040 A2D_END_EVENT_TABLE()
00041
00042 a2dWidgetButton::a2dWidgetButton( a2dCanvasObject* parent, int buttonId, double x, double y, double w, double h, WidgetMode mode )
00043 : a2dWindowMM( x, y, w, h )
00044 {
00045 m_parent = parent;
00046 m_selectedStroke = *a2dBLACK_STROKE;
00047 m_selectedFill = *a2dTRANSPARENT_FILL;
00048
00049 m_highLightStroke = *a2dNullSTROKE;
00050 m_highLightFill = *a2dNullFILL;
00051
00052 SetStroke( *a2dTRANSPARENT_STROKE );
00053 SetFill( *a2dTRANSPARENT_FILL );
00054 m_buttonId = buttonId;
00055 m_mode = mode;
00056 m_content = 0;
00057 m_contentBorder = 0.0;
00058 }
00059
00060 a2dWidgetButton::a2dWidgetButton( const a2dWidgetButton& other, CloneOptions options )
00061 : a2dWindowMM( other, options )
00062 {
00063 m_parent = other.m_parent;
00064 m_selectedStroke = other.m_selectedStroke;
00065 m_selectedFill = other.m_selectedFill;
00066 m_highLightStroke = other.m_highLightStroke;
00067 m_highLightFill = other.m_highLightFill;
00068 m_buttonId = other.m_buttonId;
00069 m_mode = other.m_mode;
00070 if ( m_content )
00071 m_content = other.m_content;
00072 m_contentBorder = other.m_contentBorder;
00073 }
00074
00075 a2dObject* a2dWidgetButton::Clone( CloneOptions options ) const
00076 {
00077 return new a2dWidgetButton( *this, options );
00078 };
00079
00080 a2dWidgetButton::~a2dWidgetButton()
00081 {
00082 }
00083
00084 void a2dWidgetButton::DoWalker( wxObject* parent, a2dWalkerIOHandler& handler )
00085 {
00086 handler.WalkTask( parent, this, a2dWalker_a2dDerivedCanvasObjectStart );
00087 a2dCanvasObject::DoWalker( parent, handler );
00088
00089 if ( m_content )
00090 m_content->Walker( this, handler );
00091
00092 handler.WalkTask( parent, this, a2dWalker_a2dDerivedCanvasObjectEnd );
00093 }
00094
00095 void a2dWidgetButton::DrawHighLighted( a2dIterC& ic )
00096 {
00097 if ( !m_highLightStroke.IsNoStroke() )
00098 ic.GetDrawer2D()->SetDrawerStroke( m_highLightStroke );
00099 else
00100 ic.GetDrawer2D()->SetDrawerStroke( a2dCanvasGlobals->GetHighLightStroke() );
00101
00102 if ( !m_highLightFill.IsNoFill() )
00103 ic.GetDrawer2D()->SetDrawerFill( m_highLightFill );
00104 else
00105 ic.GetDrawer2D()->SetDrawerFill( a2dCanvasGlobals->GetHighLightFill() );
00106
00107 a2dStroke m_shadowStroke = a2dStroke( *wxBLACK, 0, a2dSTROKE_SOLID );
00108 a2dStroke m_lightStroke = a2dStroke( *wxWHITE, 0, a2dSTROKE_SOLID );
00109
00110 double x1 = m_bbox.GetMinX();
00111 double x2 = m_bbox.GetMaxX();
00112 double y1 = m_bbox.GetMinY();
00113 double y2 = m_bbox.GetMaxY();
00114 ic.GetDrawer2D()->SetDrawerStroke( m_shadowStroke );
00115 ic.GetDrawer2D()->DrawLine( x1, y1, x1, y2 );
00116 ic.GetDrawer2D()->DrawLine( x1, y2, x2, y2 );
00117 ic.GetDrawer2D()->SetDrawerStroke( m_lightStroke );
00118 ic.GetDrawer2D()->DrawLine( x2, y1, x2, y2 );
00119 ic.GetDrawer2D()->DrawLine( x2, y1, x1, y1 );
00120
00121
00122
00123
00124
00125
00126
00127
00128 }
00129
00130
00131 void a2dWidgetButton::Render( a2dIterC& ic, OVERLAP clipparent )
00132 {
00133
00134 if( ic.GetDrawStyle() != RenderWIREFRAME_SELECT && ic.GetDrawStyle() != RenderWIREFRAME_SELECT_INVERT )
00135 a2dWindowMM::Render( ic, clipparent );
00136 }
00137
00138 bool a2dWidgetButton::DoUpdate( UpdateMode mode, const a2dBoundingBox& childbox, const a2dBoundingBox& clipbox, const a2dBoundingBox& propbox )
00139 {
00140 if ( !m_bbox.GetValid())
00141 {
00142 m_bbox = DoGetUnTransformedBbox();
00143 switch( m_mode )
00144 {
00145 case Boundingbox:
00146 m_contentWorld.Identity();
00147 break;
00148
00149 case BoundingboxSize:
00150 if ( m_content )
00151 {
00152 a2dBoundingBox tbbox;
00153 tbbox.Expand( m_content->GetCalculatedBoundingBox(INT_MAX) );
00154 double xshift = -tbbox.GetMinX();
00155 double yshift = -tbbox.GetMinY();
00156 m_contentWorld = a2dAffineMatrix( xshift, yshift );
00157 }
00158 break;
00159
00160 case ScaledContent:
00161 case ScaledContentKeepAspect:
00162 if ( m_content )
00163 {
00164 a2dBoundingBox tbbox;
00165 tbbox.Expand( m_content->GetCalculatedBoundingBox(INT_MAX) );
00166
00167
00168
00169 double
00170 scaleX = tbbox.GetWidth() ? ( m_maxx - m_minx - 2*m_contentBorder ) / tbbox.GetWidth() : 0,
00171 scaleY = tbbox.GetHeight() ? ( m_maxy - m_miny - 2*m_contentBorder ) / tbbox.GetHeight() : 0;
00172
00173 if( m_mode==ScaledContentKeepAspect )
00174 {
00175 if( scaleX && fabs( scaleX ) < fabs( scaleY ) )
00176 scaleY = scaleX;
00177 else if( scaleY && fabs( scaleY ) < fabs( scaleX ) )
00178 scaleX = scaleY;
00179 }
00180
00181 m_contentWorld = a2dAffineMatrix(
00182 0.5 * (m_maxx - m_minx) - 0.5*scaleX*( tbbox.GetMinX() + tbbox.GetMaxX() ),
00183 0.5 * (m_maxy - m_miny) - 0.5*scaleY*( tbbox.GetMinY() + tbbox.GetMaxY() ),
00184 scaleX,
00185 scaleY
00186 );
00187 }
00188
00189 break;
00190 default:
00191 break;
00192 }
00193 m_bbox.MapBbox(m_lworld);
00194 return true;
00195 }
00196 return false;
00197 }
00198
00199 a2dBoundingBox a2dWidgetButton::DoGetUnTransformedBbox( a2dBboxFlags WXUNUSED(flags) ) const
00200 {
00201 a2dBoundingBox bbox;
00202 switch( m_mode )
00203 {
00204 case Boundingbox:
00205 if ( m_content )
00206 {
00207 a2dBoundingBox tbbox;
00208 tbbox.Expand( m_content->GetCalculatedBoundingBox(INT_MAX) );
00209 bbox.Expand( tbbox );
00210 }
00211
00212 bbox.Expand( 0, 0);
00213 bbox.Expand( m_maxx - m_minx , m_maxy - m_miny );
00214 break;
00215
00216 case BoundingboxSize:
00217 if ( m_content )
00218 {
00219 a2dBoundingBox tbbox;
00220 tbbox.Expand( m_content->GetCalculatedBoundingBox(INT_MAX) );
00221 double xshift = -tbbox.GetMinX();
00222 double yshift = -tbbox.GetMinY();
00223
00224 tbbox.Translate( xshift, yshift );
00225 bbox.Expand( tbbox );
00226 }
00227
00228 bbox.Expand( 0, 0);
00229 bbox.Expand( m_maxx - m_minx , m_maxy - m_miny );
00230 bbox.Enlarge( m_contentBorder );
00231 break;
00232
00233 case ScaledContent:
00234 case ScaledContentKeepAspect:
00235
00236 bbox.Expand( 0, 0);
00237 bbox.Expand( m_maxx - m_minx , m_maxy - m_miny );
00238 break;
00239
00240 default:
00241 break;
00242 }
00243 return bbox;
00244 }
00245
00246 void a2dWidgetButton::DoRender( a2dIterC& ic, OVERLAP clipparent )
00247 {
00248 a2dWindowMM::DoRender( ic, clipparent );
00249
00250 if ( m_content )
00251 {
00252 bool old = m_content->GetChildrenOnSameLayer();
00253 a2dAffineMatrix oldMatrix = ic.GetDrawer2D()->GetTransform();
00254
00255 m_content->SetChildrenOnSameLayer(true);
00256
00257 a2dIterCU cu( ic, m_contentWorld );
00258 m_content->Render( ic, clipparent );
00259
00260 m_content->SetChildrenOnSameLayer(old);
00261 ic.GetDrawer2D()->SetTransform(oldMatrix);
00262 }
00263
00264 if(IsSelected())
00265 {
00266 if( !m_selectedFill.IsNoFill() )
00267 ic.GetDrawer2D()->SetDrawerFill( m_selectedFill );
00268 if( !m_selectedStroke.IsNoStroke() )
00269 ic.GetDrawer2D()->SetDrawerStroke( m_selectedStroke );
00270
00271
00272 a2dBoundingBox bbox = DoGetUnTransformedBbox();
00273 ic.GetDrawer2D()->DrawRoundedRectangle( bbox.GetMinX(), bbox.GetMinY(), bbox.GetWidth(), bbox.GetHeight(), 0 );
00274 }
00275 }
00276
00277 void a2dWidgetButton::OnEnterObject(a2dCanvasObjectMouseEvent &event)
00278 {
00279 m_flags.m_HighLight = true;
00280 SetPending( true );
00281 event.Skip();
00282 }
00283
00284 void a2dWidgetButton::OnLeaveObject(a2dCanvasObjectMouseEvent &event)
00285 {
00286 m_flags.m_HighLight = false;
00287 SetPending( true );
00288 event.Skip();
00289 }
00290
00291 void a2dWidgetButton::OnCanvasObjectMouseEvent( a2dCanvasObjectMouseEvent& event )
00292 {
00293 if ( event.GetMouseEvent().Moving() )
00294 {
00295 event.Skip();
00296
00297 }
00298 else if ( event.GetMouseEvent().LeftDown() )
00299 {
00300 wxCommandEvent commandEvent(wxEVT_COMMAND_BUTTON_CLICKED, m_buttonId);
00301 commandEvent.SetEventObject(this);
00302 GetEventHandler()->ProcessEvent( commandEvent );
00303 }
00304 else if ( event.GetMouseEvent().LeftUp() )
00305 {
00306 }
00307 else
00308 {
00309 event.Skip();
00310 }
00311 }
00312
00313 bool a2dWidgetButton::DoIsHitWorld( a2dIterC& ic, a2dHitEvent& hitEvent )
00314 {
00315 if ( m_content )
00316 {
00317 a2dIterCU cu( ic, m_contentWorld );
00318 if ( m_content->IsHitWorld( ic, hitEvent ) != 0 )
00319 return true;
00320 }
00321
00322 double margin = ic.GetTransformedHitMargin();
00323
00324 hitEvent.m_how = HitTestRectangle( hitEvent.m_relx, hitEvent.m_rely, m_minx, m_miny, m_maxx, m_maxy, ic.GetTransformedHitMargin() + margin );
00325
00326 return hitEvent.m_how.IsHit();
00327 }
00328
00329
00330 A2D_BEGIN_EVENT_TABLE( a2dWidgetButtonGroup, a2dCanvasObject )
00331 A2D_EVT_BUTTON_ANY( a2dWidgetButtonGroup::OnAnyButton )
00332 A2D_END_EVENT_TABLE()
00333
00334 a2dWidgetButtonGroup::a2dWidgetButtonGroup( a2dCanvasObject* WXUNUSED(parent), double x, double y, float extra )
00335 :a2dCanvasObject( x, y )
00336 {
00337 m_worldExtend = extra;
00338 m_singleSelect = true;
00339 }
00340
00341 a2dWidgetButtonGroup::~a2dWidgetButtonGroup()
00342 {
00343 }
00344
00345 void a2dWidgetButtonGroup::DoRender( a2dIterC& ic, OVERLAP WXUNUSED(clipparent) )
00346 {
00347 a2dAffineMatrix invlworld= m_lworld;
00348 invlworld.Invert();
00349
00350 a2dAffineMatrix oldMatrix = ic.GetDrawer2D()->GetTransform();
00351 a2dIterCU cu( ic, invlworld );
00352 ic.GetDrawer2D()->DrawRoundedRectangle( m_bbox.GetMinX(), m_bbox.GetMinY(), m_bbox.GetWidth(), m_bbox.GetHeight() ,0 );
00353 ic.GetDrawer2D()->SetTransform(oldMatrix);
00354 }
00355
00356 void a2dWidgetButtonGroup::OnAnyButton(wxCommandEvent &event)
00357 {
00358 a2dCanvasObject* hit = wxStaticCast(event.GetEventObject(), a2dCanvasObject);
00359
00360 if( m_singleSelect )
00361 {
00362 a2dWalker_SetSpecificFlagsCanvasObjects setflags( a2dCanvasOFlags::PENDING, a2dCanvasOFlags::SELECTED );
00363 setflags.Start( m_root->GetRootObject(), true );
00364 a2dWalker_SetSpecificFlagsCanvasObjects setflags2( a2dCanvasOFlags::SELECTED );
00365 setflags2.Start( m_root->GetRootObject(), false );
00366
00367 hit->SetSelected( true );
00368 }
00369 else
00370 {
00371 if ( hit->IsSelected() )
00372 hit->SetSelected( false );
00373 else
00374 hit->SetSelected( true );
00375 }
00376
00377 hit->SetPending( true );
00378
00379 if( hit->IsSelected() )
00380 {
00381
00382 a2dWidgetButton* hitButton = wxDynamicCast(event.GetEventObject(), a2dWidgetButton);
00383 int buttonId = hitButton ? hitButton->GetButtonId() : 0;
00384
00385 wxCommandEvent commandEvent(wxEVT_COMMAND_CHOICE_SELECTED, buttonId);
00386 commandEvent.SetEventObject(hit);
00387 hit->GetEventHandler()->ProcessEvent( commandEvent );
00388 }
00389
00390 event.Skip();
00391 }
00392
00393
00394 A2D_BEGIN_EVENT_TABLE( a2dWidgetButtonCommand, a2dWidgetButton )
00395 A2D_EVT_CHOICE_ANY( a2dWidgetButtonCommand::OnAnyChoice )
00396 A2D_END_EVENT_TABLE()
00397
00398 a2dWidgetButtonCommand::a2dWidgetButtonCommand( a2dCanvasObject* parent, int buttonId, double x, double y, double w, double h, WidgetMode mode )
00399 :a2dWidgetButton( parent, buttonId, x, y, w, h, mode )
00400 {
00401 m_docviewCommand = 0;
00402 m_event = 0;
00403 m_clientData = 0;
00404 }
00405
00406 a2dWidgetButtonCommand::~a2dWidgetButtonCommand()
00407 {
00408 if( m_docviewCommand )
00409 delete m_docviewCommand;
00410 if( m_event )
00411 delete m_event;
00412 if( m_clientData )
00413 delete m_clientData;
00414 }
00415
00416 void a2dWidgetButtonCommand::SetCanvasCommand( class a2dCommand *command) {
00417 if(m_docviewCommand)
00418 delete m_docviewCommand;
00419
00420 m_docviewCommand = command;
00421 }
00422
00423 void a2dWidgetButtonCommand::SetEvent( wxEvent *event )
00424 {
00425 if(m_event)
00426 delete m_event;
00427
00428 m_event = event;
00429 }
00430
00431 void a2dWidgetButtonCommand::OnAnyChoice(wxCommandEvent &event)
00432 {
00433 if( event.GetEventObject() == this )
00434 {
00435 if( m_docviewCommand )
00436 {
00437 assert(0);
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465 }
00466
00467 if( m_event )
00468 {
00469 wxMDIParentFrame *mdiFrame = wxDynamicCast(wxTheApp->GetTopWindow(), wxMDIParentFrame);
00470
00471 if ( mdiFrame && mdiFrame->GetActiveChild() )
00472 mdiFrame->GetActiveChild()->GetEventHandler()->ProcessEvent( *m_event );
00473 else
00474 wxTheApp->GetTopWindow()->GetEventHandler()->ProcessEvent( *m_event );
00475 }
00476 }
00477
00478 event.Skip();
00479 }