From 872f49ae8a8f1051cce2ed3c5cdc66fb654ade41 Mon Sep 17 00:00:00 2001 From: tron Date: Wed, 10 Nov 2004 21:14:16 +0000 Subject: (svn r538) -Feature: Windows snap at each other This is inspired by [1063636]. --- lang/english.txt | 2 + lang/german.txt | 2 + settings.c | 1 + settings_gui.c | 1 + variables.h | 1 + window.c | 126 ++++++++++++++++++++++++++++++++++++++++++------------- 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; -- cgit v1.2.3-70-g09d2