Drag touching edges together (WB)
authorH.G. Muller <h.g.muller@hccnet.nl>
Thu, 16 Jan 2014 21:54:32 +0000 (22:54 +0100)
committerH.G. Muller <h.g.muller@hccnet.nl>
Sat, 18 Jan 2014 23:01:58 +0000 (00:01 +0100)
When an auxiliary window is dragged by an edge, the snap code now checks
if that edge was touching another window. If so, that other window is sized
to keep touching the dragged edge. Unless it was also touching the main
window.

winboard/wsnap.c

index 5492e80..683aa15 100644 (file)
@@ -64,14 +64,22 @@ static void AddSnapRectangle( SnapData * sd, RECT * rc )
     AddSnapPoint( sd->y_grid, &sd->y_grid_len, rc->bottom );\r
 }\r
 \r
+static RECT activeRect, mainRect;\r
+static int side, loc; // code for edge we were dragging, and its latest coordinate\r
+\r
 static void AddSnapWindow( HWND hWndCaller, SnapData * sd, HWND hWndSnapWindow )\r
 {\r
-    if( hWndSnapWindow != NULL && hWndCaller != hWndSnapWindow && IsWindowVisible(hWndSnapWindow) ) {\r
+    if( hWndSnapWindow != NULL && IsWindowVisible(hWndSnapWindow) ) {\r
         RECT rc;\r
 \r
         GetWindowRect( hWndSnapWindow, &rc );\r
+       if(hWndSnapWindow == hwndMain) mainRect = rc;\r
 \r
-        AddSnapRectangle( sd, &rc );\r
+       if(hWndCaller != hWndSnapWindow) {\r
+            AddSnapRectangle( sd, &rc );\r
+       } else {\r
+           activeRect = rc; // [HGM] glue: remember original geometry of dragged window\r
+       }\r
     }\r
 }\r
 \r
@@ -101,6 +109,7 @@ LRESULT OnEnterSizeMove( SnapData * snapData, HWND hWnd, WPARAM wParam, LPARAM l
 \r
     snapData->x_grid_len = 0;\r
     snapData->y_grid_len = 0;\r
+    side = 0;\r
 \r
     /* Add desktop area */\r
     if( SystemParametersInfo( SPI_GETWORKAREA, 0, &rc, 0 ) ) {\r
@@ -157,7 +166,7 @@ LRESULT OnSizing( SnapData * snapData, HWND hWnd, WPARAM wParam, LPARAM lParam )
     switch( wParam ) {\r
     case WMSZ_BOTTOM:\r
         AdjustToSnapPoint( snapData->y_grid, snapData->y_grid_len, lprc->bottom, &snap_size_y, &delta_y );\r
-        lprc->bottom += delta_y;\r
+        lprc->bottom += delta_y; side = 4; loc = lprc->bottom;\r
         break;\r
     case WMSZ_BOTTOMLEFT:\r
         AdjustToSnapPoint( snapData->y_grid, snapData->y_grid_len, lprc->bottom, &snap_size_y, &delta_y );\r
@@ -173,15 +182,15 @@ LRESULT OnSizing( SnapData * snapData, HWND hWnd, WPARAM wParam, LPARAM lParam )
         break;\r
     case WMSZ_LEFT:\r
         AdjustToSnapPoint( snapData->x_grid, snapData->x_grid_len, lprc->left, &snap_size_x, &delta_x );\r
-        lprc->left += delta_x;\r
+        lprc->left += delta_x; side = 1; loc = lprc->left;\r
         break;\r
     case WMSZ_RIGHT:\r
         AdjustToSnapPoint( snapData->x_grid, snapData->x_grid_len, lprc->right, &snap_size_x, &delta_x );\r
-        lprc->right += delta_x;\r
+        lprc->right += delta_x; side = 2; loc = lprc->right;\r
         break;\r
     case WMSZ_TOP:\r
         AdjustToSnapPoint( snapData->y_grid, snapData->y_grid_len, lprc->top, &snap_size_y, &delta_y );\r
-        lprc->top += delta_y;\r
+        lprc->top += delta_y; side = 3; loc = lprc->top;\r
         break;\r
     case WMSZ_TOPLEFT:\r
         AdjustToSnapPoint( snapData->y_grid, snapData->y_grid_len, lprc->top, &snap_size_y, &delta_y );\r
@@ -202,7 +211,60 @@ LRESULT OnSizing( SnapData * snapData, HWND hWnd, WPARAM wParam, LPARAM lParam )
     return TRUE;\r
 }\r
 \r
+static int Adjust( LONG *data, int new, int old , int vertical)\r
+{\r
+    // protect edges that also touch main window\r
+    if(!vertical && (old == mainRect.left || old == mainRect.right))  return 0;\r
+    if( vertical && (old == mainRect.top  || old == mainRect.bottom)) return 0;\r
+    // if the coordinate was the same as the old, now make it the same as the new edge position\r
+    if(*data == old) { *data = new; return 1; }\r
+    return 0;\r
+}\r
+\r
+static void KeepTouching( int side, int new, int old, HWND hWnd )\r
+{   // if the mentioned window was touching on the moved edge, move its touching edge too\r
+    if( IsWindowVisible(hWnd) ) {\r
+        RECT rc;\r
+       int i = 0;\r
+\r
+        GetWindowRect( hWnd, &rc );\r
+\r
+       switch(side) { // figure out which edge we might need to drag along (if any)\r
+         case 1: i = Adjust(&rc.right,  new, old, 0); break;\r
+         case 2: i = Adjust(&rc.left,   new, old, 0); break;\r
+         case 3: i = Adjust(&rc.bottom, new, old, 1); break;\r
+         case 4: i = Adjust(&rc.top,    new, old, 1); break;\r
+       }\r
+\r
+       if(i) { // the correct edge was touching, and is adjusted\r
+           SetWindowPos(hWnd, HWND_TOP, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOZORDER );\r
+       }\r
+    }\r
+}\r
+\r
 LRESULT OnExitSizeMove( SnapData * snapData, HWND hWnd, WPARAM wParam, LPARAM lParam )\r
 {\r
+    if(side && hWnd != hwndMain) { // [HGM] glue: we have been sizing, by dragging an edge\r
+       int *grid = (side > 2 ? snapData->y_grid : snapData->x_grid);\r
+       int i, pos = -1, len = (side > 2 ? snapData->y_grid_len : snapData->x_grid_len);\r
+\r
+       switch(side) {\r
+         case 1: pos = activeRect.left; break;\r
+         case 2: pos = activeRect.right; break;\r
+         case 3: pos = activeRect.top; break;\r
+         case 4: pos = activeRect.bottom; break;\r
+       }\r
+\r
+       for(i=0; i<len; i++) {\r
+           if(grid[i] == pos) break; // the dragged side originally touched another auxiliary window\r
+       }\r
+\r
+       if(i < len) { // we were touching another sticky window: figure out how, and adapt it if needed\r
+               KeepTouching(side, loc, pos, moveHistoryDialog);\r
+               KeepTouching(side, loc, pos, evalGraphDialog);\r
+               KeepTouching(side, loc, pos, engineOutputDialog);\r
+               KeepTouching(side, loc, pos, gameListDialog);\r
+       }\r
+    }\r
     return 0;\r
 }\r