View difference between Paste ID: UkvT4RaE and BUTBzrEU
SHOW: | | - or go back to the newest paste.
1
/*
2
Name: GUI Buildeer Deluxe
3-
Version 1.1 (Sunday, January 24, 2016)
3+
Version 1.0 (Saturday, January 09, 2016)
4
Created: Saturday, January 02, 2016
5
Author: tidbit
6
Credit: 
7
	Family Dollar, For "providing" the delicious snacks (at discount prices) needed for making this program.
8
	Bugz000      , A currently unused function that may get added in eventually.
9
10
Hotkeys:
11
	esc   --- Quit
12
	enter --- Generate! but not Generate?
13
	maybe others
14
	
15
Description:
16
	Generate a gui with the press of a key. No more slaving away at trying to
17
	build a gui in a "Gui builder" or trying to figure out the code yourself, learning
18
	is overrated anyways.
19
	For the visually impaired or those who cannot read, there is also a Speak option.
20
	If you want some control, there's advanced settings for you to do stuff with.
21
	
22
Other info:
23-
	Avalable controls (specify the number in the GUI)
23+
24
	7=hotkey, 8=datetime, 9=Listview
25-
	7=hotkey, 8=datetime, 9=Listview, 10=slider, 11=progress
25+
26
To-do:
27
	- groupbox, treeview, tabs, possibly activex (ie)
28
	- insert random code snippets, generate fully functional guis
29
	- new positioning system to reduce the chance of oversized 90% empty guis
30
    
31
*/
32
#SingleInstance, force
33
_name_:="GUI Buildeer Deluxe"
34
_ver_:="1.0"
35-
_ver_:="1.1"
35+
36
texts:=["","Settings","Width","Height","Color","Domains","Qualification"
37
,"Dock","IPR","ACSC's","Submit","OK","Okay","Send","Forward","Back","button"
38
,"add","remove","...",A_DDDD]
39-
,"add","remove","delete","...",A_DDDD,"Reports","Open","Easy","Size","Brand"
39+
40-
,"Rank","Polar bear pelts","QTY","Quality","Quantity","Material"
40+
41-
,"Hotkey","Macro: ","Operation","GHz","MHz","pudding","Select one: "]
41+
42
43
gui, settings: margin, 6, 6
44
gui, settings: +resize
45
; gui, settings: color, 0x8FBC8F
46
; gui, settings: font, s12
47
gui, settings: add, button, xm ym w200 default gdoTheStuff, Generate!
48
gui, settings: add, checkbox, xm y+m cgreen vspeak, Speak the controls
49
gui, settings: add, text, xm y+m cblue vtxt1, Controls* to add:
50-
gui, settings: add, button, xm ym w200 default vgenbtn1 gdoTheStuff, Generate!
50+
51
gui, settings: add, updown, vud1, 7
52
gui, settings: add, text, xm y+m vtxt6, Gui name:
53
gui, settings: add, edit, xs yp-3 w100 vguiName,
54
gui, settings: add, text, xm y+-1 cgray vtxt2, *(control groups, such as a text+edit`nor three checkboxes)
55
GroupBox2("Settings", "speak,txt1,cCount,ud1,txt2,txt6,guiName", "settings")
56
57
gui, settings: add, radio, xm y+10 cred checked vmode1 gmode, Odds mode
58
gui, settings: add, radio, x+m yp cred vmode2 gmode, Order mode
59
gui, settings: add, text, xm y+m vtxt3, Control* odds:
60
gui, settings: add, edit, x+m yp-3 w150 r2 vodds, 1 1 1 1 2 2 2 2 3 3 4 5 5 6 6 7 8 9
61-
gui, settings: add, radio, x+m yp cred  vmode2 gmode, Order mode
61+
62
gui, settings: add, edit, x+m yp-3 w150 r2 vorder, 1 1 2 2 9 5
63-
gui, settings: add, edit, x+m yp-3 w150 r2 vodds, 1 1 1 1 2 2 2 2 3 3 4 5 5 6 6 7 8 9 10 10 11 11
63+
gui, settings: add, text, xm y+-1 cgray vtxt5, *(1=edit, 2=button, 3=checkbox, 4=radio, 5=ddl,`n6=combobox 7=hotkey, 8=datetime, 9=Listview)
64
65-
gui, settings: add, edit, x+m yp-3 w150 r2 vorder, 1 1 2 10 11 9 5
65+
66-
gui, settings: add, text, xm y+-1 cgray vtxt5, *(1=edit, 2=button, 3=checkbox, 4=radio, 5=ddl,`n6=combobox, 7=hotkey, 8=datetime, 9=Listview,`n10=slider, 11=progress)
66+
67
GroupBox2("Advanced settings", "mode1,mode2,txt3,odds,txt4,order,txt5", "settings")
68
69
gui, settings: add, button, xm y+m w200 vgenbtn2 gdoTheStuff, Generate?
70
71
gui, settings: add, text, ym section, Output:
72
gui, settings: add, button, x+m ys-3 w20 ghelp, ?
73
74
gui, settings: font, s10, courier new
75-
gui, settings: add, button, x+m ys-3 ghelp, What does this stuff mean?
75+
76
77
guiControlGet, pos, settings: pos, disp
78
guiControlGet, pos2, settings: pos, genbtn2
79
guiControl, settings: move, disp, % "h" pos2y+pos2h-posy
80
81
gosub, mode
82
gui, settings: show, x100 autoSize, % _name_ " - v" _ver_
83
return
84
85
86
; esc:: ; we don't need you either.
87
; 	critical
88
; 	exitapp
89
; return
90
91
92
settingsGuiClose:  ; you don't like me
93
settingsGuiEscape: ; you don't like me and you're too lazy to move the mouse
94
	exitapp
95
return
96
97-
gennedGuiEscape:
97+
98
settingsGuiSize: ; big, small, big, small
99
	guiControlGet, pos, settings: pos, disp
100
	guiControl, settings: move, disp, % "w" A_GuiWidth-posx-6 " h" A_GuiHeight-posy-6
101
return
102
103
104
mode: ; you pressed a radio button, probably
105
	gui, settings: default
106
	gui, settings: submit, nohide
107
	if (mode1=1)
108
	{
109
		guiControl, settings: +c0xff0000, txt3
110
		guiControl, settings: +c0x000000, txt4
111
	}
112
	else if (mode2=1)
113
	{
114
		guiControl, settings: +c0x000000, txt3
115-
		guiControl, settings: enable, cCount
115+
116
	}
117
	guiControl, settings: movedraw, txt3 ; update the color
118
	guiControl, settings: movedraw, txt4 ; update the color
119
return
120
121-
		guiControl, settings: disable, cCount
121+
122
help: ; because you need it
123
	help=
124
	(ltrim join`n
125
	OPTIONS:`tInformation for: gui, add, control, OPTIONS, text
126
	---
127
	x30`tx coordinates (coords) for the control, in pixels
128
	xm`tPosition the control to the GUIs "margin" (the default spacing)
129
	x+3`tPosition the control 3 pixels to the right of the previously added control
130
	xs`tPosition the control at the last controls x-coord that used the keyword "section"
131
	xp`tPosition the control at the previous added controls x-coord
132
	xp+3`tPosition the control at the previous added controls x-coord and indent 3 pixels
133
	y...`tHas all the same options as X, but for Y, obviously
134
	---
135
	w100`tWidth of the control, in pixels
136
	wp`tUse the previous controls width
137
	h100`tHeight of the control, in pixels
138
	hp`tUse the previous controls height
139
	r1`tSet the control to this many "text rows" tall. 1=1 line, 2=2 lines, etc.
140
	---
141
	vBanana`tControls output variable. This usually contains its value.
142
	`tYou DO NOT use the "v". Only use "Banana". "Banana" is the variable name.
143
	`t"v" only tells AHK that "banana is the variable for this control".
144
	gLabel`tThe label (section of code) to go to when the control is triggered.
145
	)
146
	help:=st_columnize(help, "`t")
147
	msgBox2(help, _name_ " - help", "r20 -wrap +hscroll readonly")
148
return
149
150
151
doTheStuff: ; did I stutter?
152
	critical ; prevent button spamming, because why not.
153
	gui, genned: destroy ; we don't need that old crap in our gui.
154
	gui, genned: default
155
	gui, settings: submit, nohide
156
	
157
	; !!! do not touch !!!
158
	codeArr:=[] ; raw code and settings
159
	cArr:=[]    ; the final control strings.
160
	vList:={}   ; used to generate variable names like banana1, banana2, ...
161
	gList:={}   ; is this label already in existence?
162
	odds:=strReplace(odds, ",", " ")   ; repace commas with spaces. lets users use , or space
163
	order:=strReplace(order, ",", " ") ; repace commas with spaces. lets users use , or space
164
	odds:=regExReplace(odds, "(\h){2,}", "$1")   ; remove excessive blanks
165
	order:=regExReplace(order, "(\h){2,}", "$1") ; remove excessive blanks
166
167
	guiName:=(guiName="") ? "" : guiName ": "
168
169
	if (speak=1) ; creative variable names at their finest.
170
		lemons:=ComObjCreate("SAPI.SpVoice"), lemons.rate:=3
171
	
172
	if (mode1=1)
173
	{
174
		list:=strSplit(odds, " ")
175
		count:=cCount
176
	}
177-
		guiControl, settings: disable, genbtn1
177+
178-
		guiControl, settings: disable, genbtn2
178+
179-
		lemons:=ComObjCreate("SAPI.SpVoice")
179+
180-
		lemons.rate:=3
180+
181
	}
182
	
183
	; generate the controls and their settings.
184
	; c... = control...
185
	loop, %count%
186
	{
187
		ctext:=texts[rand(texts.maxIndex())]
188
		clist:=lists[rand(lists.maxIndex())]
189
		cont:=list[(mode2=1) ? A_Index : rand(list.maxIndex())]
190
		
191
		cVar:=genLabelN(ctext)
192
		cVar:=(cVar="") ? "dummy" : cVar
193
		cPos:=genPos()
194
		cwidth:=rand(200,40)
195
		; cwidth:=(cwidth<30) ? "" : cwidth
196
		
197
		guiOptions:=cPos " w" cwidth " v" cVar
198
		guiOptions2:=guiOptions " g" cVar
199
		if (cont=1)
200
			codeArr.push(addEdit(ctext, 1, guiOptions))
201
		else if (cont=2)
202
			codeArr.push(addButton(ctext, guiOptions2))
203
		else if (cont=3)
204
			codeArr.push(addCheckbox(ctext, 1, guiOptions2, rand(4,2)))
205
		else if (cont=4)
206
			codeArr.push(addCheckbox(ctext, 2, guiOptions2, rand(4,2)))
207-
		cRange1:=rand(30)       ; min for sliders/progress
207+
208-
		cRange2:=rand(300, 100) ; max for sliders/progress
208+
209
		else if (cont=6)
210
			codeArr.push(addEdit(clist, 3, guiOptions2))
211
		else if (cont=7)
212
			codeArr.push(addEdit(ctext, 4, guiOptions))
213
		else if (cont=8)
214
			codeArr.push(addEdit(ctext, 5, guiOptions2))
215-
			codeArr.push(addButton(ctext, 1, guiOptions2))
215+
216
			codeArr.push(addListview(clist, cPos " w" rand(400,100) 
217
			. " r" rand(15, 5) " vLV" cVar " g" cVar))
218
	}
219
	
220
	; do some re-formatting to build the gui a bit easier.
221
	; probably not needed, but w/e.
222
	for key, arr in codeArr ; 'split' by the total number of items
223
	{
224
		loop, % arr["opts"].maxIndex()
225
		{
226
			options:="" ; never forget.
227
			ctype:=arr["sets", A_Index, "t"] ; control type
228
			clabel:=arr["sets", A_Index, "l"] ; control label (text)
229
			for bbb, arr2 in arr["opts", A_Index] ; I really hate doing this 2-for thingy
230
				for k, v in arr2
231-
		else if (cont=10)
231+
232-
			codeArr.push(addButton(rand(cRange2, cRange1), 2, cPos " w" cwidth 
232+
233-
			. " tooltip range" cRange1 "-" cRange2 " v" cVar " g" cVar))
233+
234-
		else if (cont=11)
234+
235-
			codeArr.push(addButton(rand(cRange2, cRange1), 3, cPos " w" cwidth 
235+
236-
			. " range" cRange1 "-" cRange2
236+
237-
			. " c0x" format("{:x}{:x}{:x}", rand(255), rand(255), rand(255))
237+
238-
			. " background0xdeb887 v" cVar " g" cVar))
238+
239
				vList[vvar]:=1
240
			arr["opts", A_Index, bbb, "v"].=vList[vvar] ; because
241
			
242
			; fileAppend, % st_printArr(arr["opts", A_Index]) "`n", * 
243
			for k, arr2 in arr["opts", A_Index] ; I really hate doing this 2-for thingy
244
				for k, v in arr2
245
					if (trim(v)!="")
246
						options.=" " k "" v
247
			cArr.push({"t":ctype, "l": clabel, "opts":options})
248
		}
249
	}
250
251
	; build the gui and generate the code
252
	codeOut:=""
253
	for k, v in cArr
254
	{
255
		t1:=trim(v.t), t2:=trim(v.opts), t3:=trim(v.l) ; the main gui sections.
256
		t22:=regExReplace(t2, "i)\b[vg]\S+") ; don't create it with a glabel. it'll toss an error. v also isn't needed.
257
		gui, genned: add, %t1%, %t22%, %t3% 
258
		if (speak=1) ; you figure this out yourself
259
		{
260
			gui, genned: show, center autoSize
261
			lemons.speak(t1)
262
		}
263
		
264
		if (t1="Listview") ; listviews need things inside them.
265
		{
266-
					options.=" " k "" v
266+
267
			{
268
				temp:=A_Index ; the row of the listview
269
				LV_Add() ; probably adds a row?
270
				loop, % LV_GetCount("column") ; that many.
271
					LV_Modify(temp, "col" A_Index, texts[rand(texts.maxIndex())])
272
			}
273-
	; msgBox, % st_printArr(codeArr)
273+
274
		}
275
		codeOut.="gui, " guiName "add, " t1 ", " t2 ", " t3 "`n"
276
	}
277-
		; if (t1="slider")
277+
278-
		; 	t2.=" +tooltip range1-" rand(222, 100)
278+
279-
		; if (t1="progress")
279+
280-
		; 	t2.=" range30-" rand(222, 100)
280+
281-
		; msgBox % t2
281+
282
	temp=
283
	(ltrim join`n
284
	`n`n
285
	`; When you press escape or the [x] button, exit the program
286
	%guiName2%GuiEscape:
287-
			lemons.speak((rand(5)=1) ? texts[rand(texts.maxIndex())] : t1)
287+
288
	`texitApp
289
	return
290
	)
291
	codeOut.=temp
292
293
	; add in the g-labels:
294
	; msgBox % "ggg`n" st_printArr(cArr)
295
	for key, val in cArr
296
	{
297
		regExMatch(val["opts"], "i)\b[g](\S+)", o) ; o1 contains the glabel
298
		if (o1="" || gList.hasKey(o1))
299
			continue
300
		gList[o1]:=1 ; this label has now been used. do not add another.
301
		temp=
302
		(ltrim join`n
303
		`n`n
304
		%o1%:
305
		`tgui, %guiName%submit, noHide
306
		`t`; Your code here
307
		return
308
		)
309
		codeOut.=temp
310
	}
311
312
	if (speak=1) ; I hope you understand what this means by now...
313
		lemons.rate:=0, lemons.speak("Your ""G. u. i."" is complete")
314
	
315
	guiControl, settings:, disp, %codeOut%
316
	gui, genned: show, autoSize, % _name_ " - v" rand(200) ".0"
317
	
318
	if (speak=1) ; I give up.
319
	{
320
		lemons.speak("Copy the code, and study it well, " texts[rand(texts.maxIndex())])
321
		soundBeep, 750, 345
322
		lemons.speak("don't forget to thank tidbit!")
323
	}
324
	; msgBox % st_printArr(vList) "`n---`n" st_printArr(codeArr)
325
	; msgBox % st_printArr(cArr)
326
return
327
328
329
; 3 1 1 5 3 16 135 1 5 5 8 2 53
330
rand(max=100, min=1)
331
{
332
	random, r, %min%, %max%
333
	return r
334
}
335
336
; supid position stuff
337
genPos()
338
{
339
	aaa:=rand(100, 1)
340
	return (aaa<=60) ? "xm"
341
	     : (aaa<=70) ? "x+3 yp"
342-
	gui, genned: show, autoSize NA, % _name_ " - v" rand(200) ".0"
342+
343
	     :             "ym"
344
}
345
; old supid position stuff
346
; genPos()
347
; {
348-
		if (rand(3)=1)
348+
349-
			lemons.speak("don't forget to thank tidbit!")
349+
350-
		guiControl, settings: enable, genbtn1
350+
351-
		guiControl, settings: enable, genbtn2
351+
352
; 	     :             {"x":" " , "y":"m"}
353
; }
354
355
; generate a name for vVar or whatever. remove anything not in the ABCs. Poor ampersand.
356
genLabelN(N)
357
{
358
	if (N="")
359
		return "Banana"
360
	return regExReplace(N, "[\W- ]", "")
361
}
362
363
; very sloppy stuff below. I won't bother explaining.
364
addEdit(labelT="", ctype=1, options="x14 y13 w200 r1")
365
{
366
	opts:={}
367
	opts["opts"]:={}  ; gui options, x, y, w, h, etc
368
	opts["sets"]:={}  ; gui settings, such as type and display text
369
	ctype:=(ctype=1) ? "edit" 
370
	: (ctype=2) ? "ddl" 
371
	: (ctype=3) ? "comboBox" 
372
	: (ctype=4) ? "hotkey" 
373
	: "dateTime"
374
	
375
	if (ctype="hotkey")
376
		modifiers:=["!","+","^","!+","^!","!^+","^+"]
377
		, special:=modifiers[rand(modifiers.maxIndex())] chr(rand(90, 65))
378
	if (ctype="dateTime")
379
		modifiers:=["","LongDate","Time","yyyy-MMM-dd","yyyy-dd-MMM"]
380
		, special:=modifiers[rand(modifiers.maxIndex())]
381
	; control 1. the label/text control.
382
	if (labelT!=""        ; if the label is blank don't create it.
383
	&& ctype!="ddl"       ; ddls don't need a label.
384
	&& ctype!="datetime") ; datetime don't need a label.
385
	{
386
		temp:=opts["opts"].push({})
387
		options2:=RegExReplace(options, "i)\b[wrhg]\S+")
388
		options2:=RegExReplace(options2, "i)(v\S+)", "vtext")
389
		for k,v in strSplit(trim(RegExReplace(options2, "(\h)+", "$1")), " ")
390
			regExMatch(v, "i)\b(hwnd|[xywhrcvg])(\S+)", o) ; these are the GUI options
391
			, opts["opts", temp].push({"" o1:o2})
392
			
393
		opts["sets"].push({"l":(ctype="combobox") ? "List" : labelT, "t":"text"})
394
395
		; control 2. the input control to the right
396
		temp:=opts["opts"].push({})
397
		options:="x+3 yp-3 " RegExReplace(options, "i)\b[xy]\S+")
398
		for k,v in strSplit(trim(RegExReplace(options, "(\h)+", "$1")), " ")
399
			regExMatch(v, "i)\b(hwnd|[xywhrcvg])(\S+)", o) ; these are the GUI options
400
			, opts["opts", temp].push({"" o1:o2})
401
		
402
		opts["sets"].push({"l":(ctype="Edit") ? "" 
403
		: (ctype="Hotkey") ? special 
404
		: labelT
405
		, "t":ctype})
406
	}
407
	else
408
	{
409
		temp:=opts["opts"].push({})
410
		for k,v in strSplit(trim(RegExReplace(options, "(\h)+", "$1")), " ")
411
			regExMatch(v, "i)\b(hwnd|[xywhrcvg])(\S+)", o) ; these are the GUI options
412
			, opts["opts", temp].push({"" o1:o2})
413
	
414
		opts["sets"].push({"l":(ctype="edit") ? "List" 
415
		: (ctype="dateTime") ? special
416
		: labelT
417
		, "t":ctype})
418
	}
419
	; msgBox % st_printArr(opts)
420
	return opts
421
}
422
423
; use your imagination.
424
addButton(labelT="Button", options="x14 y13 w200 r1")
425
{
426
	opts:={}
427
	opts["opts"]:={}  ; gui options, x, y, w, h, etc
428
	opts["sets"]:={}  ; gui settings, such as type and display text
429
430
	temp:=opts["opts"].push({})
431
	for k,v in strSplit(trim(RegExReplace(options, "(\h)+", "$1")), " ")
432
		regExMatch(v, "i)\b(hwnd|[xywhrcvg])(\S+)", o) ; these are the GUI options
433
		, opts["opts", temp].push({"" o1:o2})
434
	
435
	opts["sets"].push({"l":labelT, "t":"button"})
436
	return opts
437
}
438
439
; checkbox, radio
440
addCheckbox(labelT="aaa", ctype=1, options="x14 y13 w200 r1", count=3)
441
{
442
	opts:={}
443
	opts["opts"]:={}  ; gui options, x, y, w, h, etc
444
	opts["sets"]:={}  ; gui settings, such as type and display text
445
	labelT:=(trim(labelT)="") ? "dummy" : labelT
446
	ctype:=(ctype=1) ? "checkbox" : "radio"
447
	aaa:=rand(3,1)=1
448
	
449
	loop, %count%
450
	{
451
		bbb:=A_Index ; super usful variable name. atleast it's easy to identify
452-
; use your imagination. Also supports sliders and progresses. big boring rectangles.
452+
453-
addButton(labelT="Button", ctype=1, options="x14 y13 w200 r1")
453+
454
		 ; first control of the group dictates the starting position
455
		 ; which is the initial Options. we don't need to modify them.
456
		temp:=opts["opts"].push({}) ; this var name isn't so helpful. deal with it
457
		if (bbb!=1)
458-
	ctype:=(ctype=3) ? "progress" 
458+
459-
	: (ctype=2) ? "slider"
459+
460-
	: "button"
460+
461
			else ; vertical list
462
				options:=" xp y+3 " RegExReplace(options, "i)\b[xy]\S+")
463
		}
464-
		regExMatch(v, "i)\b(hwnd|background|tooltip|range|[xywhrcvg])(\S*)", o) ; these are the GUI options
464+
465
		for k,v in strSplit(options, " ")
466-
	opts["sets"].push({"l":labelT, "t":ctype})
466+
467
			, opts["opts", temp].push({"" o1:o2})
468-
	; msgBox, % st_printArr(opts)
468+
469
	}	
470
	; msgBox % st_printArr(opts)
471
	return opts
472
}
473
474
; Listview. pretty much identical code to Button. should have just combined them. boohoo.
475
addListview(labelT="Header1|Header2|Header3", options="x14 y13 w200 r15")
476
{
477
	opts:={}
478
	opts["opts"]:={}  ; gui options, x, y, w, h, etc
479
	opts["sets"]:={}  ; gui settings, such as type and display text
480
481
	temp:=opts["opts"].push({})
482
	for k,v in strSplit(trim(RegExReplace(options, "(\h)+", "$1")), " ")
483
		regExMatch(v, "i)\b(hwnd|[xywhrcvg])(\S+)", o) ; these are the GUI options
484
		, opts["opts", temp].push({"" o1:o2})
485
	
486
	opts["sets"].push({"l":labelT, "t":"listView"})
487
	return opts
488
}
489
490
; really old function made by tidbit.
491
msgbox2(text="", title="Msgbox", options="readonly -wrap w300 r12", ctrl="edit")
492
{
493
	static
494
	Gui, msgbox: New
495
	Gui, font,, Courier New
496
	Gui, +OwnDialogs +hwndMBHWND
497
	Gui, add, %ctrl%, %options% -wantReturn, %text%
498
	GuiControlGet, x, Pos, %ctrl%1
499
	xw:=xw-70+xx
500
	Gui, add, button, x%xw% y+10 w70 Default vbtn gMB2OK, OK
501
	GuiControl, focus, btn
502
	Gui, show,, %title%
503
	WinWaitClose, ahk_id %MBHWND%
504
505
	msgboxGUIEscape:
506
	msgboxGUIClose:
507
	MB2OK:
508
		gui,  Destroy
509
	Return
510
}
511
512
; really really old function made by tidbit.
513
GroupBox2(Text, Controls, GuiName=1, Offset="0,0", Padding="3,3,3,3", TitleHeight=15)
514
{
515
   static
516
   xx:=yy:=ww:=hh:=PosX:=PosY:=PosW:=PosH:=0
517
   StringSplit, Padding, Padding, `,
518
   StringSplit, Offset, Offset, `,
519
   loop, parse, Controls, `,
520
   {
521
      LoopField:=trim(A_LoopField)
522
      guiControlGet, Pos, %GuiName%: Pos, %LoopField%
523
      if (A_Index=1)
524
         xx:=PosX, yy:=PosY, ww:=PosX+PosW, hh:=PosY+PosH
525
      xx:=((xx<PosX) ? xx : PosX)
526
      yy:=((yy<PosY) ? yy : PosY)
527
      ww:=((ww>PosX+PosW) ? ww : PosX+PosW)
528
      hh:=((hh>PosY+PosH) ? hh : PosY+PosH)
529
      guiControl, %GuiName%: Move, %LoopField%, % "x" PosX+Padding1+Offset1 " y" PosY+Padding3+Offset2+titleHeight
530
   }
531
   xx+=Offset1
532
   yy+=Offset2
533
   ww+=Padding1+Padding2+Offset1-xx
534
   hh+=Padding3+Padding4+titleHeight+Offset2-yy
535
   counter+=1
536
   UID:="GB" GUIName counter xx yy ww hh
537
   status := GroupBox2_Add(guiname, xx, yy, ww, hh, uid, text)
538
   Return (status == true ? [uid,xx,yy,ww,hh] : false)
539
}
540
GroupBox2_Add(guiname, xx, yy, ww, hh, uid, text) {
541
	Global
542
	Gui, %GuiName%: add, GroupBox, x%xx% y%yy% w%ww% h%hh% v%UID%, %Text%
543
	return (errorlevel == 0 ? true : false)
544
}
545
546
; used for debugging. it's a major life-saver
547
; Lexikos or someone needs to add something like this built-in to ahk :P
548
st_printArr(array, depth=5, indentLevel="")
549
{
550
   for k,v in Array
551
   {
552
      list.= indentLevel "[" k "]"
553
      if (IsObject(v) && depth>1)
554
         list.="`n" st_printArr(v, depth-1, indentLevel . "    ")
555
      Else
556
         list.=" => " v
557
      list.="`n"
558
   }
559
   return rtrim(list, "`r`n `t")
560
}
561
562
; ; old function made by tidbit. pretty helpful. quite long. probably not the best.
563
st_columnize(data, delim="csv", justify=1, pad=" ", colsep=" | ")
564
{		
565
	widths:=[]
566
	dataArr:=[]
567
	
568
	if (instr(justify, "|"))
569
		colMode:=strsplit(justify, "|")
570
	else
571
		colMode:=justify
572
	; make the arrays and get the total rows and columns
573
	loop, parse, data, `n, `r
574
	{
575
		if (A_LoopField="")
576
			continue
577
		row:=A_Index
578
		
579
		if (delim="csv")
580
		{
581
			loop, parse, A_LoopField, csv
582
			{
583
				dataArr[row, A_Index]:=A_LoopField
584
				if (dataArr.maxindex()>maxr)
585
					maxr:=dataArr.maxindex()
586
				if (dataArr[A_Index].maxindex()>maxc)
587
					maxc:=dataArr[A_Index].maxindex()
588
			}
589
		}
590
		else
591
		{
592
			dataArr[A_Index]:=strsplit(A_LoopField, delim)
593
			if (dataArr.maxindex()>maxr)
594
				maxr:=dataArr.maxindex()
595
			if (dataArr[A_Index].maxindex()>maxc)
596
				maxc:=dataArr[A_Index].maxindex()
597
		}
598
	}
599
	; get the longest item in each column and store its length
600
	loop, %maxc%
601
	{
602
		col:=A_Index
603
		loop, %maxr%
604
			if (strLen(dataArr[A_Index, col])>widths[col])
605
				widths[col]:=strLen(dataArr[A_Index, col])
606
	}
607
	; the main goodies.
608
	loop, %maxr%
609
	{
610
		row:=A_Index
611
		loop, %maxc%
612
		{
613
			col:=A_Index
614
			stuff:=dataArr[row,col]
615
			len:=strlen(stuff)
616
			difference:=abs(strlen(stuff)-widths[col])
617
618
			; generate a repeating string about the length of the longest item
619
			; in the column.
620
			loop, % ceil(widths[col]/((strlen(pad)<1) ? 1 : strlen(pad)))
621
    			padSymbol.=pad
622
623
			if (isObject(colMode))
624
				justify:=colMode[col]
625
			; justify everything correctly.
626
			; 3 = center, 2= right, 1=left.
627
			if (strlen(stuff)<widths[col])
628
			{
629
				if (justify=3)
630
					stuff:=SubStr(padSymbol, 1, floor(difference/2)) . stuff
631
					. SubStr(padSymbol, 1, ceil(difference/2))
632
				else
633
				{
634
					if (justify=2)
635
						stuff:=SubStr(padSymbol, 1, difference) stuff
636
					else ; left justify by default.
637
						stuff:= stuff SubStr(padSymbol, 1, difference) 
638
				}
639
			}
640
			out.=stuff ((col!=maxc) ? colsep : "")
641
		}
642
		out:=trim(out) "`r`n"
643
		; out.="`r`n"
644
	}
645
	stringTrimRight, out, out, 2 ; remove the last blank newline
646
	return out
647
}
648
649
; hope you enjoyed the random babbling.
650
; enjoy.