summaryrefslogtreecommitdiff
path: root/window.c
diff options
context:
space:
mode:
authortron <tron@openttd.org>2004-11-10 21:14:16 +0000
committertron <tron@openttd.org>2004-11-10 21:14:16 +0000
commit872f49ae8a8f1051cce2ed3c5cdc66fb654ade41 (patch)
treeae3d4187734dda8d016a4515d4b9b21427c4be08 /window.c
parent603618a75b6b55ca46ce015d97d462e2b7f83fb7 (diff)
downloadopenttd-872f49ae8a8f1051cce2ed3c5cdc66fb654ade41.tar.xz
(svn r538) -Feature: Windows snap at each other
This is inspired by [1063636].
Diffstat (limited to 'window.c')
-rw-r--r--window.c126
1 files changed, 98 insertions, 28 deletions
diff --git a/window.c b/window.c
index b0dd73a3e..13f1bdaad 100644
--- a/window.c
+++ b/window.c
@@ -5,6 +5,9 @@
#include "viewport.h"
#include "console.h"
+// delta between mouse cursor and upper left corner of dragged window
+static Point _drag_delta;
+
void HandleButtonClick(Window *w, byte widget)
{
w->click_state |= (1 << widget);
@@ -691,50 +694,116 @@ bool HandlePopupMenu()
bool HandleWindowDragging()
{
Window *w;
- int x, y, t;
-
// Get out immediately if no window is being dragged at all.
if (!_dragging_window)
return true;
// Otherwise find the window...
- for(w=_windows; w != _last_window; w++) {
- if (w->flags4&(WF_DRAGGING|WF_SIZING)) {
+ for (w = _windows; w != _last_window; w++) {
+ if (w->flags4 & WF_DRAGGING) {
+ const Window *v;
+ int x;
+ int y;
+ int nx;
+ int ny;
// Stop the dragging if the left mouse button was released
if (!_left_button_down) {
- w->flags4 &= ~(WF_DRAGGING | WF_SIZING);
+ w->flags4 &= ~WF_DRAGGING;
break;
}
- // Otherwise calculate the delta position.
- x = _cursor.pos.x;
- y = clamp2(_cursor.pos.y, 23, _screen.height-12);
- t = _cursorpos_drag_start.x; _cursorpos_drag_start.x = x; x-=t;
- t = _cursorpos_drag_start.y; _cursorpos_drag_start.y = y; y-=t;
+ SetWindowDirty(w);
- // No movement?
- if (x == 0 && y == 0)
- return false;
+ x = _cursor.pos.x + _drag_delta.x;
+ y = _cursor.pos.y + _drag_delta.y;
+ nx = x;
+ ny = y;
+
+ if (_patches.window_snap_radius != 0) {
+ uint hsnap = _patches.window_snap_radius;
+ uint vsnap = _patches.window_snap_radius;
+ uint delta;
+
+ // Snap at screen borders
+ // Left screen border
+ delta = abs(x);
+ if (delta <= hsnap) {
+ nx = 0;
+ hsnap = delta;
+ }
- // Mark the old position dirty
- SetWindowDirty(w);
+ // Right screen border
+ delta = abs(_screen.width - x - w->width);
+ if (delta <= hsnap) {
+ nx = _screen.width - w->width;
+ hsnap = delta;
+ }
- if (w->flags4 & WF_SIZING) {
- // Size the window
- w->width += x;
- w->height += y;
- } else {
- // Move the window and viewport
- w->left += x;
- w->top += y;
- if (w->viewport) {
- w->viewport->left += x;
- w->viewport->top += y;
+ // Top of screen
+ delta = abs(y);
+ if (delta <= vsnap) {
+ ny = 0;
+ vsnap = delta;
+ }
+
+ // Bottom of screen
+ delta = abs(_screen.height - y - w->height);
+ if (delta <= vsnap) {
+ ny = _screen.height - w->height;
+ vsnap = delta;
+ }
+
+ // Snap at other windows
+ for (v = _windows; v != _last_window; ++v) {
+ if (v == w) continue; // Don't snap at yourself
+
+ if (y + w->height > v->top && y < v->top + v->height) {
+ // Your left border <-> other right border
+ delta = abs(v->left + v->width - x);
+ if (delta <= hsnap) {
+ nx = v->left + v->width;
+ hsnap = delta;
+ }
+
+ // Your right border <-> other left border
+ delta = abs(v->left - x - w->width);
+ if (delta <= hsnap) {
+ nx = v->left - w->width;
+ hsnap = delta;
+ }
+ }
+
+ if (x + w->width > v->left && x < v->left + v->width) {
+ // Your top border <-> other bottom border
+ delta = abs(v->top + v->height - y);
+ if (delta <= vsnap) {
+ ny = v->top + v->height;
+ vsnap = delta;
+ }
+
+ // Your bottom border <-> other top border
+ delta = abs(v->top - y - w->height);
+ if (delta <= vsnap) {
+ ny = v->top - w->height;
+ vsnap = delta;
+ }
+ }
}
}
- // And also mark the new position dirty.
+ // Make sure the window doesn't leave the screen
+ // 13 is the height of the title bar
+ nx = clamp(nx, 13 - w->width, _screen.width - 13);
+ ny = clamp(ny, 0, _screen.height - 13);
+
+ if (w->viewport != NULL) {
+ w->viewport->left += nx - w->left;
+ w->viewport->top += ny - w->top;
+ }
+ w->left = nx;
+ w->top = ny;
+
SetWindowDirty(w);
return false;
}
@@ -748,7 +817,8 @@ Window *StartWindowDrag(Window *w)
{
w->flags4 |= WF_DRAGGING;
_dragging_window = true;
- _cursorpos_drag_start = _cursor.pos;
+ _drag_delta.x = w->left - _cursor.pos.x;
+ _drag_delta.y = w->top - _cursor.pos.y;
w = BringWindowToFront(w);
DeleteWindowById(WC_DROPDOWN_MENU, 0);
return w;