Skip to content

Commit e4b6749

Browse files
committed
Add Window properties 'resizable', 'minWidth' and 'minHeight'
This allows to make windows not resizable and to set a minimum size. Fixes #125 and #158.
1 parent 7864b63 commit e4b6749

File tree

5 files changed

+103
-4
lines changed

5 files changed

+103
-4
lines changed

src/nigui.nim

+30
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,8 @@ type
234234
fMinimized: bool
235235
fAlwaysOnTop: bool
236236
fWidth, fHeight: int
237+
fMinWidth, fMinHeight: int
238+
fResizable: bool
237239
fClientWidth, fClientHeight: int
238240
fX, fY: int
239241
fControl: Control
@@ -705,6 +707,15 @@ method `width=`*(window: Window, width: int) {.base, locks: "unknown".}
705707
method height*(window: Window): int {.base.}
706708
method `height=`*(window: Window, height: int) {.base, locks: "unknown".}
707709

710+
method minWidth*(window: Window): int {.base.}
711+
method `minWidth=`*(window: Window, minWidth: int) {.base, locks: "unknown".}
712+
713+
method minHeight*(window: Window): int {.base.}
714+
method `minHeight=`*(window: Window, minHeight: int) {.base, locks: "unknown".}
715+
716+
method resizable*(window: Window): bool {.base.}
717+
method `resizable=`*(window: Window, resizable: bool) {.base, locks: "unknown".}
718+
708719
method clientWidth*(window: Window): int {.base.}
709720

710721
method clientHeight*(window: Window): int {.base.}
@@ -1443,6 +1454,7 @@ proc init(window: Window) =
14431454
window.fVisible = false
14441455
window.fWidth = 640 # do not trigger resize
14451456
window.height = 480 # trigger resize
1457+
window.resizable = true
14461458
window.fX = -1 # window will be centered on screen
14471459
window.fY = -1
14481460
window.title = getAppFilename().extractFilename().changeFileExt("")
@@ -1556,6 +1568,24 @@ method `height=`(window: Window, height: int) =
15561568
window.fHeight = height
15571569
# has to be extended by WindowImpl
15581570

1571+
method minWidth(window: Window): int = window.fMinWidth
1572+
1573+
method `minWidth=`(window: Window, minWidth: int) =
1574+
window.fMinWidth = minWidth
1575+
# has to be extended by WindowImpl
1576+
1577+
method minHeight(window: Window): int = window.fMinHeight
1578+
1579+
method `minHeight=`(window: Window, minHeight: int) =
1580+
window.fMinHeight = minHeight
1581+
# has to be extended by WindowImpl
1582+
1583+
method resizable(window: Window): bool = window.fResizable
1584+
1585+
method `resizable=`(window: Window, resizable: bool) =
1586+
window.fResizable = resizable
1587+
# has to be extended by WindowImpl
1588+
15591589
method clientWidth(window: Window): int = window.fClientWidth
15601590

15611591
method clientHeight(window: Window): int = window.fClientHeight

src/nigui/private/gtk3/gtk3.nim

+20-1
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,20 @@ type
103103
dummy13: cint
104104
dummy14: pointer
105105

106+
GdkGeometry* {.byCopy.} = object
107+
min_width*: cint
108+
min_height*: cint
109+
max_width*: cint
110+
max_height*: cint
111+
base_width*: cint
112+
base_height*: cint
113+
width_inc*: cint
114+
height_inc*: cint
115+
min_aspect*: cdouble
116+
max_aspect*: cdouble
117+
win_gravity*: cint
118+
119+
106120
converter gbool*(val: bool): Gboolean = ord(val).Gboolean
107121

108122
converter toBool*(val: Gboolean): bool = int(val) != 0
@@ -243,6 +257,9 @@ const
243257
GDK_WINDOW_TYPE_HINT_COMBO* = 12
244258
GDK_WINDOW_TYPE_HINT_DND* = 13
245259

260+
# GdkWindowHints
261+
GDK_HINT_MIN_SIZE* = 2
262+
246263

247264
# ----------------------------------------------------------------------------------------
248265
# General Gtk Procs
@@ -270,9 +287,11 @@ proc gtk_window_set_title*(window: pointer, title: cstring) {.importc, libgtk3.}
270287
proc gtk_window_set_transient_for*(window, parent: pointer) {.importc, libgtk3.}
271288
proc gtk_window_set_modal*(window: pointer, modal: cint) {.importc, libgtk3.}
272289
proc gtk_window_set_type_hint*(window: pointer, hint: cint) {.importc, libgtk3.}
273-
# proc gtk_window_set_default_size*(window: pointer, width, height: cint) {.importc, libgtk3.}
290+
proc gtk_window_set_default_size*(window: pointer, width, height: cint) {.importc, libgtk3.}
274291
proc gtk_window_resize*(window: pointer, width, height: cint) {.importc, libgtk3.}
275292
proc gtk_window_resize_to_geometry*(window: pointer, width, height: cint) {.importc, libgtk3.}
293+
proc gtk_window_set_resizable*(window: pointer, resizable: bool) {.importc, libgtk3.}
294+
proc gtk_window_set_geometry_hints*(window: pointer, geometry_widget: pointer, geometry: var GdkGeometry, geom_mask: cint) {.importc, libgtk3.}
276295
proc gtk_window_get_size*(window: pointer, width, height: var cint) {.importc, libgtk3.}
277296
proc gtk_window_get_position*(window: pointer, x, y: var cint) {.importc, libgtk3.}
278297
proc gtk_window_move*(window: pointer, x, y: cint) {.importc, libgtk3.}

src/nigui/private/gtk3/platform_impl.nim

+20-2
Original file line numberDiff line numberDiff line change
@@ -881,14 +881,32 @@ method `alwaysOnTop=`(window: WindowImpl, alwaysOnTop: bool) =
881881

882882
method `width=`*(window: WindowImpl, width: int) =
883883
procCall window.Window.`width=`(width)
884-
gtk_window_resize(window.fHandle, window.width.cint, window.height.cint)
884+
gtk_window_set_default_size(window.fHandle, window.width.cint, window.height.cint)
885885
window.fClientWidth = window.width
886886

887887
method `height=`*(window: WindowImpl, height: int) =
888888
procCall window.Window.`height=`(height)
889-
gtk_window_resize(window.fHandle, window.width.cint, window.height.cint)
889+
gtk_window_set_default_size(window.fHandle, window.width.cint, window.height.cint)
890890
window.fClientHeight = window.height
891891

892+
proc pUpdateMinSize(window: WindowImpl) =
893+
var geometry: GdkGeometry
894+
geometry.min_width = window.minWidth.cint
895+
geometry.min_height = window.minHeight.cint
896+
gtk_window_set_geometry_hints(window.fHandle, nil, geometry, GDK_HINT_MIN_SIZE)
897+
898+
method `minWidth=`(window: WindowImpl, minWidth: int) =
899+
procCall window.Window.`minWidth=`(minWidth)
900+
pUpdateMinSize(window)
901+
902+
method `minHeight=`(window: WindowImpl, minHeight: int) =
903+
procCall window.Window.`minHeight=`(minHeight)
904+
pUpdateMinSize(window)
905+
906+
method `resizable=`(window: WindowImpl, resizable: bool) =
907+
procCall window.Window.`resizable=`(resizable)
908+
gtk_window_set_resizable(window.fHandle, resizable)
909+
892910
proc pUpdatePosition(window: WindowImpl) = gtk_window_move(window.fHandle, window.x.cint, window.y.cint)
893911

894912
method `x=`(window: WindowImpl, x: int) =

src/nigui/private/windows/platform_impl.nim

+23-1
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,12 @@ proc pWindowWndProc(hWnd: pointer, uMsg: int32, wParam, lParam: pointer): pointe
353353
fn[]()
354354
freeShared(fn)
355355
dec pQueue
356+
of WM_GETMINMAXINFO:
357+
let window = cast[Window](pGetWindowLongPtr(hWnd, GWLP_USERDATA))
358+
if window != nil:
359+
let minMaxInfo = cast[ptr MinMaxInfo](lParam)
360+
minMaxInfo.ptMinTrackSize.x = window.minWidth.int32
361+
minMaxInfo.ptMinTrackSize.y = window.minHeight.int32
356362
else:
357363
discard
358364
result = pCommonWndProc(hWnd, uMsg, wParam, lParam)
@@ -888,7 +894,7 @@ method endPixelDataAccess(image: Image) =
888894
proc init(window: WindowImpl) =
889895
if pDefaultParentWindow == nil:
890896
raiseError("'app.init()' needs to be called before creating a Window.")
891-
var dwStyle: int32 = WS_OVERLAPPEDWINDOW
897+
var dwStyle: int32 = WS_CAPTION or WS_SYSMENU or WS_THICKFRAME or WS_MINIMIZEBOX or WS_MAXIMIZEBOX
892898
window.fHandle = pCreateWindowExWithUserdata(pTopLevelWindowClass, dwStyle, 0, nil, cast[pointer](window))
893899
DragAcceptFiles(window.fHandle, true)
894900
window.Window.init()
@@ -968,6 +974,22 @@ method `height=`*(window: WindowImpl, height: int) =
968974
procCall window.Window.`height=`(height)
969975
window.pUpdateSize()
970976

977+
method `minWidth=`(window: WindowImpl, minWidth: int) =
978+
procCall window.Window.`minWidth=`(minWidth)
979+
#pUpdateMinSize(window)
980+
981+
method `minHeight=`(window: WindowImpl, minHeight: int) =
982+
procCall window.Window.`minHeight=`(minHeight)
983+
#pUpdateMinSize(window)
984+
985+
method `resizable=`(window: WindowImpl, resizable: bool) =
986+
procCall window.Window.`resizable=`(resizable)
987+
if resizable:
988+
pSetWindowLong(window.fHandle, GWL_STYLE, WS_CAPTION or WS_SYSMENU or WS_THICKFRAME)
989+
else:
990+
pSetWindowLong(window.fHandle, GWL_STYLE, WS_CAPTION or WS_SYSMENU)
991+
window.pUpdatePosition()
992+
971993
method `title=`(window: WindowImpl, title: string) =
972994
procCall window.Window.`title=`(title)
973995
pSetWindowText(window.fHandle, window.title)

src/nigui/private/windows/windows.nim

+10
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ const
187187
WM_CUT* = 0x0300
188188
WM_COPY* = 0x0301
189189
WM_PASTE* = 0x0302
190+
WM_GETMINMAXINFO* = 0x0024
190191
WS_CLIPCHILDREN* = 0x02000000
191192
WS_CAPTION* = 0x00C00000
192193
WS_CHILD* = 0x40000000
@@ -195,6 +196,8 @@ const
195196
WS_HSCROLL* = 0x00100000
196197
WS_OVERLAPPEDWINDOW* = 0x00CF0000
197198
WS_SYSMENU* = 0x00080000
199+
WS_MINIMIZEBOX* = 0x00020000
200+
WS_MAXIMIZEBOX* = 0x00010000
198201
WS_TABSTOP* = 0x00010000
199202
WS_THICKFRAME* = 0x00040000
200203
WS_VSCROLL* = 0x00200000
@@ -385,6 +388,13 @@ type
385388
lParam*: pointer
386389
iImage*: int32
387390

391+
MinMaxInfo* = object
392+
ptReserved*: Point
393+
ptMaxSize*: Point
394+
ptMaxPosition*: Point
395+
ptMinTrackSize*: Point
396+
ptMaxTrackSize*: Point
397+
388398

389399

390400
# ----------------------------------------------------------------------------------------

0 commit comments

Comments
 (0)