PDA

View Full Version : Ui_oop



ReneMiner
31-01-2015, 18:55
it runs, but it's just an incomplete sketch.




#MINVERSION 1.9.15.0

#INCLUDE Once "UI_OOP_wrapper.tBasicU"


Type t_myWindow Extends cWindow

' instead of ControlID ;)

CloseButton As DWord
OtherButton As DWord ' this could be some array "OtherButton(123) too...
someLabel As DWord

'Static sType As String Value "t_myWindow"
'( i wish that were possible and all extended types would have their own sType then) -
' perhaps a built-in Static Typename on all udts could solve the TypeOf-Question for udts...
End Type


Dim myWindow(3) As t_myWindow

' either dimension dialogs as global
' see cCommandButton_Click therefor how to use "by varname"
' or dialogs maybe local to tBMain, then see cLabel_Click()

Function TBMain()

Long numberOfDialogsAlive

With myWindow(1)
.TypeID( "t_myWindow" ) ' this is mandatory
.Init(0, "Just a window", -1, -1, 320, 240)
.SetBackcolor(%RGB_INDIANRED)
.CloseButton = myWindow(1).CreateControl( "cCommandButton", "Close 1", 10, 200, 300, 30 )
.OtherButton = myWindow(1).CreateControl( "cCommandButton", "other button", 10, 40, 300, 30)

' want to change/add something to this button?
Local lBtn As cCommandButton At .otherButton
With lBtn
.SetFont(Font_Create("courier new", 12))
.SetTooltip("just here to annoy you")
End With
.ShowModeless()

End With

With myWindow(2)
.TypeID( "t_myWindow" )
.Init(0, "another window", 100, 100, 320, 240)
.SetBackcolor(%RGB_GREEN)
.CloseButton = myWindow(2).CreateControl( "cCommandButton", "Close 2", 10, 30, 300, 30 )
.OtherButton = myWindow(2).CreateControl( "cCommandButton", "the other other button", 10, 140, 300, 30)
SetAt( lBtn, .otherButton )
With lBtn
.SetTooltip("just here to confuse you")
.SetFont(Font_Create("comic sans ms", 14))
End With
.someLabel = myWindow(2).CreateControl("cLabel","label the label", 10, 200, 300, 30 )

.ShowModeless()

End With

With myWindow(3)
.TypeID( "t_myWindow" )
.Init(0, "one more window", 300, 300, 320, 240)
.SetBackcolor(%RGB_MIDNIGHTBLUE)
.CloseButton = myWindow(3).CreateControl("cCommandButton", "Close 3", 10, 100, 300, 30 )
.someLabel = myWindow(3).CreateControl("cLabel","wow a label", 10, 30, 300, 30 )

.ShowModeless()
End With

Do
Dialog DoEvents To numberofDialogsAlive
Loop While numberofDialogsAlive


End Function



Sub cCommandButton_Click(ByRef lButton As cCommandButton)


Local i As Long
For i = 1 To UBound(myWindow)

Select Case VarPtr(lButton)

Case myWindow(i).CloseButton
If myWindow(i).Destroy() Then Nop ' *** see below
Exit Sub ' no need to check other windows buttons now...
Case myWindow(i).otherButton
lButton.SetText( IIf$(lButton.GetText = "i was clicked", "hit me once more", "i was clicked" ))
Exit Sub
End Select

Next

End Sub

Sub cLabel_Click(ByRef lLabel As cLabel)


Local lDialog Like lLabel.DialogType At lLabel.DialogPtr

lDialog.SetCaption(IIf$( lDialog.GetCaption = "my label was clicked", "hit my label again", "my label was clicked" ))




End Sub


' Dim lControl As t_UI_Control At myWindow(1).otherbutton ... if need only base-type-functionality
' Dim lRealControl Like lControl.GetType() At Varptr(lControl) ... the real control type now

' Dim lRealControl Like Heap_Get(Peek(Dword, myWindow(1).otherButton)) At myWindow(1).otherButton
' ... both the above in one step - no pre-layover

' Dim lBtn As cCommandButton At myWindow.otherButton ' sure about the type? then this.




all included in attachement

Also some

*** issue discovered:
if a type-functions result does not get requested then some using "like" dimensioned variable inside this type-function will keep it's type in the next functions execution - this should not happen. That's why .Destroy gets "requested" here instead of simple be called

+ already new ideas, await a better version soon

ReneMiner
03-02-2015, 21:02
New approach!
Still contains only labels and commandbuttons, but the dialogs have improved and now the controls are part of the dialogs udt-structure!

This is the user-defined code:
for the window:


' example TypeUnitFile
' must be saved as "t_myWindow.tBasicU" - so filename matches typename!

' this be the user-defined window-type
'----------------------------------------------------------
Type t_myWindow Extends t_UI_Dialog

ExitButton As t_UI_cmdButton
otherButton(2) As t_UI_cmdButton
someLabel As t_UI_Label

Create As Function

ExitButton_Click As Function
otherButton_Click As Function
otherButton_GotFocus As Function
otherButton_LostFocus As Function
someLabel_Click As Function

End Type

'----------------------------------------------------------
Function t_myWindow.Create(Optional ByVal hParent As Long, _
ByVal sTitle As String, _
ByVal x As Long = -1, _
ByVal y As Long = -1 _
) As Long
'----------------------------------------------------------
' usually all windows of this type have all same properties
' except maybe parent, caption and position...

Local style As Long = %WS_CLIPCHILDREN Or _
%WS_CLIPSIBLINGS Or _
%WS_DLGFRAME Or _
%WS_CAPTION Or _
%WS_SYSMENU Or _
%WS_OVERLAPPEDWINDOW

' Local ex_style As Long = %WS_Ex...


If Function_CParams < 2 Then sTitle = "look, a window"

With Me

.hWnd = Dialog_New Pixels, hParent, sTitle, x, y, 320, 240, style ' , ex_Style
.Parent = hParent

'---Store into a dialog user slot a pointer to Me, in order to get it during dialog callback
Dialog Set User Me.hWnd, 1, VarPtr(Me)
' *** EDIT:
' pass Me.hWnd - not just .hWnd here - else ERROR if more than one window...


.ExitButton.Init(Me.hWnd, "Exit", 10, 210, 300, 24)
.someLabel.Init(Me.hWnd, "a label", 10, 20, 300, 24)
.otherButton(1).Init(Me.hWnd, "other button 1", 10, 80, 300, 24)
.otherButton(2).Init(Me.hWnd, "other button 2", 10, 120, 300, 24)


Function = .hWnd

End With



End Function

'----------------------------------------------------------
Function t_myWindow.ExitButton_Click(ByRef lDialog As t_myWindow, _
ByRef lButton As t_UI_cmdButton)
'----------------------------------------------------------

' there's no way to place Me when composing the functions name from strings
' so the first refered object is always the calling dialog, second is the control

lDialog.Destroy()


End Function


'----------------------------------------------------------
Function t_myWindow.otherButton_Click(ByRef lDialog As t_myWindow, _
ByRef lButton As t_UI_cmdButton)
'----------------------------------------------------------

lDialog.someLabel.SetText( "you clicked otherbutton(" & TStr$(lButton.Index) & ")" )



End Function


'----------------------------------------------------------
Function t_myWindow.otherButton_GotFocus(ByRef lDialog As t_myWindow, _
ByRef lButton As t_UI_cmdButton)
'----------------------------------------------------------

lButton.SetText( "i got focus" )



End Function

'----------------------------------------------------------
Function t_myWindow.otherButton_LostFocus(ByRef lDialog As t_myWindow, _
ByRef lButton As t_UI_cmdButton)
'----------------------------------------------------------

lButton.SetText( "i lost focus" )

End Function

'----------------------------------------------------------
Function t_myWindow.someLabel_Click(ByRef lDialog As t_myWindow, _
ByRef lLabel As t_UI_Label)
'----------------------------------------------------------

' there's no way to place Me when composing the functions name from strings
' so the first refered object is always the calling dialog, second is the control

lDialog.SetText(IIf$(lDialog.GetText ="you clicked my label", "click more please", "you clicked my label") )


End Function



and this is the main-script:


#MINVERSION 1.9.15.0

#INCLUDE Once "UI_OOP.tBasicU"

' include the user-type-unit for a user-window-type:
' MANDATORY HAS TO BE A SINGLE CLEAN TYPE-UNIT-FILE

#INCLUDE Once "t_myWindow.tBasicU"

' ---------------------------------------------

Function TBMain()

' lets have 3 of t_myWindow:
Local myWindow(3) As t_myWindow
Local i As Long

For i = 1 To UBound(myWindow)

If myWindow(i).Load("t_myWindow") Then
' parameter "t_myWindow" MUST MATCH .tBasicU-filename above and the typename also!
' this will load the file above and read in controls names, types and assign ControlIDs

myWindow(i).Create(0, "window" & Str$(i), 200 + 80 * i, 200 + 40 * i)
myWindow(i).ShowModeless()

EndIf
Next

Do
Dialog DoEvents To i
Loop While i


End Function


I do some code-parsing here to read controls names from the udt-description in the first file...

Also i use some additional "TypeUnitFile-manager" that adds some type-functionalities and assumes a new kind of thinBasic-TypeUnit-files - currently using simple .tBasicU as a substitute.

In type-unit-files is only allowed to have 1 Type-definition and it's Type-functions. It may contain needed external dll-declarations but no global variables nor global constants and no executeable code outside type-functions nor other "hidden secrets" so TypeUnit-files stay "clean" and are re-useable any time.

Petr Schreiber
05-02-2015, 22:48
Very cool Rene :)

I like the automagical nature of the solution (binding of events).


Petr

ReneMiner
06-02-2015, 07:29
the next improvement is on the way: the dialogs callback will in future handle only the dialog-events - controls will have theirs own events at the control-type - result in the end will be the same. Helpful were some



Call ByRef lDialog, lControl.sName & "_Click" (lControl) [To result]

(see support)

to have at least Me placed "automagical" and correct without having to pass it to the type-function as a parameter.
Also intentionally i did only want to pass an Index and not the control ByRef (since the controls name is known by user from the functions name) but it seems to have the complete control accesseable ByRef is not that bad...

And for the fututre: i heard roumors about dynamic udt-sub-arrays- what you guess would the "real" SizeOf some dynamic subArray be?
1 pointer/4 bytes or more?

ErosOlmi
06-02-2015, 08:52
Hi Rene,

I still have to understand all the details of your code so excuse me if I didn't get all the inside but ... I see one problem in your solution:
you are parsing source code loading it from disk but what if code is executed from a bundled exe? There will be no source code on disk in that case.

In this case, the only way is to give script source code similar possibilities of thinDebug to discover variable configuration at run time in order to auto-discover type configuration of elements and methods

Ciao
Eros

ReneMiner
06-02-2015, 14:09
the retrieving of controls names & types is only done this way because i can not request an

UDT_ElementName({"Typename"|Varname}, offset) (http://www.thinbasic.com/community/showthread.php?12529-3-problems-that-complicate-my-life&p=91825#post91825)

to find out controls names and i don't want the user have to pass the same information multiple times.
If it were done by a module it probably could work different.

What my Type_Include()-function does, won't work either: it's only a workaround because there's no

#Include Type "t_myType" (http://www.thinbasic.com/community/showthread.php?12529-3-problems-that-complicate-my-life&p=91825#post91825)

which does include the type-unit-file and also adds the typename to the list of known types.
thinCore "knows" the types of variables - but the only way for me is to store typenames as string so i can Dim Like

i have no Udt_GetName$(var)/TypeOf(var) to get the information and if a control-type would have a static that holds the type-information then an extended control would mess that up. A reason for

Const UDT-members (http://www.thinbasic.com/community/showthread.php?12529-3-problems-that-complicate-my-life&p=91825#post91825)

...the whole thing is more about the simple syntax to achieve as in the user-code above. If it were possible for me to take another way to get there...

ReneMiner
07-02-2015, 07:54
...anyway since is saw your code in screenshot above i'm not really motivated to continue using v 1.9.15. ;)


My current requests (see support or follow links posted above) were the same if i would use this for some TBGL-GUI instead of UI since i want my own GUI in TBGL finally work on user-side exactly as easy as above -no matter what happens behind the curtain-

ErosOlmi
07-02-2015, 13:33
...anyway since is saw your code in screenshot above i'm not really motivated to continue using v 1.9.15. ;)


;) it is not just round the corner.
I still need few weeks of work.