Treeviews aren't my thing right now, but if/when I need them, I'll be happy that you shared this <g> – thanks!
Code archives/Miscellaneous/[MaxGUI] GUITools class
This code has been declared by its author to be Public Domain code.
Download source code
| Module with a collection of useful functions (own work and community code) to make working with MaxGUI easier. Leave me a mail for requests, comments and bugreports. |
SuperStrict
Rem
BBDoc: MaxGUI Tools and useful functions
EndRem
Module fuw.guitools
ModuleInfo "Version: 0.8"
ModuleInfo "OS: Win32 / MacOS / Linux"
ModuleInfo "History: 0.8 - Removed GadgetClass() and ClearTreeView() as they are now supported in MaxGUI.MaxGUI."
ModuleInfo "History: 0.7 - Added RequestString and TreeViewKidsList"
ModuleInfo "History: 0.6 - Added ListViewSwapItems"
ModuleInfo "History: 0.5 - Added GadgetGetD/GadgetSetD"
ModuleInfo "History: 0.4 - TreeviewNodeFind and others added"
ModuleInfo "History: 0.3 - some bugfixes, added GadgetGet$/GadgetSet$"
ModuleInfo "History: 0.2 - multifile-requester (Win32 only)"
ModuleInfo "HISTORY: 0.1 - some treeview helpers to start with"
Import maxgui.drivers
Import brl.retro
Import brl.eventqueue
Private
Rem
BBDoc: Float to string, cutting of precision digits
EndRem
Function _TrimFloat$(value:Double,places:Int=2)
Return Left(String(value),Instr(String(value),".") + places)
End Function
Const MAX_BUFFER_SIZE:Int = 8192
Const OFN_ALLOWMULTISELECT:Int = 512
Const OFN_CREATEPROMPT:Int = $2000
Const OFN_ENABLEHOOK:Int = 32
Const OFN_ENABLESIZING:Int = $800000
Const OFN_ENABLETEMPLATE:Int = 64
Const OFN_ENABLETEMPLATEHANDLE:Int = 128
Const OFN_EXPLORER:Int = $80000
Const OFN_EXTENSIONDIFFERENT:Int = $400
Const OFN_FILEMUSTEXIST:Int = $1000
Const OFN_HIDEREADONLY:Int = 4
Const OFN_LONGNAMES:Int = $200000
Const OFN_NOCHANGEDIR:Int = 8
Const OFN_NODEREFERENCELINKS:Int = $100000
Const OFN_NOLONGNAMES:Int = $40000
Const OFN_NONETWORKBUTTON:Int = $20000
Const OFN_NOREADONLYRETURN:Int = $8000
Const OFN_NOTESTFILECREATE:Int = $10000
Const OFN_NOVALIDATE:Int = 256
Const OFN_OVERWRITEPROMPT:Int = 2
Const OFN_PATHMUSTEXIST:Int = $800
Const OFN_READONLY:Int = 1
Const OFN_SHAREAWARE:Int = $4000
Const OFN_SHOWHELP:Int = 16
Const OFN_SHAREFALLTHROUGH:Int = 2
Const OFN_SHARENOWARN:Int = 1
Const OFN_SHAREWARN:Int = 0
Type TOpenFileNameA
Field lStructSize:Int
Field hwndOwner:Int
Field hInstance:Int
Field lpstrFilter:Byte Ptr
Field lpstrCustomFilter:Int
Field nMaxCustFilter:Int
Field nFilterIndex:Int
Field lpstrFile:Byte Ptr
Field nMaxFile:Int
Field lpstrFileTitle:Byte Ptr
Field nMaxFileTitle:Int
Field lpstrInitialDir:Byte Ptr
Field lpstrTitle:Byte Ptr
Field flags:Int
Field nFileOffset:Short
Field nFileExtension:Short
Field lpstrDefExt:Byte Ptr
Field lCustData:Int
Field lpfnHook:Byte Ptr
Field lpTemplateName:Byte Ptr
EndType
Extern "Win32"
Function GetOpenFileName:Int( of:Byte Ptr) = "GetOpenFileNameA@4"
EndExtern
Public
Rem
BBDoc: get a node's level
EndRem
Function TreeViewNodeLevel%(NODE:TGadget)
Assert NODE<>Null,"TreeViewNodeLevel: node=Null!"
Local lvl%
While NODE.parent And GadgetClass(NODE)<>GADGET_TREEVIEW
NODE=NODE.parent
lvl:+1
Wend
Return lvl
End Function
Rem
BBDoc: get the subindex of a node
EndRem
Function TreeViewNodeIndex%(NODE:TGadget)
Assert NODE<>Null,"TreeViewNodeIndex: node=Null!"
Assert NODE.parent<>Null, "TreeViewNodeIndex: node is not a child!"
Local idx%
Local Link:TLink=NODE.parent.kids.FirstLink()
While TGadget(Link.value())<>NODE
Link=Link.NextLink()
idx:+1
Wend
Return idx
End Function
Rem
BBDoc: Return names of node's kids as stringarray
EndRem
Function TreeViewKidsList$[](node:TGadget)
Assert NODE<>Null,"TreeViewNodeIndex: node=Null!"
Local cnt%=node.kids.Count()
Local res$[]=New String[cnt]
Local Link:TLink=NODE.kids.FirstLink()
Local i%
While Link<>Null
res[i]=TGadget(Link.Value()).name
Link=Link.NextLink()
i:+1
Wend
Return res
End Function
Rem
BBDoc: returns the node by a parentnodes subindex
EndRem
Function TreeViewNodeAtIndex:TGadget(NODE:TGadget,index%)
Assert NODE<>Null,"TreeViewNodeAtIndex: node=Null!"
Local Link:TLink=NODE.kids.FirstLink()
While Link<>Null
If index<=0 Then Return TGadget(Link.value())
index:-1
Link=Link.NextLink()
Wend
Return Null
End Function
Rem
BBDoc: This function will swap node's captions but cannot swap icons unless you provide them
EndRem
Function TreeViewSwapNodes (node1:TGadget,node2:TGadget,icon1%=-1,icon2%=-1)
?Debug
Assert node1<>Null And node2<>Null,"TreeViewSwapNodes: Null not allowed"
?
Local temp$=node1.name
Local tobj:Object=node1.context
ModifyTreeViewNode (node1,node2.name,icon2)
ModifyTreeViewNode (node2,temp,icon1)
node1.context=node2.context
node2.context=tobj
End Function
Rem
BBDoc: Search a treeview starting from node to find a children by name (and optional level)
EndRem
Function TreeViewNodeFind:TGadget (NODE:TGadget,txt$,lvl%=-1)
Local Link:TLink=NODE.kids.FirstLink()
Local n:TGadget
While Link<>Null
n=TGadget(Link.value())
If n.name=txt And (lvl=-1 Or TreeViewNodeLevel(n)=lvl) Then Return n
Link=Link.NextLink()
Wend
End Function
Rem
BBDoc: Find a listitem by extra content
EndRem
Function GetGadgetItemByExtra% (listgadget:TGadget,extra:Object,compare_string%=False)
Local ex:Object
For Local i%=0 Until CountGadgetItems(listgadget)
ex=GadgetItemExtra(listgadget,i)
If ex=extra Or (compare_string And String(ex)=String(extra))
Return i
End If
Next
Return -1
End Function
Rem
BBDoc: Swap two listitems
EndRem
Function ListViewSwapItems (lstview:TGadget,idx1%,idx2%)
Local tmp$=GadgetItemText (lstview,idx1)
Local tmpflags%=GadgetItemFlags (lstview,idx1)
Local tmpextra:Object=GadgetItemExtra(lstview,idx1)
Local tmptip$=lstView.ItemTip(idx1)
Local tmpicon%=GadgetItemIcon(lstview,idx1)
Local si%=SelectedGadgetItem(lstView)
ModifyGadgetItem (lstview,idx1,GadgetItemText(lstview,idx2),GadgetItemFlags(lstview,idx2),GadgetItemIcon(lstview,idx2),..
lstView.ItemTip(idx2),GadgetItemExtra(lstview,idx2))
ModifyGadgetItem (lstview,idx2,tmp,tmpflags,tmpicon,tmptip,tmpextra)
If si=idx1 Then SelectGadgetItem(lstView,idx2) ElseIf si=idx2 Then SelectGadgetItem(lstView,idx1)
End Function
Rem
BBDoc: Create a textfield with label
EndRem
Function AddTextField:TGadget (parent:TGadget,x%,y%,w%,caption$="",text$="")
Local G:TGadget=CreateTextField (x,y,w,20,parent)
If text Then SetGadgetText (G,text)
If caption
Local lbl:TGadget=CreateLabel (caption,x-105,y+3,100,20,parent,LABEL_RIGHT)
EndIf
Return G
End Function
Rem
BBDoc: Create a checkbox and set it's state
EndRem
Function AddCheckbox:TGadget (parent:TGadget,x%,y%,w%,caption$,checked%=False)
Local G:TGadget=CreateButton (caption,x,y,w,20,parent,BUTTON_CHECKBOX)
SetButtonState(G,checked)
End Function
Rem
BBDoc: Request multiple files
About: Done by Blitzmax community, slightly changed the way files are returned
EndRem
Function RequestFiles:String[]( text:String, exts:String = Null, path:String = Null)
?MacOs | Linux
Local res:String = RequestFile( test, exts, False, path)
If res.length <= 0 Then Return Null
Return [res]
?
?Win32
Global hwndFocus:Int
' prepare filename / path (ripped from BRL's RequestFile())
Local File:String, Dir:String
path = path.Replace( "/","\" )
Local i:Int = path.FindLast( "\" )
If i <> -1 Then
Dir = path[..i]
File = path[i+1..]
Else
File = path
EndIf
' calculate default index of extension in extension list from path name
Local ext:String, defext:Int,p:Int,q:Int
p = path.Find(".")
If (p>-1) Then
ext = "," + path[p+1..].toLower() + ","
Local exs:String = exts.toLower()
exs = exs.Replace(":",":,")
exs = exs.Replace(";",",;")
p = exs.find(ext)
If p >-1 Then
Local q:Int = -1
defext = 1
While True
q = exs.find(";",q+1)
If q > p Then Exit
If q = -1 Then
defext = 0
Exit
EndIf
defext :+ 1
Wend
EndIf
EndIf
If exts Then
If exts.Find(":") = -1 Then
exts = "Files~0*." + exts
Else
exts = exts.Replace(":","~0*.")
EndIf
exts = exts.Replace(";","~0")
exts = exts.Replace(",",";*.") + "~0"
EndIf
' allocate cstrings
Local textp:Byte Ptr = text.ToCString()
Local extsp:Byte Ptr = exts.ToCString()
Local dirp:Byte Ptr
If Dir.length > 0 Then dirp = Dir.ToCString()
' prepare file buffer
Local Buf:Byte[MAX_BUFFER_SIZE]
memcpy_( Buf, File, File.length)
' initialize dialog options
Local of:TOpenFileNameA = New TOpenFileNameA
of.lStructSize = SizeOf(TOpenFileNameA)
of.hwndOwner = GetActiveWindow()
of.lpstrTitle = textp
of.lpstrFilter = extsp
of.nFilterIndex = defext
of.lpstrFile = Buf
of.lpstrInitialDir = dirp
of.nMaxFile = Buf.length
of.flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT | OFN_EXPLORER ' | OFN_LONGNAMES
' display dialog
hwndFocus = GetFocus()
Local n:Int = GetOpenFileName( of)
SetFocus( hwndFocus)
' free cstrings
MemFree textp
MemFree extsp
If dirp Then MemFree dirp
' failure ?
If n <= 0 Then Return Null
' count the number of files
Local s:Byte Ptr = Buf
Local count:Int = 0
While s[0] <> 0
If s[1] = 0 Then
count :+ 1
s :+ 2
If s[0] = 0 Then Exit
EndIf
s :+ 1
Wend
If count <= 0 Then Return Null
' extract filenames into String array
If count = 1 Then
'MARK: im following RequestFile() convention here, and returing "\" path seperators #1
'Return [ String.FromCString( buf).Replace( "\", "/") ]
Return [ String.FromCString( Buf) ]
Else
Local result:String[] = New String[count]
s = Buf
For Local i:Int = 0 Until count
result[i] = String.FromCString( s)
s :+ result[i].length + 1
If i>0 Then result[i] = result[0]+"\"+result[i]
Next
'MARK: im following RequestFile() convention here, and returing "\" path seperators #2
'result[0] = result[0].Replace( "\", "/") + "/"
result=Result[1..]
Return result
EndIf
EndFunction
Rem
BBDoc: Return a gadget's value as Double
EndRem
Function GadgetGetD! (G:TGadget)
Return Double(GadgetGet(G))
End Function
Rem
BBDoc: Set a gadget's value from Double
EndRem
Function GadgetSetD (G:TGadget,d!)
SetGadgetText (G,_TrimFloat(d))
End Function
Rem
BBDoc: Return a gadget's value as Float
EndRem
Function GadgetGetF# (G:TGadget)
Select GadgetClass(G)
Case GADGET_TEXTFIELD
Return Float(GadgetText(G))
End Select
End Function
Rem
BBDoc: Return a gadget's value as Int
EndRem
Function GadgetGetI% (G:TGadget)
Select GadgetClass(G)
Case GADGET_TEXTFIELD
Return Int(GadgetText(G))
End Select
End Function
Rem
BBDoc: Return a gadget's value as string
About: Not quite useful yet, but other gadget-types could be added
EndRem
Function GadgetGet$ (G:TGadget)
Select GadgetClass(G)
Case GADGET_TEXTFIELD
Return GadgetText(G)
End Select
End Function
Rem
BBDoc: Set a gadget's value from Float
EndRem
Function GadgetSetF (G:TGadget,f#)
SetGadgetText(G,_TrimFloat(f))
End Function
Rem
BBDoc: Set a gadget's value from Int
EndRem
Function GadgetSetI (G:TGadget,i%)
SetGadgetText(G,i)
End Function
Rem
BBDoc: Set a gadget's value from string
About: Not quite useful yet, but other gadget-types could be added
EndRem
Function GadgetSet (G:TGadget,s$)
SetGadgetText(G,s)
End Function
Rem
BBDoc: A DialogBox
EndRem
Function RequestString$(caption$,text$)
Local ww%=220
Local wh%=30
Local wx%=Desktop().width/2-ww/2
Local wy%=Desktop().height/2-wh/2
Local win:TGadget=CreateWindow(caption,wx,wy,ww,wh,Null,WINDOW_TITLEBAR|WINDOW_TOOL|WINDOW_CLIENTCOORDS)
Local txt:TGadget=CreateTextField(5,5,ww-100,20,win)
SetGadgetText (txt,text)
Local ok:TGadget=CreateButton("OK",ww-85,5,80,20,win)
ActivateGadget(txt)
Repeat
Select WaitEvent()
Case EVENT_WINDOWCLOSE
FreeGadget(win)
Return text
Case EVENT_GADGETACTION
If EventSource()=ok
text=GadgetText(txt)
FreeGadget(win)
Return text
End If
End Select
Forever
End Function
Rem
BBDoc: Absolute to relative paths
About: Copied from Blitzmax community
EndRem
Function ExtractRelativePath:String( src:String, dest:String )
src=ExtractDir(RealPath(src))
dest=RealPath(dest)
Local count:Int=0
While src<>Left(dest,Len(src))
count:+1
Local i:Int=src.FindLast("/")
src=src[..i]
Wend
dest=dest.Replace(src,"")
dest=dest[1..]
For Local i:Int=1 To count
dest="../"+dest
Next
Return dest
End Function |
Comments
There are a few safety checks missing from the above code.
For example, in TreeViewNodeIndex, the code should be testing link <> Null before calling link.Value().
For example, in TreeViewNodeIndex, the code should be testing link <> Null before calling link.Value().
You're right. I will update my post with the latest version soon. Also added a few functions since the first version.
EDIT: Updated with new latest version.
EDIT: Updated with new latest version.
When I try to compile the module I get an error: Module does not match commandline module ...
Can anybody help me what to do now?
Thanks
Can anybody help me what to do now?
Thanks
You should copy the code into a file called "guitools.bmx" and put that in the path <your Blitzmax>/mod/fuw.mod/guitools.mod/
compile it using BMK.exe (from Blitzmax/Bin):
bmk -makemods fuw.guitools
Jake
compile it using BMK.exe (from Blitzmax/Bin):
bmk -makemods fuw.guitools
Jake
Thanks, but that what I tried out...
Also I rebuild all modules with the IDE - but in my guitools.mod folder is after building also only the guitools.bmx module, no builded binarys.
However, bmk reports no error but for sure the commands like RequestString$ are not recognized ...
Also I rebuild all modules with the IDE - but in my guitools.mod folder is after building also only the guitools.bmx module, no builded binarys.
However, bmk reports no error but for sure the commands like RequestString$ are not recognized ...
You should have some binary code after compiling with bmk, so something must be wrong with your directory structure I think.
I copy&pasted the code from my existing mod which I use the whole day....it should definitely work. Are you using windows?
I copy&pasted the code from my existing mod which I use the whole day....it should definitely work. Are you using windows?
Yes I'm using Windows XP.
I've installed some others mods like bah and fmc - and after a lot of questions and great support I've no more trouble compiling mods.
The matter with the GUITool Class is that I get no error code - it seems that anything whould be fine but the binaries are not available.
Is there a way to get the binary code from somewhere?
I've installed some others mods like bah and fmc - and after a lot of questions and great support I've no more trouble compiling mods.
The matter with the GUITool Class is that I get no error code - it seems that anything whould be fine but the binaries are not available.
Is there a way to get the binary code from somewhere?
Well, you should be able to compile this mod, as I am. Don't know why it don't work on your side, but copy&paste the code to whereever you like (plain bmx, your own mod etc..) and use it, if you want.
With the latest 1.30 SVN version, I'm getting the following error when compiling this module:
Compiling:guitools.bmx
Compile Error: Unable to convert from 'Int()' to 'Int'
[c:/code/blitzmax/mod/fuw.mod/guitools.mod/guitools.bmx;108;3]
Compile Error: Unable to convert from 'Int()' to 'Int'
[c:/code/blitzmax/mod/fuw.mod/guitools.mod/guitools.bmx;108;3]
Thanks, that did the trick.
GadgetClass() is a built-in MaxGUI function now so you can just remove that declaration. Also, the one given here does not work with MaxGUI.Win32MaxGUIEx and may report incorrect values.
Jake: Just a note to say that I've updated the code archive entry with the now officially supported commands (ClearTreeView() and GadgetClass()) removed.