PageRenderTime 41ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/winboard/wevalgraph.c

#
C | 315 lines | 204 code | 64 blank | 47 comment | 35 complexity | 9b593fd1b6d9f578b81ef9fdaaa4a9d2 MD5 | raw file
Possible License(s): GPL-3.0, MPL-2.0-no-copyleft-exception
  1. /*
  2. * wevalgraph.c - Evaluation graph front-end part
  3. *
  4. * Author: Alessandro Scotti (Dec 2005)
  5. *
  6. * Copyright 2005 Alessandro Scotti
  7. *
  8. * ------------------------------------------------------------------------
  9. *
  10. * GNU XBoard is free software: you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation, either version 3 of the License, or (at
  13. * your option) any later version.
  14. *
  15. * GNU XBoard is distributed in the hope that it will be useful, but
  16. * WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. * General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program. If not, see http://www.gnu.org/licenses/. *
  22. *
  23. *------------------------------------------------------------------------
  24. ** See the file ChangeLog for a revision history. */
  25. // code refactored by HGM to obtain front-end / back-end separation
  26. #include "config.h"
  27. #include <windows.h>
  28. #include <commdlg.h>
  29. #include <dlgs.h>
  30. #include <stdio.h>
  31. #include "common.h"
  32. #include "frontend.h"
  33. #include "backend.h"
  34. #include "winboard.h"
  35. #include "evalgraph.h"
  36. #include "wsnap.h"
  37. #define WM_REFRESH_GRAPH (WM_USER + 1)
  38. /* Module globals */
  39. static BOOLEAN evalGraphDialogUp;
  40. static COLORREF crWhite = RGB( 0xFF, 0xFF, 0xB0 );
  41. static COLORREF crBlack = RGB( 0xAD, 0x5D, 0x3D );
  42. static HDC hdcPB = NULL;
  43. static HBITMAP hbmPB = NULL;
  44. static HPEN pens[6]; // [HGM] put all pens in one array
  45. static HBRUSH hbrHist[3] = { NULL, NULL, NULL };
  46. Boolean EvalGraphIsUp()
  47. {
  48. return evalGraphDialogUp;
  49. }
  50. // [HGM] front-end, added as wrapper to avoid use of LineTo and MoveToEx in other routines (so they can be back-end)
  51. void DrawSegment( int x, int y, int *lastX, int *lastY, int penType )
  52. {
  53. POINT stPt;
  54. if(penType == PEN_NONE) MoveToEx( hdcPB, x, y, &stPt ); else {
  55. HPEN hp = SelectObject( hdcPB, pens[penType] );
  56. LineTo( hdcPB, x, y );
  57. SelectObject( hdcPB, hp );
  58. }
  59. if(lastX != NULL) { *lastX = stPt.x; *lastY = stPt.y; }
  60. }
  61. // front-end wrapper for drawing functions to do rectangles
  62. void DrawRectangle( int left, int top, int right, int bottom, int side, int style )
  63. {
  64. HPEN hp = SelectObject( hdcPB, pens[PEN_BLACK] );
  65. RECT rc;
  66. rc.top = top; rc.left = left; rc.bottom = bottom; rc.right = right;
  67. if(style == FILLED)
  68. FillRect( hdcPB, &rc, hbrHist[side] );
  69. else {
  70. SelectObject( hdcPB, hbrHist[side] );
  71. Rectangle( hdcPB, left, top, right, bottom );
  72. }
  73. SelectObject( hdcPB, hp );
  74. }
  75. // front-end wrapper for putting text in graph
  76. void DrawEvalText(char *buf, int cbBuf, int y)
  77. {
  78. SIZE stSize;
  79. SetBkMode( hdcPB, TRANSPARENT );
  80. GetTextExtentPoint32( hdcPB, buf, cbBuf, &stSize );
  81. TextOut( hdcPB, MarginX - stSize.cx - 2, y - stSize.cy / 2, buf, cbBuf );
  82. }
  83. // front-end
  84. static HBRUSH CreateBrush( UINT style, COLORREF color )
  85. {
  86. LOGBRUSH stLB;
  87. stLB.lbStyle = style;
  88. stLB.lbColor = color;
  89. stLB.lbHatch = 0;
  90. return CreateBrushIndirect( &stLB );
  91. }
  92. // front-end. Create pens, device context and buffer bitmap for global use, copy result to display
  93. // The back-end part n the middle has been taken out and moed to PainEvalGraph()
  94. static VOID DisplayEvalGraph( HWND hWnd, HDC hDC )
  95. {
  96. RECT rcClient;
  97. int width;
  98. int height;
  99. /* Get client area */
  100. GetClientRect( hWnd, &rcClient );
  101. width = rcClient.right - rcClient.left;
  102. height = rcClient.bottom - rcClient.top;
  103. /* Create or recreate paint box if needed */
  104. if( hbmPB == NULL || width != nWidthPB || height != nHeightPB ) {
  105. if( pens[PEN_DOTTED] == NULL ) {
  106. pens[PEN_BLACK] = GetStockObject(BLACK_PEN);
  107. pens[PEN_DOTTED] = CreatePen( PS_DOT, 0, RGB(0xA0,0xA0,0xA0) );
  108. pens[PEN_BLUEDOTTED] = CreatePen( PS_DOT, 0, RGB(0x00,0x00,0xFF) );
  109. pens[PEN_BOLD] = CreatePen( PS_SOLID, 2, crWhite );
  110. pens[PEN_BOLD+1] = CreatePen( PS_SOLID, 2, crBlack );
  111. hbrHist[0] = CreateBrush( BS_SOLID, crWhite );
  112. hbrHist[1] = CreateBrush( BS_SOLID, crBlack );
  113. hbrHist[2] = CreateBrush( BS_SOLID, GetSysColor( COLOR_3DFACE ) ); // background
  114. }
  115. if( hdcPB != NULL ) {
  116. DeleteDC( hdcPB );
  117. hdcPB = NULL;
  118. }
  119. if( hbmPB != NULL ) {
  120. DeleteObject( hbmPB );
  121. hbmPB = NULL;
  122. }
  123. hdcPB = CreateCompatibleDC( hDC );
  124. nWidthPB = width;
  125. nHeightPB = height;
  126. hbmPB = CreateCompatibleBitmap( hDC, nWidthPB, nHeightPB );
  127. SelectObject( hdcPB, hbmPB );
  128. }
  129. // back-end painting; calls back front-end primitives for lines, rectangles and text
  130. PaintEvalGraph();
  131. SetWindowText(hWnd, MakeEvalTitle(T_("Evaluation Graph")));
  132. /* Copy bitmap into destination DC */
  133. BitBlt( hDC, 0, 0, nWidthPB, nHeightPB, hdcPB, 0, 0, SRCCOPY );
  134. }
  135. // Note: Once the eval graph is opened, this window-proc lives forever; een closing the
  136. // eval-graph window merely hides it. On opening we re-initialize it, though, so it could
  137. // as well hae been destroyed. While it is open it processes the REFRESH_GRAPH commands.
  138. LRESULT CALLBACK EvalGraphProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
  139. {
  140. static SnapData sd;
  141. PAINTSTRUCT stPS;
  142. HDC hDC;
  143. switch (message) {
  144. case WM_INITDIALOG:
  145. Translate(hDlg, DLG_EvalGraph);
  146. if( evalGraphDialog == NULL ) {
  147. evalGraphDialog = hDlg;
  148. RestoreWindowPlacement( hDlg, &wpEvalGraph ); /* Restore window placement */
  149. }
  150. return FALSE;
  151. case WM_COMMAND:
  152. switch (LOWORD(wParam)) {
  153. case IDOK:
  154. EndDialog(hDlg, TRUE);
  155. return TRUE;
  156. case IDCANCEL:
  157. EndDialog(hDlg, FALSE);
  158. return TRUE;
  159. default:
  160. break;
  161. }
  162. break;
  163. case WM_ERASEBKGND:
  164. return TRUE;
  165. case WM_PAINT:
  166. hDC = BeginPaint( hDlg, &stPS );
  167. DisplayEvalGraph( hDlg, hDC );
  168. EndPaint( hDlg, &stPS );
  169. break;
  170. case WM_REFRESH_GRAPH:
  171. hDC = GetDC( hDlg );
  172. DisplayEvalGraph( hDlg, hDC );
  173. ReleaseDC( hDlg, hDC );
  174. break;
  175. case WM_LBUTTONDOWN:
  176. if( wParam == 0 || wParam == MK_LBUTTON ) {
  177. int index = GetMoveIndexFromPoint( LOWORD(lParam), HIWORD(lParam) );
  178. if( index >= 0 && index < currLast ) {
  179. ToNrEvent( index + 1 );
  180. }
  181. }
  182. return TRUE;
  183. case WM_SIZE:
  184. InvalidateRect( hDlg, NULL, FALSE );
  185. break;
  186. case WM_GETMINMAXINFO:
  187. {
  188. MINMAXINFO * mmi = (MINMAXINFO *) lParam;
  189. mmi->ptMinTrackSize.x = 100;
  190. mmi->ptMinTrackSize.y = 100;
  191. }
  192. break;
  193. /* Support for captionless window */
  194. case WM_CLOSE:
  195. EvalGraphPopDown();
  196. break;
  197. case WM_ENTERSIZEMOVE:
  198. return OnEnterSizeMove( &sd, hDlg, wParam, lParam );
  199. case WM_SIZING:
  200. return OnSizing( &sd, hDlg, wParam, lParam );
  201. case WM_MOVING:
  202. return OnMoving( &sd, hDlg, wParam, lParam );
  203. case WM_EXITSIZEMOVE:
  204. return OnExitSizeMove( &sd, hDlg, wParam, lParam );
  205. }
  206. return FALSE;
  207. }
  208. // creates the eval graph, or unhides it.
  209. VOID EvalGraphPopUp()
  210. {
  211. FARPROC lpProc;
  212. CheckMenuItem(GetMenu(hwndMain), IDM_ShowEvalGraph, MF_CHECKED);
  213. if( evalGraphDialog ) {
  214. SendMessage( evalGraphDialog, WM_INITDIALOG, 0, 0 );
  215. if( ! evalGraphDialogUp ) {
  216. ShowWindow(evalGraphDialog, SW_SHOW);
  217. }
  218. }
  219. else {
  220. crWhite = appData.evalHistColorWhite;
  221. crBlack = appData.evalHistColorBlack;
  222. lpProc = MakeProcInstance( (FARPROC) EvalGraphProc, hInst );
  223. /* Note to self: dialog must have the WS_VISIBLE style set, otherwise it's not shown! */
  224. CreateDialog( hInst, MAKEINTRESOURCE(DLG_EvalGraph), hwndMain, (DLGPROC)lpProc );
  225. FreeProcInstance(lpProc);
  226. }
  227. evalGraphDialogUp = TRUE;
  228. }
  229. // Note that this hides the window. It could as well have destroyed it.
  230. VOID EvalGraphPopDown()
  231. {
  232. CheckMenuItem(GetMenu(hwndMain), IDM_ShowEvalGraph, MF_UNCHECKED);
  233. if( evalGraphDialog ) {
  234. ShowWindow(evalGraphDialog, SW_HIDE);
  235. }
  236. evalGraphDialogUp = FALSE;
  237. }
  238. // This function is the interface to the back-end. It is currently called through the front-end,
  239. // though, where it shares the HistorySet() wrapper with MoveHistorySet(). Once all front-ends
  240. // support the eval graph, it would be more logical to call it directly from the back-end.
  241. VOID EvalGraphSet( int first, int last, int current, ChessProgramStats_Move * pvInfo )
  242. {
  243. /* [AS] Danger! For now we rely on the pvInfo parameter being a static variable! */
  244. currFirst = first;
  245. currLast = last;
  246. currCurrent = current;
  247. currPvInfo = pvInfo;
  248. if( evalGraphDialog ) {
  249. SendMessage( evalGraphDialog, WM_REFRESH_GRAPH, 0, 0 );
  250. }
  251. }