worked on premove bug
[xboard.git] / winboard / wsnap.c
1 /*\r
2  * Smart "snapping" for window moving and sizing\r
3  *\r
4  * Author: Alessandro Scotti (Dec 2005)\r
5  *\r
6  * Copyright 2005 Alessandro Scotti\r
7  *\r
8  * ------------------------------------------------------------------------\r
9  *\r
10  * GNU XBoard is free software: you can redistribute it and/or modify\r
11  * it under the terms of the GNU General Public License as published by\r
12  * the Free Software Foundation, either version 3 of the License, or (at\r
13  * your option) any later version.\r
14  *\r
15  * GNU XBoard is distributed in the hope that it will be useful, but\r
16  * WITHOUT ANY WARRANTY; without even the implied warranty of\r
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
18  * General Public License for more details.\r
19  *\r
20  * You should have received a copy of the GNU General Public License\r
21  * along with this program. If not, see http://www.gnu.org/licenses/.  *\r
22  *\r
23  *------------------------------------------------------------------------\r
24  ** See the file ChangeLog for a revision history.  */\r
25 \r
26 #include "wsnap.h"\r
27 \r
28 /* Imports from winboard.c */\r
29 extern HINSTANCE hInst;\r
30 \r
31 extern HWND hwndMain;\r
32 extern HWND moveHistoryDialog;\r
33 extern HWND evalGraphDialog;\r
34 extern HWND engineOutputDialog;\r
35 extern HWND gameListDialog;\r
36 \r
37 static BOOL SnappingEnabled = TRUE;\r
38 \r
39 static void AddSnapPoint( int * grid, int * grid_len, int value )\r
40 {\r
41     int len = *grid_len;\r
42 \r
43     if( len < MAX_SNAP_POINTS ) {\r
44         int i;\r
45 \r
46         for( i=0; i<len; i++ ) {\r
47             if( grid[i] == value ) {\r
48                 return;\r
49             }\r
50         }\r
51 \r
52         grid[ len++ ] = value;\r
53 \r
54         *grid_len = len;\r
55     }\r
56 }\r
57 \r
58 static void AddSnapRectangle( SnapData * sd, RECT * rc )\r
59 {\r
60     AddSnapPoint( sd->x_grid, &sd->x_grid_len, rc->left );\r
61     AddSnapPoint( sd->x_grid, &sd->x_grid_len, rc->right );\r
62 \r
63     AddSnapPoint( sd->y_grid, &sd->y_grid_len, rc->top );\r
64     AddSnapPoint( sd->y_grid, &sd->y_grid_len, rc->bottom );\r
65 }\r
66 \r
67 static void AddSnapWindow( HWND hWndCaller, SnapData * sd, HWND hWndSnapWindow )\r
68 {\r
69     if( hWndSnapWindow != NULL && hWndCaller != hWndSnapWindow && IsWindowVisible(hWndSnapWindow) ) {\r
70         RECT rc;\r
71 \r
72         GetWindowRect( hWndSnapWindow, &rc );\r
73 \r
74         AddSnapRectangle( sd, &rc );\r
75     }\r
76 }\r
77 \r
78 static BOOL AdjustToSnapPoint( int * grid, int grid_len, int value, int * snap_size, int * delta )\r
79 {\r
80     BOOL result = FALSE;\r
81     int i;\r
82 \r
83     for( i=0; i<grid_len; i++ ) {\r
84         int distance = value - grid[i];\r
85 \r
86         if( distance < 0 ) distance = -distance;\r
87 \r
88         if( distance < *snap_size ) {\r
89             result = TRUE;\r
90             *snap_size = distance;\r
91             *delta = grid[i] - value;\r
92         }\r
93     }\r
94 \r
95     return result;\r
96 }\r
97 \r
98 LRESULT OnEnterSizeMove( SnapData * snapData, HWND hWnd, WPARAM wParam, LPARAM lParam )\r
99 {\r
100     RECT rc;\r
101 \r
102     snapData->x_grid_len = 0;\r
103     snapData->y_grid_len = 0;\r
104 \r
105     /* Add desktop area */\r
106     if( SystemParametersInfo( SPI_GETWORKAREA, 0, &rc, 0 ) ) {\r
107         AddSnapRectangle( snapData, &rc );\r
108     }\r
109 \r
110     if( hWnd != hwndMain ) {\r
111         /* Add other windows */\r
112         AddSnapWindow( hWnd, snapData, hwndMain );\r
113         AddSnapWindow( hWnd, snapData, moveHistoryDialog );\r
114         AddSnapWindow( hWnd, snapData, evalGraphDialog );\r
115         AddSnapWindow( hWnd, snapData, engineOutputDialog );\r
116         AddSnapWindow( hWnd, snapData, gameListDialog );\r
117     }\r
118 \r
119     return 0;\r
120 }\r
121 \r
122 LRESULT OnMoving( SnapData * snapData, HWND hWnd, WPARAM wParam, LPARAM lParam )\r
123 {\r
124     LPRECT lprc = (LPRECT) lParam;\r
125     int delta_x = 0;\r
126     int delta_y = 0;\r
127     int snap_size_x = SNAP_DISTANCE;\r
128     int snap_size_y = SNAP_DISTANCE;\r
129 \r
130     if( ! SnappingEnabled ) {\r
131         return FALSE;\r
132     }\r
133 \r
134     AdjustToSnapPoint( snapData->x_grid, snapData->x_grid_len, lprc->left, &snap_size_x, &delta_x );\r
135     AdjustToSnapPoint( snapData->x_grid, snapData->x_grid_len, lprc->right, &snap_size_x, &delta_x );\r
136 \r
137     AdjustToSnapPoint( snapData->y_grid, snapData->y_grid_len, lprc->top, &snap_size_y, &delta_y );\r
138     AdjustToSnapPoint( snapData->y_grid, snapData->y_grid_len, lprc->bottom, &snap_size_y, &delta_y );\r
139 \r
140     OffsetRect( lprc, delta_x, delta_y );\r
141 \r
142     return TRUE;\r
143 }\r
144 \r
145 LRESULT OnSizing( SnapData * snapData, HWND hWnd, WPARAM wParam, LPARAM lParam )\r
146 {\r
147     LPRECT lprc = (LPRECT) lParam;\r
148     int delta_x = 0;\r
149     int delta_y = 0;\r
150     int snap_size_x = SNAP_DISTANCE;\r
151     int snap_size_y = SNAP_DISTANCE;\r
152 \r
153     if( ! SnappingEnabled ) {\r
154         return FALSE;\r
155     }\r
156 \r
157     switch( wParam ) {\r
158     case WMSZ_BOTTOM:\r
159         AdjustToSnapPoint( snapData->y_grid, snapData->y_grid_len, lprc->bottom, &snap_size_y, &delta_y );\r
160         lprc->bottom += delta_y;\r
161         break;\r
162     case WMSZ_BOTTOMLEFT:\r
163         AdjustToSnapPoint( snapData->y_grid, snapData->y_grid_len, lprc->bottom, &snap_size_y, &delta_y );\r
164         lprc->bottom += delta_y;\r
165         AdjustToSnapPoint( snapData->x_grid, snapData->x_grid_len, lprc->left, &snap_size_x, &delta_x );\r
166         lprc->left += delta_x;\r
167         break;\r
168     case WMSZ_BOTTOMRIGHT:\r
169         AdjustToSnapPoint( snapData->y_grid, snapData->y_grid_len, lprc->bottom, &snap_size_y, &delta_y );\r
170         lprc->bottom += delta_y;\r
171         AdjustToSnapPoint( snapData->x_grid, snapData->x_grid_len, lprc->right, &snap_size_x, &delta_x );\r
172         lprc->right += delta_x;\r
173         break;\r
174     case WMSZ_LEFT:\r
175         AdjustToSnapPoint( snapData->x_grid, snapData->x_grid_len, lprc->left, &snap_size_x, &delta_x );\r
176         lprc->left += delta_x;\r
177         break;\r
178     case WMSZ_RIGHT:\r
179         AdjustToSnapPoint( snapData->x_grid, snapData->x_grid_len, lprc->right, &snap_size_x, &delta_x );\r
180         lprc->right += delta_x;\r
181         break;\r
182     case WMSZ_TOP:\r
183         AdjustToSnapPoint( snapData->y_grid, snapData->y_grid_len, lprc->top, &snap_size_y, &delta_y );\r
184         lprc->top += delta_y;\r
185         break;\r
186     case WMSZ_TOPLEFT:\r
187         AdjustToSnapPoint( snapData->y_grid, snapData->y_grid_len, lprc->top, &snap_size_y, &delta_y );\r
188         lprc->top += delta_y;\r
189         AdjustToSnapPoint( snapData->x_grid, snapData->x_grid_len, lprc->left, &snap_size_x, &delta_x );\r
190         lprc->left += delta_x;\r
191         break;\r
192     case WMSZ_TOPRIGHT:\r
193         AdjustToSnapPoint( snapData->y_grid, snapData->y_grid_len, lprc->top, &snap_size_y, &delta_y );\r
194         lprc->top += delta_y;\r
195         AdjustToSnapPoint( snapData->x_grid, snapData->x_grid_len, lprc->right, &snap_size_x, &delta_x );\r
196         lprc->right += delta_x;\r
197         break;\r
198     default:\r
199         return FALSE;\r
200     }\r
201 \r
202     return TRUE;\r
203 }\r
204 \r
205 LRESULT OnExitSizeMove( SnapData * snapData, HWND hWnd, WPARAM wParam, LPARAM lParam )\r
206 {\r
207     return 0;\r
208 }\r