(svn r1348) -Feature: resizable windows. Read the comment in window.h to find out
how the system works. All useful windows are already made resizable. Enjoy :) -Fix: fixed some GUI-glitches and flaws along the way
This commit is contained in:
155
window.c
155
window.c
@@ -51,23 +51,23 @@ void DispatchLeftClickEvent(Window *w, int x, int y) {
|
||||
w->wndproc(w, &e);
|
||||
|
||||
if (w->desc_flags & WDF_STD_BTN) {
|
||||
if (e.click.widget == 0) DeleteWindow(w);
|
||||
else {
|
||||
if (e.click.widget == 0) {
|
||||
DeleteWindow(w);
|
||||
} else {
|
||||
if (e.click.widget == 1) {
|
||||
if (_ctrl_pressed)
|
||||
StartWindowSizing(w);
|
||||
else
|
||||
StartWindowDrag(w);
|
||||
StartWindowDrag(w);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (w->desc_flags & WDF_STICKY_BUTTON) {
|
||||
if (e.click.widget == 2) {
|
||||
w->click_state ^= (1 << e.click.widget);
|
||||
w->flags4 ^= WF_STICKY;
|
||||
InvalidateWidget(w, e.click.widget);
|
||||
}
|
||||
|
||||
if (w->desc_flags & WDF_RESIZABLE && wi->type == WWT_RESIZEBOX) {
|
||||
StartWindowSizing(w);
|
||||
}
|
||||
|
||||
if (w->desc_flags & WDF_STICKY_BUTTON && wi->type == WWT_STICKYBOX) {
|
||||
w->click_state ^= (1 << e.click.widget);
|
||||
w->flags4 ^= WF_STICKY;
|
||||
InvalidateWidget(w, e.click.widget);
|
||||
}
|
||||
} else {
|
||||
w->wndproc(w, &e);
|
||||
@@ -223,6 +223,8 @@ void DeleteWindow(Window *w)
|
||||
|
||||
SetWindowDirty(w);
|
||||
|
||||
free(w->widget);
|
||||
|
||||
v = --_last_window;
|
||||
count = (byte*)v - (byte*)w;
|
||||
memcpy(w, w + 1, count);
|
||||
@@ -313,6 +315,31 @@ static Window *ForceFindDeletableWindow(void)
|
||||
}
|
||||
}
|
||||
|
||||
bool IsWindowOfPrototype(Window *w, const Widget *widget)
|
||||
{
|
||||
return (w->original_widget == widget);
|
||||
}
|
||||
|
||||
/* Copies 'widget' to 'w->widget' */
|
||||
void AssignWidgetToWindow(Window *w, const Widget *widget)
|
||||
{
|
||||
w->original_widget = widget;
|
||||
|
||||
if (widget != NULL) {
|
||||
const Widget *wi = widget;
|
||||
uint index = 1;
|
||||
while (wi->type != WWT_LAST) {
|
||||
wi++;
|
||||
index++;
|
||||
}
|
||||
|
||||
w->widget = malloc(sizeof(Widget) * index);
|
||||
memcpy(w->widget, widget, sizeof(Widget) * index);
|
||||
} else {
|
||||
w->widget = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
Window *AllocateWindow(
|
||||
int x,
|
||||
int y,
|
||||
@@ -373,7 +400,11 @@ Window *AllocateWindow(
|
||||
w->vscroll.count = 0;
|
||||
w->hscroll.pos = 0;
|
||||
w->hscroll.count = 0;
|
||||
w->widget = widget;
|
||||
AssignWidgetToWindow(w, widget);
|
||||
w->resize.width = width;
|
||||
w->resize.height = height;
|
||||
w->resize.step_width = 1;
|
||||
w->resize.step_height = 1;
|
||||
|
||||
{
|
||||
int i;
|
||||
@@ -898,6 +929,89 @@ bool HandleWindowDragging()
|
||||
w->left = nx;
|
||||
w->top = ny;
|
||||
|
||||
SetWindowDirty(w);
|
||||
return false;
|
||||
} else if (w->flags4 & WF_SIZING) {
|
||||
WindowEvent e;
|
||||
int x, y;
|
||||
|
||||
/* Stop the sizing if the left mouse button was released */
|
||||
if (!_left_button_down) {
|
||||
w->flags4 &= ~WF_SIZING;
|
||||
break;
|
||||
}
|
||||
|
||||
x = _cursor.pos.x - _drag_delta.x;
|
||||
y = _cursor.pos.y - _drag_delta.y;
|
||||
|
||||
/* X and Y has to go by step.. calculate it */
|
||||
if (w->resize.step_width > 1)
|
||||
x = x - (x % (int)w->resize.step_width);
|
||||
|
||||
if (w->resize.step_height > 1)
|
||||
y = y - (y % (int)w->resize.step_height);
|
||||
|
||||
/* Check if we don't go below the minimum set size */
|
||||
if ((int)w->width + x < (int)w->resize.width)
|
||||
x = w->resize.width - w->width;
|
||||
if ((int)w->height + y < (int)w->resize.height)
|
||||
y = w->resize.height - w->height;
|
||||
|
||||
/* Window already on size */
|
||||
if (x == 0 && y == 0)
|
||||
return false;
|
||||
|
||||
/* Now find the new cursor pos.. this is NOT _cursor, because
|
||||
we move in steps. */
|
||||
_drag_delta.x += x;
|
||||
_drag_delta.y += y;
|
||||
|
||||
SetWindowDirty(w);
|
||||
|
||||
/* Scroll through all the windows and update the widgets if needed */
|
||||
{
|
||||
Widget *wi = w->widget;
|
||||
bool resize_height = false;
|
||||
bool resize_width = false;
|
||||
|
||||
while (wi->type != WWT_LAST) {
|
||||
if (wi->resize_flag != RESIZE_NONE) {
|
||||
/* Resize this widget */
|
||||
if (wi->resize_flag & RESIZE_LEFT) {
|
||||
wi->left += x;
|
||||
resize_width = true;
|
||||
}
|
||||
if (wi->resize_flag & RESIZE_RIGHT) {
|
||||
wi->right += x;
|
||||
resize_width = true;
|
||||
}
|
||||
|
||||
if (wi->resize_flag & RESIZE_TOP) {
|
||||
wi->top += y;
|
||||
resize_height = true;
|
||||
}
|
||||
if (wi->resize_flag & RESIZE_BOTTOM) {
|
||||
wi->bottom += y;
|
||||
resize_height = true;
|
||||
}
|
||||
}
|
||||
wi++;
|
||||
}
|
||||
|
||||
/* We resized at least 1 widget, so let's rezise the window totally */
|
||||
if (resize_width)
|
||||
w->width = x + w->width;
|
||||
if (resize_height)
|
||||
w->height = y + w->height;
|
||||
}
|
||||
|
||||
e.event = WE_RESIZE;
|
||||
e.sizing.size.x = x + w->width;
|
||||
e.sizing.size.y = y + w->height;
|
||||
e.sizing.diff.x = x;
|
||||
e.sizing.diff.y = y;
|
||||
w->wndproc(w, &e);
|
||||
|
||||
SetWindowDirty(w);
|
||||
return false;
|
||||
}
|
||||
@@ -911,8 +1025,10 @@ Window *StartWindowDrag(Window *w)
|
||||
{
|
||||
w->flags4 |= WF_DRAGGING;
|
||||
_dragging_window = true;
|
||||
|
||||
_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;
|
||||
@@ -922,7 +1038,10 @@ Window *StartWindowSizing(Window *w)
|
||||
{
|
||||
w->flags4 |= WF_SIZING;
|
||||
_dragging_window = true;
|
||||
_cursorpos_drag_start = _cursor.pos;
|
||||
|
||||
_drag_delta.x = _cursor.pos.x;
|
||||
_drag_delta.y = _cursor.pos.y;
|
||||
|
||||
w = BringWindowToFront(w);
|
||||
DeleteWindowById(WC_DROPDOWN_MENU, 0);
|
||||
return w;
|
||||
@@ -1090,8 +1209,8 @@ static void HandleKeypress(uint32 key)
|
||||
{
|
||||
Window *w;
|
||||
WindowEvent we;
|
||||
/* Stores if a window with a textfield for typing is open
|
||||
* If this is the case, keypress events are only passed to windows with text fields and
|
||||
/* Stores if a window with a textfield for typing is open
|
||||
* If this is the case, keypress events are only passed to windows with text fields and
|
||||
* to thein this main toolbar. */
|
||||
bool query_open = false;
|
||||
|
||||
@@ -1369,7 +1488,7 @@ void DeleteNonVitalWindows()
|
||||
}
|
||||
}
|
||||
|
||||
/* It is possible that a stickied window gets to a position where the
|
||||
/* It is possible that a stickied window gets to a position where the
|
||||
* 'close' button is outside the gaming area. You cannot close it then; except
|
||||
* with this function. It closes all windows calling the standard function,
|
||||
* then, does a little hacked loop of closing all stickied windows. Note
|
||||
|
Reference in New Issue
Block a user