summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lang/english.txt2
-rw-r--r--lang/german.txt2
-rw-r--r--settings.c1
-rw-r--r--settings_gui.c1
-rw-r--r--variables.h1
-rw-r--r--window.c126
6 files changed, 105 insertions, 28 deletions
diff --git a/lang/english.txt b/lang/english.txt
index 1c5eb1441..6883ef23a 100644
--- a/lang/english.txt
+++ b/lang/english.txt
@@ -1040,6 +1040,8 @@ STR_CONFIG_PATCHES_TOOLBAR_POS :{LTBLUE}Position of main toolbar: {ORANGE}{STR
STR_CONFIG_PATCHES_TOOLBAR_POS_LEFT :Left
STR_CONFIG_PATCHES_TOOLBAR_POS_CENTER :Centre
STR_CONFIG_PATCHES_TOOLBAR_POS_RIGHT :Right
+STR_CONFIG_PATCHES_SNAP_RADIUS :{LTBLUE}Window snap radius: {ORANGE}{STRING} px
+STR_CONFIG_PATCHES_SNAP_RADIUS_DISABLED :{LTBLUE}Window snap radius: {ORANGE}disabled
STR_CONFIG_PATCHES_GUI :{BLACK}Interface
STR_CONFIG_PATCHES_CONSTRUCTION :{BLACK}Construction
diff --git a/lang/german.txt b/lang/german.txt
index 9b57fcf68..649ee8d20 100644
--- a/lang/german.txt
+++ b/lang/german.txt
@@ -1040,6 +1040,8 @@ STR_CONFIG_PATCHES_TOOLBAR_POS :{LTBLUE}Position der Haupttoolbar: {ORANGE}{
STR_CONFIG_PATCHES_TOOLBAR_POS_LEFT :Links
STR_CONFIG_PATCHES_TOOLBAR_POS_CENTER :Mitte
STR_CONFIG_PATCHES_TOOLBAR_POS_RIGHT :Rechts
+STR_CONFIG_PATCHES_SNAP_RADIUS :{LTBLUE}Fenster schnappen aneinander, wenn näher als: {ORANGE}{STRING} px
+STR_CONFIG_PATCHES_SNAP_RADIUS_DISABLED :{LTBLUE}Fenster schnappen aneinander, wenn näher als: {ORANGE}ausgeschaltet
STR_CONFIG_PATCHES_GUI :{BLACK}Oberfläche
STR_CONFIG_PATCHES_CONSTRUCTION :{BLACK}Konstruktion
diff --git a/settings.c b/settings.c
index 9171a6875..b85cb69f6 100644
--- a/settings.c
+++ b/settings.c
@@ -829,6 +829,7 @@ static const SettingDesc patch_settings[] = {
{"realistic_acceleration",SDT_BOOL, (void*)false, (void*)offsetof(Patches, realistic_acceleration), NULL},
{"toolbar_pos", SDT_UINT8, (void*)0, (void*)offsetof(Patches, toolbar_pos), NULL},
+ {"window_snap_radius", SDT_UINT8, (void*)10, (void*)offsetof(Patches, window_snap_radius), NULL},
{"max_trains", SDT_UINT8, (void*)80, (void*)offsetof(Patches, max_trains), NULL},
{"max_roadveh", SDT_UINT8, (void*)80, (void*)offsetof(Patches, max_roadveh), NULL},
diff --git a/settings_gui.c b/settings_gui.c
index 4e7501305..f84c0e140 100644
--- a/settings_gui.c
+++ b/settings_gui.c
@@ -572,6 +572,7 @@ static const PatchEntry _patches_ui[] = {
{PE_UINT8, 0, STR_CONFIG_PATCHES_ERRMSG_DURATION, &_patches.errmsg_duration, 0, 20, 1, NULL},
{PE_UINT8, PF_MULTISTRING, STR_CONFIG_PATCHES_TOOLBAR_POS, &_patches.toolbar_pos, 0, 2, 1, &v_PositionMainToolbar},
+ {PE_UINT8, PF_0ISDIS, STR_CONFIG_PATCHES_SNAP_RADIUS, &_patches.window_snap_radius, 1, 32, 1, NULL},
{PE_BOOL, 0, STR_CONFIG_PATCHES_INVISIBLE_TREES, &_patches.invisible_trees, 0, 1, 1, &InvisibleTreesActive},
};
diff --git a/variables.h b/variables.h
index ae14c6136..bf0035fec 100644
--- a/variables.h
+++ b/variables.h
@@ -114,6 +114,7 @@ typedef struct Patches {
bool invisible_trees; // don't show trees when buildings are transparent
uint8 toolbar_pos; // position of toolbars, 0=left, 1=center, 2=right
+ uint8 window_snap_radius; // Windows snap at each other if closer than this
byte max_trains; //max trains in game per player (these are 8bit because the unitnumber field can't hold more)
byte max_roadveh; //max trucks in game per player
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;