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