Skip to content

Commit

Permalink
Implementing resizable windows
Browse files Browse the repository at this point in the history
  • Loading branch information
ZILtoid1991 committed May 26, 2024
1 parent b0b522b commit fa5ddfe
Show file tree
Hide file tree
Showing 4 changed files with 189 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ public class StyleSheet{

drawParameters["defDialogPadding"] = 10;

drawParameters["windowMinimumSizes"] = 64;

pattern["blackDottedLine"] = [0x1f, 0x1f, 0x10, 0x10];
}
/**
Expand Down
182 changes: 169 additions & 13 deletions pixelperfectengine/src/pixelperfectengine/concrete/window.d
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,17 @@ public class Window : ElementContainer, Focusable, MouseEventReceptor {
//public int header;//, sizeX, sizeY;
protected int moveX, moveY; ///Relative x and y coordinates for drag events
protected uint flags; ///Stores various flags
protected static enum IS_ACTIVE = 1 << 0;
protected static enum NEEDS_FULL_UPDATE = 1 << 1;
protected static enum HEADER_UPDATE = 1 << 2;
protected static enum IS_MOVED = 1 << 3;
protected static enum IS_RESIZED = 1 << 4;
protected static enum IS_RESIZED_L = 1 << 5;
protected static enum IS_RESIZED_T = 1 << 6;
protected static enum IS_RESIZED_B = 1 << 7;
protected static enum IS_RESIZED_R = 1 << 8;
protected static enum IS_RESIZABLE_BY_MOUSE = 1 << 9;
protected static enum IS_ACTIVE = 1 << 0; ///Set if window is active
protected static enum NEEDS_FULL_UPDATE = 1 << 1;///Set if window needs full redraw (Deprecated)
protected static enum HEADER_UPDATE = 1 << 2; ///Set if header needs redraw (Deprecated)
protected static enum IS_MOVED = 1 << 3; ///Set if window is being moved
protected static enum IS_RESIZED = 0xF0; ///Used to test if window is being resized or not
protected static enum IS_RESIZED_L = 1 << 4; ///Set if window is being resized by the left edge
protected static enum IS_RESIZED_T = 1 << 5; ///Set if window is being resized by the top edge
protected static enum IS_RESIZED_B = 1 << 6; ///Set if window is being resized by the bottom edge
protected static enum IS_RESIZED_R = 1 << 7; ///Set if window is being resized by the right edge
protected static enum IS_RESIZABLE_BY_MOUSE_H = 1 << 8;///Set if window is horizontally resizable
protected static enum IS_RESIZABLE_BY_MOUSE_V = 1 << 9;///Set if window is vertically resizable
//protected bool fullUpdate; ///True if window needs full redraw
//protected bool isActive; ///True if window is currently active
//protected bool headerUpdate; ///True if needs header update
Expand Down Expand Up @@ -242,7 +243,7 @@ public class Window : ElementContainer, Focusable, MouseEventReceptor {
drawTextSL(headerArea, title, Point(0,0));
}
///Returns true if the window is focused
public @property bool active() @safe @nogc pure nothrow {
public @property bool active() @safe @nogc pure nothrow const {
return flags & IS_ACTIVE;
}
///Sets the IS_ACTIVE flag to the given value
Expand All @@ -256,15 +257,34 @@ public class Window : ElementContainer, Focusable, MouseEventReceptor {
}
return active();
}
public @property bool resizableH() @safe @nogc pure nothrow const {
return flags & IS_RESIZABLE_BY_MOUSE_H ? true : false;
}
public @property bool resizableH(bool val) @safe @nogc pure nothrow {
if (val) flags |= IS_RESIZABLE_BY_MOUSE_H;
else flags &= ~IS_RESIZABLE_BY_MOUSE_H;
return flags & IS_RESIZABLE_BY_MOUSE_H ? true : false;
}
public @property bool resizableV() @safe @nogc pure nothrow const {
return flags & IS_RESIZABLE_BY_MOUSE_V ? true : false;
}
public @property bool resizableV(bool val) @safe @nogc pure nothrow {
if (val) flags |= IS_RESIZABLE_BY_MOUSE_V;
else flags &= ~IS_RESIZABLE_BY_MOUSE_V;
return flags & IS_RESIZABLE_BY_MOUSE_V ? true : false;
}
public @property bool isResized() @safe @nogc pure nothrow const {
return flags & IS_RESIZED ? true : false;
}
///Returns whether the window is moved or not
public @property bool isMoved() @safe @nogc pure nothrow {
public @property bool isMoved() @safe @nogc pure nothrow const {
return flags & IS_MOVED ? true : false;
}
///Sets whether the window is moved or not
public @property bool isMoved(bool val) @safe @nogc pure nothrow {
if (val) flags |= IS_MOVED;
else flags &= ~IS_MOVED;
return isMoved();
return flags & IS_MOVED ? true : false;
}
///Sets the title of the window
public void setTitle(Text s) @trusted {
Expand Down Expand Up @@ -492,6 +512,7 @@ public class Window : ElementContainer, Focusable, MouseEventReceptor {
public void passMCE(MouseEventCommons mec, MouseClickEvent mce) {
if (!isMoved) {
lastMousePos = Point(mce.x - position.left, mce.y - position.top);
//WindowElement block
foreach (WindowElement we; elements) {
if (we.getPosition.isBetween(lastMousePos)) {
lastMouseEventTarget = we;
Expand All @@ -501,6 +522,7 @@ public class Window : ElementContainer, Focusable, MouseEventReceptor {
return;
}
}
//Header button block
foreach (ISmallButton sb; smallButtons) {
WindowElement we = cast(WindowElement)sb;
if (we.getPosition.isBetween(lastMousePos)) {
Expand All @@ -511,6 +533,61 @@ public class Window : ElementContainer, Focusable, MouseEventReceptor {
return;
}
}
//Resize event block
if (resizableH) {
if (mce.x - 2 <= position.left) { ///Left edge
if (resizableV) {
if (mce.y - 2 <= position.top) {///Top-left corner
flags |= IS_RESIZED_T | IS_RESIZED_L;
handler.initDragEvent(this);
return;
} else if (mce.y >= position.bottom - 2) {///Bottom-left corner
flags |= IS_RESIZED_B | IS_RESIZED_L;
handler.initDragEvent(this);
return;
}
}
flags |= IS_RESIZED_L;///Left edge in general
handler.initDragEvent(this);
return;
} else if (mce.x >= position.right - 2) {///Right edge
if (resizableV) {
if (mce.y - 2 <= position.top) {///Top-right corner
flags |= IS_RESIZED_T | IS_RESIZED_R;
handler.initDragEvent(this);
return;
} else if (mce.y >= position.bottom - 2) {///Bottom-right corner
flags |= IS_RESIZED_B | IS_RESIZED_R;
handler.initDragEvent(this);
return;
}
}
flags |= IS_RESIZED_R;///Right edge in general
handler.initDragEvent(this);
return;
} else if (resizableV) {///Top or bottom edge
if (mce.y - 2 <= position.top) {
flags |= IS_RESIZED_T;
handler.initDragEvent(this);
return;
} else if(mce.y >= position.bottom - 2) {
flags |= IS_RESIZED_B;
handler.initDragEvent(this);
return;
}
}
} else if (resizableV) {///The previous one already took care of the corner cases, so we won't have to deal with them here
if (mce.y - 2 <= position.top) {
flags |= IS_RESIZED_T;
handler.initDragEvent(this);
return;
} else if(mce.y >= position.bottom - 2) {
flags |= IS_RESIZED_B;
handler.initDragEvent(this);
return;
}
}
//Move even block
const int headerHeight = getStyleSheet().drawParameters["WindowHeaderHeight"];
if (lastMousePos.y < headerHeight) {
isMoved = true;
Expand All @@ -519,6 +596,7 @@ public class Window : ElementContainer, Focusable, MouseEventReceptor {
lastMouseEventTarget = null;
} else if (!mce.state) {
isMoved = false;
flags &= ~IS_MOVED;
}
}
///Passes mouse move event
Expand All @@ -529,6 +607,44 @@ public class Window : ElementContainer, Focusable, MouseEventReceptor {
relMove(mme.relX, mme.relY);
else
isMoved = false;
} else if (isResized) {
const Box safePosition = position;
const int windowMinSize = getStyleSheet().drawParameters["windowMinimumSizes"];
if (mme.buttonState) {
switch (flags & IS_RESIZED) {
case IS_RESIZED_L:
position.left += mme.relX;
break;
case IS_RESIZED_R:
position.right += mme.relX;
break;
case IS_RESIZED_T:
position.top += mme.relY;
break;
case IS_RESIZED_B:
position.bottom += mme.relY;
break;
case IS_RESIZED_L | IS_RESIZED_T:
position.left += mme.relX;
position.top += mme.relY;
break;
case IS_RESIZED_L | IS_RESIZED_B:
position.left += mme.relX;
position.bottom += mme.relY;
break;
case IS_RESIZED_R | IS_RESIZED_T:
position.right += mme.relX;
position.top += mme.relY;
break;
case IS_RESIZED_R | IS_RESIZED_B:
position.right += mme.relX;
position.bottom += mme.relY;
break;
default: break;
}
if (position.width < windowMinSize || position.height < windowMinSize) position = safePosition;
else draw();
} else flags &= ~IS_RESIZED;
} else if (lastMouseEventTarget) {
mme.x = lastMousePos.x;
mme.y = lastMousePos.y;
Expand All @@ -546,6 +662,46 @@ public class Window : ElementContainer, Focusable, MouseEventReceptor {
return;
}
}
if (!position.isBetween(mme.x, mme.y)) {
if (handler.getCursor != CursorType.Arrow) handler.resetCursor();
} else {
if (resizableH) {
if (mme.x - 2 <= position.left) { ///Left edge
if (resizableV) {
if (mme.y - 2 <= position.top) {///Top-left corner
handler.setCursor(CursorType.ResizeNWSE);
return;
} else if (mme.y >= position.bottom - 2) {///Bottom-left corner
handler.setCursor(CursorType.ResizeNESW);
return;
}
}
handler.setCursor(CursorType.ResizeWE);///Left edge in general
return;
} else if (mme.x >= position.right - 2) {///Right edge
if (resizableV) {
if (mme.y - 2 <= position.top) {///Top-right corner
handler.setCursor(CursorType.ResizeNESW);
return;
} else if (mme.y >= position.bottom - 2) {///Bottom-right corner
handler.setCursor(CursorType.ResizeNWSE);
return;
}
}
handler.setCursor(CursorType.ResizeWE);///Right edge in general
return;
} else if ((mme.y - 2 <= position.top || mme.y >= position.bottom - 2) && resizableV) {///Top or bottom edge
handler.setCursor(CursorType.ResizeNS);
return;
}
} else if (resizableV) {///The previous one already took care of the corner cases, so we won't have to deal with them here
if (mme.y - 2 <= position.top || mme.y >= position.bottom - 2) {///Top or bottom edge
handler.setCursor(CursorType.ResizeNS);
return;
}
}
if (handler.getCursor != CursorType.Arrow) handler.resetCursor();
}
}
}
///Passes mouse scroll event
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ public class WindowHandler : InputListener, MouseListener, PopUpHandler {
SDL_SetCursor(sdlCursor);
return cursor;
}
public void resetCursor() {
setCursor(CursorType.Arrow);
}
/**
* Returns the current cursor type.
*/
Expand Down
15 changes: 15 additions & 0 deletions test3/app.d
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ public class TestWindow : Window {
Button btn_messageDialog;
Button btn_addElem;
Button btn_subMenu;
Button btn_resizeTest;
VertScrollBar vScrollBarTest;
Label singleLineLabel;
Label multiLineLabel;
Expand Down Expand Up @@ -161,6 +162,9 @@ public class TestWindow : Window {
btn_subMenu = new Button("Submenu test", "", Box.bySize(300, 95, 70, 20));
btn_subMenu.onMouseLClick = &btn_subMenu_onClick;
addElement(btn_subMenu);
btn_resizeTest = new Button("Window resize", "", Box.bySize(300, 120, 70, 20));
btn_resizeTest.onMouseLClick = &btn_resizeTest_onClick;
addElement(btn_resizeTest);

multiLineDialog = lang["multilinedialog"];
}
Expand Down Expand Up @@ -191,6 +195,9 @@ public class TestWindow : Window {
menutree[2] ~= new PopUpMenuElement("", "Submenu 3/3");
handler.addPopUpElement(new PopUpMenu(menutree, "", null));
}
private void btn_resizeTest_onClick(Event ev) {
handler.addWindow(new ResizableWindow());
}
private void fileDialogEvent(Event ev) {
FileEvent fe = cast(FileEvent)ev;
writeln(fe.path);
Expand All @@ -200,4 +207,12 @@ public class TestWindow : Window {
private void listView_onItemAdd(Event ev) {
writeln(ev);
}
}

public class ResizableWindow : Window {
public this() {
resizableH = true;
resizableV = true;
super(Box.bySize(0, 0, 200, 200), "Resizing test");
}
}

0 comments on commit fa5ddfe

Please sign in to comment.