tagging release
[dasher.git] / Src / Win32 / Widgets / Canvas.cpp
blobba1d00b07edd41307431312ee4ab9b419327e26a
1 // Canvas.cpp
2 //
3 /////////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (c) 2002 Iain Murray, Inference Group, Cavendish, Cambridge.
6 //
7 /////////////////////////////////////////////////////////////////////////////
9 #include "..\Common\WinCommon.h"
11 #include "Canvas.h"
12 //#include "Edit.h"
13 #include "../Dasher.h"
14 //#include "..\..\DasherCore\DasherInterfaceBase.h"
18 #define PRESSED 0x8000
19 #define REPEAT 0x40000000
20 using namespace Dasher;
22 #include "../TabletPC/SystemInfo.h"
23 #include "Screen.h"
25 /////////////////////////////////////////////////////////////////////////////
27 CCanvas::CCanvas(CDasher *DI, Dasher::CEventHandler *pEventHandler, CSettingsStore *pSettingsStore)
28 :m_pDasherInterface(DI), imousex(0), imousey(0), buttonnum(0), mousepostime(0) ,
29 m_dwTicksLastEvent(0), m_bButtonDown(false), m_pScreen(0),
30 CDasherComponent(pEventHandler, pSettingsStore)
34 #ifndef _WIN32_WCE
36 #else
37 WNDCLASS canvasclass;
38 GetClassInfo(NULL, TEXT("STATIC"), &canvasclass);
39 canvasclass.lpszClassName = TEXT("CANVAS");
41 #endif
44 /////////////////////////////////////////////////////////////////////////////
46 HWND CCanvas::Create(HWND hParent)
48 HWND hWnd = CWindowImpl<CCanvas>::Create(hParent, NULL, NULL, WS_CHILD | WS_VISIBLE ,WS_EX_CLIENTEDGE);
50 m_hdc = GetDC();
51 HDC hdc2 = GetDC();
52 HDC hdc3 = GetDC();
54 // Create input device objects
55 // NB We create the SocketInput object now, even if socket input is not enabled, because
56 // we can't safely create it later in response to a parameter change event (because it itself
57 // needs to register an event listener when it constructs itself).
59 // CreateSettingsStore only creates a new one if there isn't one there already
62 // TODO: Reimplement?
64 // m_pSocketInput = (CSocketInput *)m_pDasherInterface->GetModule(1);
65 // m_pSocketInput->Ref();
67 //m_pMouseInput = (CDasherMouseInput *)m_pDasherInterface->GetModule(0);
68 // m_pMouseInput->Ref();
70 /*if(m_pDasherInterface->GetBoolParameter(BP_SOCKET_INPUT_ENABLE))
72 m_pSocketInput->StartListening();
73 m_pDasherInterface->SetInput(1);
75 else {
76 m_pDasherInterface->SetInput(0);
77 }*/
80 m_pKeyboardHelper = new CKeyboardHelper;
82 m_pScreen = new CScreen(m_hdc, 300, 300);
83 m_pScreen->SetFont(m_pDasherInterface->GetStringParameter(SP_DASHER_FONT));
84 //ReleaseDC(m_hwnd,m_hDC);
85 m_pDasherInterface->ChangeScreen(m_pScreen);
87 for(int i = 0; i < 18; i++)
89 keycoords[i] = 0;
91 running = 0;
92 previoustime = GetTickCount();
93 direction = 0;
95 return hWnd;
98 /////////////////////////////////////////////////////////////////////////////
100 void CCanvas::SetScreenInterface(Dasher::CDasherInterfaceBase * dasherinterface)
102 m_pScreen->SetInterface(dasherinterface);
105 /////////////////////////////////////////////////////////////////////////////
107 LRESULT CCanvas::OnCreate(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
109 bHandled = TRUE;
111 // If we're a tablet, initialize the event-generator
112 if (IsTabletPC())
114 HRESULT h = m_CursorInRange.Initialize(m_hWnd);
115 if (! SUCCEEDED(h))
117 // detected tablet, but cant initialize the event-generator
118 return -1;
121 return 0;
124 /////////////////////////////////////////////////////////////////////////////
126 LRESULT CCanvas::OnDestroy(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
128 int iRC = ReleaseDC(m_hdc);
129 if(!iRC) {
130 LPVOID lpMsgBuf;
131 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
132 (LPTSTR) & lpMsgBuf, 0, NULL);
133 // Process any inserts in lpMsgBuf.
134 // ...
135 // Display the string.
136 ::MessageBox(NULL, (LPCTSTR) lpMsgBuf, TEXT("Error"), MB_OK | MB_ICONINFORMATION);
137 // Free the buffer.
138 LocalFree(lpMsgBuf);
141 bHandled = true;
142 return 0;
145 /////////////////////////////////////////////////////////////////////////////
147 CCanvas::~CCanvas() {
148 delete m_pScreen;
149 //if(m_pMouseInput != NULL) {
150 // delete m_pMouseInput;
152 //if(m_pSocketInput != NULL) {
153 // delete m_pSocketInput;
156 if(m_pKeyboardHelper)
157 delete m_pKeyboardHelper;
160 void CCanvas::Move(int x, int y, int Width, int Height)
162 MoveWindow(x, y, Width, Height, TRUE);
165 void CCanvas::Paint()
167 InvalidateRect(NULL, FALSE);
168 UpdateWindow();
172 LRESULT CCanvas::OnCommand(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
174 bHandled = TRUE;
175 SendMessage(GetParent(), message, wParam, lParam);
176 return 0;
179 LRESULT CCanvas::OnSetFocus(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
181 bHandled = TRUE;
182 SendMessage(GetParent(), WM_DASHER_FOCUS, 0, (LPARAM)&m_hWnd);
183 return 0;
186 LRESULT CCanvas::OnPaint(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
188 PAINTSTRUCT ps;
189 BeginPaint(&ps);
191 m_pScreen->Display();
193 EndPaint(&ps);
195 bHandled = TRUE;
196 return 0;
199 LRESULT CCanvas::OnKeyUp(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
201 bHandled = TRUE;
203 int iKeyVal(-1);
205 if(m_pKeyboardHelper)
206 iKeyVal = m_pKeyboardHelper->ConvertKeyCode(wParam);
208 if(iKeyVal != -1) {
209 m_pDasherInterface->KeyUp(GetTickCount(), iKeyVal);
210 return 0;
213 switch(wParam)
215 case VK_SHIFT:
216 if(GetKeyState(VK_CONTROL) & PRESSED)
217 m_pDasherInterface->SetLongParameter(LP_BOOSTFACTOR, 25);
218 else
219 m_pDasherInterface->SetLongParameter(LP_BOOSTFACTOR, 100);
220 return 0;
221 case VK_CONTROL:
222 if(GetKeyState(VK_SHIFT) & PRESSED)
223 m_pDasherInterface->SetLongParameter(LP_BOOSTFACTOR, 175);
224 else
225 m_pDasherInterface->SetLongParameter(LP_BOOSTFACTOR, 100);
227 return 0;
228 default:
229 return 0;
234 LRESULT CCanvas::OnKeyDown(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
236 #ifdef _DEBUG
237 TCHAR tmpAutoOffset[128];
238 #endif
240 bHandled = TRUE;
242 int iKeyVal(-1);
244 if(m_pKeyboardHelper)
245 iKeyVal = m_pKeyboardHelper->ConvertKeyCode(wParam);
247 if(iKeyVal != -1) {
248 m_pDasherInterface->KeyDown(GetTickCount(), iKeyVal);
249 return 0;
252 switch (wParam) {
253 // Space, for start/stop events etc.
254 case VK_SPACE:
255 m_pDasherInterface->KeyDown(GetTickCount(), 0);
256 return 0;
258 //#ifdef _DEBUG
259 // case VK_F11:
260 // wsprintf(tmpAutoOffset, TEXT("yAutoValue: %d"), m_pDasherInterface->GetAutoOffset());
261 // MessageBox(tmpAutoOffset, TEXT("Auto-offset Value"), MB_OK);
262 // return 0;
263 //#endif
265 case VK_F12:
266 centrecursor();
267 return 0;
269 // Boost keys
270 case VK_SHIFT:
271 if(lParam ^ REPEAT) // ignore auto-repeat
272 m_pDasherInterface->SetLongParameter(LP_BOOSTFACTOR, 175);
273 return 0;
274 case VK_CONTROL:
275 if(lParam ^ REPEAT) // ignore auto-repeat
276 m_pDasherInterface->SetLongParameter(LP_BOOSTFACTOR, 25);
277 return 0;
279 // Button mode keys
280 case 0x41:
281 m_pDasherInterface->KeyDown(GetTickCount(), 1);
282 return 0;
283 case 0x53:
284 m_pDasherInterface->KeyDown(GetTickCount(), 2);
285 return 0;
286 case 0x57:
287 m_pDasherInterface->KeyDown(GetTickCount(), 3);
288 return 0;
289 case 0x58:
290 m_pDasherInterface->KeyDown(GetTickCount(), 4);
291 return 0;
292 default:
293 return 0;
297 LRESULT CCanvas::OnLButtonDblClk(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
299 // bHandled = TRUE;
300 // if( m_pDasherInterface->GetBoolParameter(BP_START_STYLUS) )
301 // {
302 // m_pDasherInterface->PauseAt(0, 0);
303 // }
304 return 0;
307 LRESULT CCanvas::OnLButtonDown(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
309 bHandled = TRUE;
311 OutputDebugString(TEXT("Canvas::LButtonDown\n"));
313 // FIXME - what does this do - please document
314 LPARAM lp = GetMessageExtraInfo();
315 if (lp == 0xFF515702)
316 return 0;
317 // ---
319 m_pDasherInterface->KeyDown(GetTickCount(), 100);
321 // else if ( m_pDasherInterface->GetBoolParameter(BP_START_STYLUS) )
322 // {
323 // // DJW - for the time being we only do stylus mode if not BP_START_MOUSE
325 // if ( m_pDasherInterface->GetBoolParameter(BP_DASHER_PAUSED) )
326 // m_pDasherInterface->Unpause(GetTickCount());
327 // }
329 m_bButtonDown = true;
330 return 0;
333 LRESULT CCanvas::OnLButtonUp(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
335 bHandled = TRUE;
337 endturbo = GetTickCount();
339 if(endturbo - startturbo > 1)
341 TCHAR deb[80];
342 wsprintf(deb, TEXT("start: %d\nend: %d\nduration: %d"), startturbo, endturbo, endturbo - startturbo);
343 OutputDebugString(deb);
345 lbuttonheld = 0;
347 m_bButtonDown = false;
349 return 0;
353 LRESULT CCanvas::OnCursorInRange(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
355 OutputDebugString(TEXT("CursorInRange\n"));
357 bHandled = TRUE;
359 //SetFocus();
361 if ( m_pDasherInterface->GetBoolParameter(BP_START_MOUSE) )
363 if (m_pDasherInterface->GetBoolParameter(BP_DASHER_PAUSED))
364 m_pDasherInterface->Unpause(GetTickCount());
367 return 0;
371 LRESULT CCanvas::OnCursorOutOfRange(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
373 OutputDebugString(TEXT("CursorOutOfRange\n"));
375 bHandled = TRUE;
376 if ( m_pDasherInterface->GetBoolParameter(BP_START_MOUSE) )
378 if (!m_pDasherInterface->GetBoolParameter(BP_DASHER_PAUSED))
379 m_pDasherInterface->PauseAt(0, 0);
382 return 0;
385 LRESULT CCanvas::OnRButtonDown(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
387 // bHandled = TRUE;
388 // if( m_pDasherInterface->GetBoolParameter(BP_START_STYLUS) )
389 // {
390 // if( m_pDasherInterface->GetBoolParameter(BP_DASHER_PAUSED) )
391 // m_pDasherInterface->Unpause(GetTickCount());
392 // }
393 // m_bButtonDown = true;
394 return 0;
398 LRESULT CCanvas::OnRButtonUp(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
400 bHandled = TRUE;
401 m_bButtonDown = false;
402 return 0;
405 LRESULT CCanvas::OnMouseMove(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
407 bHandled = true;
409 imousex = LOWORD(lParam);
410 imousey = HIWORD(lParam);
411 m_dwTicksLastEvent = GetTickCount();
412 // if( m_pDasherInterface->GetBoolParameter(BP_START_STYLUS) )
413 // {
414 // if( m_pDasherInterface->GetBoolParameter(BP_DASHER_PAUSED) )
415 // m_pDasherInterface->Unpause(GetTickCount());
416 // }
418 return 0;
421 LRESULT CCanvas::OnSize(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
423 bHandled = TRUE;
424 if(m_pScreen != 0)
426 delete m_pScreen;
427 m_pScreen = 0;
429 if (LOWORD(lParam)>0 && HIWORD(lParam) >0)
431 m_pScreen = new CScreen(m_hdc, LOWORD(lParam), HIWORD(lParam));
432 m_pScreen->SetFont(m_pDasherInterface->GetStringParameter(SP_DASHER_FONT));
433 m_pDasherInterface->ChangeScreen(m_pScreen);
434 InvalidateRect( NULL, FALSE);
436 return 0;
439 LRESULT CCanvas::OnTimer(UINT message, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
440 bHandled = true;
442 m_pDasherInterface->Main();
444 return 0;
447 void CCanvas::DoFrame()
449 POINT mousepos2;
450 GetCursorPos(&mousepos2);
452 ScreenToClient(&mousepos2);
454 POINT mousepos;
455 GetCursorPos(&mousepos);
457 // if(running == 0) {
458 // ScreenToClient(m_hwnd, &mousepos);
459 // if(m_pDasherInterface->GetBoolParameter(BP_MOUSEPOS_MODE) == true) // configuration option
460 // {
461 // // DASHER_TRACEOUTPUT("first:%d second:%d %d\n",firstwindow,secondwindow,m_iMousePosDist);
462 // if(firstwindow != true && secondwindow != true) {
463 // m_pDasherInterface->SetLongParameter(LP_MOUSE_POS_BOX, 1);
464 // firstwindow = true;
465 // }
466 // int mouseDist = m_pDasherInterface->GetLongParameter(LP_MOUSEPOSDIST);
467 // if(mousepos.y > m_pScreen->GetHeight() / 2 - mouseDist - 50 && mousepos.y < m_pScreen->GetHeight() / 2 - mouseDist + 50 && firstwindow == true) {
468 // // Mouse is in the top box
469 // if(mousepostime == 0) {
470 // mousepostime = GetTickCount();
471 // }
472 // else if((GetTickCount() - mousepostime) > 2000) {
473 // firstwindow = false;
474 // secondwindow = true;
475 // mousepostime = 0;
476 // m_pDasherInterface->SetLongParameter(LP_MOUSE_POS_BOX, 2);
477 // }
478 // }
479 // else if(firstwindow == true) {
480 // mousepostime = 0;
481 // }
482 // if(secondwindow == true) {
483 // if(mousepos.y < m_pScreen->GetHeight() / 2 + mouseDist + 50 && mousepos.y > (m_pScreen->GetHeight() / 2 + mouseDist - 50)) {
484 // // In second window
485 // if(mousepostime == 0) {
486 // mousepostime = GetTickCount();
487 // }
488 // else if((GetTickCount() - mousepostime) > 2000) {
489 // m_pDasherInterface->SetLongParameter(LP_MOUSE_POS_BOX, -1);
490 // StartStop();
491 // }
492 // }
493 // else if(mousepostime > 0) {
494 // secondwindow = false;
495 // firstwindow = true;
496 // m_pDasherInterface->SetLongParameter(LP_MOUSE_POS_BOX, 1);
497 // mousepostime = 0;
498 // }
499 // }
500 // }
501 // imousey = mousepos.y;
503 // imousex = mousepos.x;
505 // if(m_pDasherInterface->GetBoolParameter(BP_NUMBER_DIMENSIONS) == true) {
506 // double scalefactor;
507 // if(yscaling == 0) {
508 // scalefactor = 2.0;
509 // }
510 // else {
511 // scalefactor = m_pScreen->GetHeight() / yscaling;
512 // }
513 // imousey -= m_pScreen->GetHeight() / 2;
514 // imousey *= scalefactor;
515 // imousey += m_pScreen->GetHeight() / 2;
516 // }
518 // if((GetTickCount() - previoustime) > 200) {
519 // if(firstwindow == true) {
520 // m_pDasherInterface->SetLongParameter(LP_MOUSE_POS_BOX, 1);
521 // }
522 // else if(secondwindow == true) {
523 // m_pDasherInterface->SetLongParameter(LP_MOUSE_POS_BOX, 2);
524 // }
526 // previoustime = GetTickCount();
527 // }
529 // return 0;
530 // }
532 //// if(m_pDasherInterface->GetBoolParameter(BP_WINDOW_PAUSE) == true) {
533 // // RECT windowrect;
535 //// GetWindowRect(m_hwnd, &windowrect);
536 // // if(mousepos.y > windowrect.bottom || mousepos.y < windowrect.top || mousepos.x > windowrect.right || mousepos.x < windowrect.left)
537 //// return 0;
538 // // }
540 // ScreenToClient(m_hwnd, &mousepos);
541 // imousey = mousepos.y;
542 // imousex = mousepos.x;
544 // if(m_pDasherInterface->GetBoolParameter(BP_NUMBER_DIMENSIONS) == true) {
545 // double scalefactor;
546 // if(yscaling == 0) {
547 // scalefactor = 2;
548 // }
549 // else {
550 // scalefactor = m_pScreen->GetHeight() / yscaling;
551 // }
552 // imousey -= m_pScreen->GetHeight() / 2;
553 // imousey *= scalefactor;
554 // imousey += m_pScreen->GetHeight() / 2;
555 // }
557 DWORD dwTicks = GetTickCount();
559 // If not paused need to consider stop on idle
560 if( !m_pDasherInterface->GetBoolParameter(BP_DASHER_PAUSED) )
562 // only pause if button is not down
563 if( !m_bButtonDown && m_pDasherInterface->GetBoolParameter(BP_STOP_IDLE) )
565 if (dwTicks - m_dwTicksLastEvent > m_pDasherInterface->GetLongParameter(LP_STOP_IDLETIME) )
567 // idle time exceeded
568 m_pDasherInterface->PauseAt(0, 0);
573 m_pDasherInterface->NewFrame(dwTicks, false);//TapOn(imousex, imousey, GetTickCount());
576 void CCanvas::centrecursor() {
577 POINT mousepos;
578 mousepos.x = m_pScreen->GetWidth() / 2;
580 mousepos.y = m_pScreen->GetHeight() / 2;
582 ClientToScreen( &mousepos);
584 SetCursorPos(mousepos.x, mousepos.y);
588 void CCanvas::MousePosStart(bool Value) {
589 if(Value == false) {
590 firstwindow = false;
591 secondwindow = false;
595 /////////////////////////////////////////////////////////////////////////////
597 void CCanvas::StartStop() {
599 if(running == 0) {
600 SetCapture();
601 running = 1;
602 m_pDasherInterface->Unpause(GetTickCount());
603 firstwindow = false;
604 secondwindow = false;
605 mousepostime = 0;
608 else {
609 m_pDasherInterface->PauseAt(0, 0);
610 running = 0;
611 // if (speakonstop==true) { // FIXME - reimplement this
612 // m_DasherEditBox->speak(2);
613 // }
614 ReleaseCapture();
618 /////////////////////////////////////////////////////////////////////////////
620 // Gets the size of the canvas in screen coordinates. Need if we
621 // want to log mouse positions normalized by the size of the
622 // canvas.
623 bool CCanvas::GetCanvasSize(int& iTop, int& iLeft, int& iBottom, int& iRight)
626 RECT sWindowRect;
628 if (GetWindowRect( &sWindowRect))
630 iTop = sWindowRect.top;
631 iLeft = sWindowRect.left;
632 iBottom = sWindowRect.bottom;
633 iRight = sWindowRect.right;
634 return true;
636 else
637 return false;
641 void CCanvas::HandleEvent(Dasher::CEvent *pEvent) {
643 if(pEvent->m_iEventType == 1) {
644 Dasher::CParameterNotificationEvent * pEvt(static_cast < Dasher::CParameterNotificationEvent * >(pEvent));
645 switch (pEvt->m_iParameter) {
646 case SP_DASHER_FONT:
647 m_pScreen->SetFont(m_pDasherInterface->GetStringParameter(SP_DASHER_FONT));
648 break;
649 /* case BP_SOCKET_INPUT_ENABLE:
650 OutputDebugString(TEXT("Processing BP_SOCKET_INPUT_ENABLE change\n"));
651 if(GetBoolParameter(BP_SOCKET_INPUT_ENABLE)) {
652 if(!m_pSocketInput->isListening()) {
653 m_pSocketInput->StartListening();
655 m_pDasherInterface->SetInput(1);
657 else {
658 if(m_pSocketInput != NULL) {
659 m_pSocketInput->StopListening();
661 m_pDasherInterface->SetInput(0);
663 break;*/
664 default:
665 break;