Go to the documentation of this file.00001
00002 #include "vgui_wx_adaptor.h"
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "vgui_wx_menu.h"
00012 #include <vgui/vgui_macro.h>
00013 #include <vgui/vgui_popup_params.h>
00014
00015 #include <wx/log.h>
00016
00017 #include <wx/menu.h>
00018 #include <wx/timer.h>
00019 #include <wx/dcclient.h>
00020
00021 #ifndef wxEventHandler // wxWidgets-2.5.3 doesn't define this
00022 #define wxEventHandler(func) \
00023 (wxObjectEventFunction)wxStaticCastEvent(wxEventFunction, &func)
00024 #endif
00025
00026 #include <vcl_cassert.h>
00027 #include <vcl_iostream.h>
00028
00029
00030
00031
00032
00033 namespace
00034 {
00035
00036 const wxEventType wxEVT_VGUI_TIMER = wxNewEventType();
00037
00038 inline bool is_modifier(int key_code);
00039 inline vgui_modifier get_modifiers(const wxMouseEvent& e);
00040 inline vgui_modifier get_modifiers(const wxKeyEvent& e);
00041 inline vgui_event_type translate_mouse_event_type(const wxMouseEvent& e);
00042 inline vgui_button translate_mouse_button(int button);
00043 inline vgui_key translate_key(int key_code);
00044 }
00045
00046
00047
00048
00049 IMPLEMENT_CLASS(vgui_wx_adaptor, wxGLCanvas)
00050
00051
00052 vgui_menu vgui_wx_adaptor::last_popup_;
00053
00054
00055 vgui_wx_adaptor::vgui_wx_adaptor(wxWindow* parent,
00056 wxWindowID id,
00057 const wxPoint& pos,
00058 const wxSize& size,
00059 long style,
00060 const wxString& name,
00061 int* attributes)
00062 : wxGLCanvas(parent, id, pos, size,
00063 style|wxFULL_REPAINT_ON_RESIZE|wxBORDER_SUNKEN, name, attributes)
00064 , view_(0)
00065 , redraw_posted_(true)
00066 , overlay_redraw_posted_(true)
00067 , idle_request_posted_(false)
00068 , destroy_posted_(false)
00069 {
00070 wxLogTrace(wxTRACE_RefCount, wxT("vgui_wx_adaptor::vgui_wx_adaptor"));
00071 }
00072
00073
00074 vgui_wx_adaptor::~vgui_wx_adaptor()
00075 {
00076 wxLogTrace(wxTRACE_RefCount, wxT("vgui_wx_adaptor::~vgui_wx_adaptor"));
00077 }
00078
00079
00080
00081
00082
00083 void vgui_wx_adaptor::post_redraw(void)
00084 {
00085 if (!redraw_posted_)
00086 {
00087 redraw_posted_ = true;
00088 invalidate_canvas();
00089 }
00090 }
00091
00092
00093 void vgui_wx_adaptor::post_overlay_redraw(void)
00094 {
00095 if (!overlay_redraw_posted_)
00096 {
00097 overlay_redraw_posted_ = true;
00098 invalidate_canvas();
00099 }
00100 }
00101
00102
00103 void vgui_wx_adaptor::post_idle_request(void)
00104 {
00105 if (!idle_request_posted_)
00106 {
00107 idle_request_posted_ = true;
00108 wxWakeUpIdle();
00109 }
00110 }
00111
00112
00113
00114 void vgui_wx_adaptor::post_message(char const *, void const *)
00115 {
00116 assert(false);
00117 }
00118
00119
00120 void vgui_wx_adaptor::post_destroy(void)
00121 {
00122
00123 redraw_posted_ = false;
00124 overlay_redraw_posted_ = false;
00125
00126 vgui_macro_report_errors;
00127
00128 if (!destroy_posted_)
00129 {
00130 destroy_posted_ = true;
00131 Close();
00132 }
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 vgui_macro_report_errors;
00146 }
00147
00148
00149 void vgui_wx_adaptor::post_timer(float timeout, int id)
00150 {
00151 Connect(id, wxEVT_VGUI_TIMER, wxEventHandler(vgui_wx_adaptor::on_timer));
00152 }
00153
00154
00155 void vgui_wx_adaptor::kill_timer(int id)
00156 {
00157 Disconnect(id, wxEVT_VGUI_TIMER);
00158 }
00159
00160
00161 void vgui_wx_adaptor::swap_buffers()
00162 {
00163 SwapBuffers();
00164 }
00165
00166
00167 void vgui_wx_adaptor::make_current()
00168 {
00169 SetCurrent();
00170 }
00171
00172
00173
00174
00175 BEGIN_EVENT_TABLE(vgui_wx_adaptor, wxGLCanvas)
00176 EVT_SIZE(vgui_wx_adaptor::on_size)
00177 EVT_PAINT(vgui_wx_adaptor::on_paint)
00178 EVT_ERASE_BACKGROUND(vgui_wx_adaptor::on_erase_background)
00179 EVT_KEY_DOWN(vgui_wx_adaptor::on_key_down)
00180 EVT_KEY_UP(vgui_wx_adaptor::on_key_up)
00181 EVT_CHAR(vgui_wx_adaptor::on_char)
00182 EVT_MOUSE_EVENTS(vgui_wx_adaptor::on_mouse_event)
00183 EVT_IDLE(vgui_wx_adaptor::on_idle)
00184 EVT_CLOSE(vgui_wx_adaptor::on_close)
00185 END_EVENT_TABLE()
00186
00187
00188 void vgui_wx_adaptor::on_size(wxSizeEvent& event)
00189 {
00190 wxGLCanvas::OnSize(event);
00191 dispatch_to_tableau(vgui_RESHAPE);
00192 post_redraw();
00193 Update();
00194 }
00195
00196
00197 void vgui_wx_adaptor::on_paint(wxPaintEvent& WXUNUSED(event))
00198 {
00199 vgui_macro_report_errors;
00200
00201 wxPaintDC dc(this);
00202
00203 #ifndef __WXMOTIF__
00204 if (!GetContext()) { return; }
00205 #endif
00206
00207 SetCurrent();
00208
00209 if (redraw_posted_ || overlay_redraw_posted_)
00210 {
00211 dispatch_to_tableau(vgui_DRAW);
00212 redraw_posted_ = false;
00213 }
00214
00215 if (overlay_redraw_posted_)
00216 {
00217 dispatch_to_tableau(vgui_DRAW_OVERLAY);
00218 overlay_redraw_posted_ = false;
00219 }
00220
00221 SwapBuffers();
00222 vgui_macro_report_errors;
00223 }
00224
00225
00226 void vgui_wx_adaptor::on_erase_background(wxEraseEvent& WXUNUSED(event))
00227 {
00228 vgui_macro_report_errors;
00229
00230 }
00231
00232
00233 void vgui_wx_adaptor::on_key(vgui_event& ve, wxKeyEvent& event)
00234 {
00235 ve.origin = this;
00236
00237 ve.ascii_char = translate_key(event.GetKeyCode());
00238 ve.modifier = get_modifiers(event);
00239
00240
00241
00242 if (0 < ve.ascii_char && ve.ascii_char < 27 && ve.modifier_is_down(vgui_CTRL))
00243 {
00244 ve.key = static_cast<vgui_key>(ve.ascii_char + 'a' - 1);
00245 }
00246 else { ve.set_key(ve.ascii_char); }
00247
00248 #if 0
00249 if (ve.type == vgui_KEY_PRESS)
00250 {
00251 vcl_cout << "key (wx, vgui): " << ve.key << '\t' << ve.ascii_char
00252 << '\t' << ve.modifier << vcl_endl;
00253 }
00254 #endif
00255
00256
00257 ve.wx = event.GetX();
00258 ve.wy = get_height() - event.GetY();
00259
00260
00261 ve.timestamp = 0;
00262
00263 if (!dispatch_to_tableau(ve)) { event.Skip(); }
00264
00265 }
00266
00267
00268 void vgui_wx_adaptor::on_key_down(wxKeyEvent& event)
00269 {
00270
00271 if (is_modifier(event.GetKeyCode()))
00272 {
00273 event.Skip();
00274 return;
00275 }
00276
00277 #if 0
00278 vcl_cout << "EVT_KEY_DOWN: " << event.GetKeyCode() << vcl_endl;
00279 #endif
00280
00281
00282 last_key_down_ = event.GetKeyCode();
00283 event.Skip();
00284
00285
00286
00287 }
00288
00289
00290 void vgui_wx_adaptor::on_key_up(wxKeyEvent& event)
00291 {
00292 if (is_modifier(event.GetKeyCode()))
00293 {
00294 event.Skip();
00295 return;
00296 }
00297
00298 #if 0
00299 vcl_cout << "EVT_KEY_UP : " << event.GetKeyCode()
00300 << " (" << ascii_code_[event.GetKeyCode()] << ')' << vcl_endl;
00301 #endif
00302
00303
00304 event.m_keyCode = ascii_code_[event.GetKeyCode()];
00305
00306 vgui_event e(vgui_KEY_RELEASE);
00307 on_key(e, event);
00308 }
00309
00310
00311
00312
00313
00314
00315 void vgui_wx_adaptor::on_char(wxKeyEvent& event)
00316 {
00317 if (is_modifier(event.GetKeyCode()))
00318 {
00319 event.Skip();
00320 return;
00321 }
00322
00323 #if 0
00324 vcl_cout << "EVT_CHAR : " << last_key_down_
00325 << " (" << event.GetKeyCode() << ')' << vcl_endl;
00326 #endif
00327
00328
00329 ascii_code_[last_key_down_] = event.GetKeyCode();
00330
00331 vgui_event e(vgui_KEY_PRESS);
00332 on_key(e, event);
00333 }
00334
00335
00336 void vgui_wx_adaptor::on_mouse_event(wxMouseEvent& event)
00337 {
00338 vgui_macro_report_errors;
00339 vgui_event e;
00340
00341 e.origin = this;
00342 e.modifier = get_modifiers(event);
00343 e.button = translate_mouse_button(event.GetButton());
00344 e.type = translate_mouse_event_type(event);
00345
00346
00347 e.wx = event.GetX();
00348 e.wy = get_height() - event.GetY();
00349
00350
00351 e.timestamp = 0;
00352
00353 if ( e.modifier == mixin::popup_modifier &&
00354 e.button == mixin::popup_button )
00355 {
00356 vgui_macro_report_errors;
00357 vgui_popup_params params;
00358 params.x = e.wx;
00359 params.y = e.wy;
00360
00361 vgui_macro_report_errors;
00362
00363 last_popup_ = get_total_popup(params);
00364
00365 vgui_macro_report_errors;
00366
00367 vgui_wx_menu popup;
00368 wxMenu* menu = popup.create_wx_menu(last_popup_);
00369 vgui_macro_report_errors;
00370 PushEventHandler(&popup);
00371 PopupMenu(menu);
00372 PopEventHandler();
00373 vgui_macro_report_errors;
00374 delete menu;
00375
00376 vgui_macro_report_errors;
00377 invalidate_canvas();
00378 vgui_macro_report_errors;
00379 return;
00380 }
00381
00382
00383 if (e.button == vgui_LEFT)
00384 {
00385 if (e.type == vgui_BUTTON_DOWN)
00386 {
00387 CaptureMouse();
00388 }
00389 else if (e.type == vgui_BUTTON_UP)
00390 {
00391 ReleaseMouse();
00392 }
00393 }
00394
00395 if (!dispatch_to_tableau(e)) { event.Skip(); }
00396
00397 vgui_macro_report_errors;
00398 }
00399
00400
00401 void vgui_wx_adaptor::on_idle(wxIdleEvent& event)
00402 {
00403 if (idle_request_posted_)
00404 {
00405 idle_request_posted_ = dispatch_to_tableau(vgui_IDLE);
00406 event.RequestMore(idle_request_posted_);
00407
00408
00409 }
00410
00411 event.Skip();
00412 }
00413
00414
00415
00416
00417 void vgui_wx_adaptor::on_close(wxCloseEvent& event)
00418 {
00419
00420 vgui_macro_report_errors;
00421 dispatch_to_tableau(vgui_DESTROY);
00422 vgui_macro_report_errors;
00423 Destroy();
00424
00425 vgui_macro_report_errors;
00426 }
00427
00428
00429 void vgui_wx_adaptor::on_timer(wxEvent& event)
00430 {
00431 vgui_event e(vgui_TIMER);
00432 e.origin = this;
00433 e.timer_id = event.GetId();
00434 dispatch_to_tableau(e);
00435 }
00436
00437
00438 void vgui_wx_adaptor::invalidate_canvas(void)
00439 {
00440 Refresh();
00441
00442 #if 0
00443 if (view_)
00444 {
00445 view_->GetDocument()->UpdateAllViews();
00446 }
00447 else { Refresh(); }
00448 #endif
00449 }
00450
00451
00452
00453
00454 namespace
00455 {
00456 inline bool is_modifier(int key_code)
00457 {
00458 switch (key_code)
00459 {
00460 case WXK_SHIFT:
00461 case WXK_ALT:
00462 case WXK_CONTROL:
00463
00464 return true;
00465 default:
00466 return false;
00467 }
00468 }
00469
00470
00471 inline vgui_modifier get_modifiers(const wxMouseEvent& e)
00472 {
00473 int mod = 0;
00474 if (e.ShiftDown()) { mod |= vgui_SHIFT; }
00475 if (e.AltDown()) { mod |= vgui_ALT; }
00476 #ifdef __WXMAC__
00477
00478
00479
00480 if (e.MetaDown()) { mod |= vgui_CTRL; }
00481 if (e.ControlDown()) { mod |= vgui_META; }
00482 #else
00483 if (e.ControlDown()) { mod |= vgui_CTRL; }
00484 if (e.MetaDown()) { mod |= vgui_META; }
00485 #endif
00486 return static_cast<vgui_modifier>(mod);
00487 }
00488
00489
00490 inline vgui_modifier get_modifiers(const wxKeyEvent& e)
00491 {
00492 int mod = 0;
00493 if (e.ShiftDown()) { mod |= vgui_SHIFT; }
00494 if (e.AltDown()) { mod |= vgui_ALT; }
00495 #ifdef __WXMAC__
00496
00497
00498
00499 if (e.MetaDown()) { mod |= vgui_CTRL; }
00500 if (e.ControlDown()) { mod |= vgui_META; }
00501 #else
00502 if (e.ControlDown()) { mod |= vgui_CTRL; }
00503 if (e.MetaDown()) { mod |= vgui_META; }
00504 #endif
00505 return static_cast<vgui_modifier>(mod);
00506 }
00507
00508 inline vgui_event_type translate_mouse_event_type(const wxMouseEvent& e)
00509 {
00510 if (e.Moving() || e.Dragging()) { return vgui_MOTION; }
00511 else if (e.ButtonDown() || e.ButtonDClick())
00512 {
00513 return vgui_BUTTON_DOWN;
00514 }
00515 else if (e.ButtonUp()) { return vgui_BUTTON_UP; }
00516 else if (e.Entering()) { return vgui_ENTER; }
00517 else if (e.Leaving ()) { return vgui_LEAVE; }
00518 else if (e.GetEventType() == wxEVT_MOUSEWHEEL)
00519 {
00520 if (e.GetWheelRotation() > 0) { return vgui_WHEEL_UP; }
00521 else { return vgui_WHEEL_DOWN; }
00522 }
00523 else { return vgui_OTHER; }
00524 }
00525
00526 inline vgui_button translate_mouse_button(int button)
00527 {
00528 switch (button)
00529 {
00530 case wxMOUSE_BTN_NONE : return vgui_BUTTON_NULL;
00531 case wxMOUSE_BTN_LEFT : return vgui_LEFT;
00532 case wxMOUSE_BTN_MIDDLE : return vgui_MIDDLE;
00533 case wxMOUSE_BTN_RIGHT : return vgui_RIGHT;
00534 default:
00535 vcl_cerr << "VGUI wx Error: Unknown button identifier.\n";
00536 return vgui_BUTTON_NULL;
00537 }
00538 }
00539
00540 inline vgui_key translate_key(int key_code)
00541 {
00542 switch (key_code)
00543 {
00544 case WXK_ESCAPE : return vgui_ESC;
00545 case WXK_TAB : return vgui_TAB;
00546 case WXK_RETURN : return vgui_RETURN;
00547 case '\n' : return vgui_NEWLINE;
00548
00549 case WXK_F1 : return vgui_F1;
00550 case WXK_F2 : return vgui_F2;
00551 case WXK_F3 : return vgui_F3;
00552 case WXK_F4 : return vgui_F4;
00553 case WXK_F5 : return vgui_F5;
00554 case WXK_F6 : return vgui_F6;
00555 case WXK_F7 : return vgui_F7;
00556 case WXK_F8 : return vgui_F8;
00557 case WXK_F9 : return vgui_F9;
00558 case WXK_F10 : return vgui_F10;
00559 case WXK_F11 : return vgui_F11;
00560 case WXK_F12 : return vgui_F12;
00561 case WXK_LEFT : return vgui_CURSOR_LEFT;
00562 case WXK_UP : return vgui_CURSOR_UP;
00563 case WXK_RIGHT : return vgui_CURSOR_RIGHT;
00564 case WXK_DOWN : return vgui_CURSOR_DOWN;
00565 case WXK_PRIOR : return vgui_PAGE_UP;
00566 case WXK_NEXT : return vgui_PAGE_DOWN;
00567
00568
00569 case WXK_HOME : return vgui_HOME;
00570 case WXK_END : return vgui_END;
00571 case WXK_DELETE : return vgui_DELETE;
00572 case WXK_INSERT : return vgui_INSERT;
00573 default:
00574 if (0 < key_code && key_code < 256)
00575 {
00576 return static_cast<vgui_key>(key_code);
00577 }
00578 else
00579 {
00580 #ifdef __WXDEBUG__
00581 vcl_cerr << "VGUI wx Error: Unknown key code.\n";
00582 #endif
00583 return vgui_KEY_NULL;
00584 }
00585 }
00586 }
00587 }