Bound Together Forever

BlitzMax Forums/MaxGUI Module/Bound Together Forever

dw817(Posted 2016) [#1]
Now that I am starting to work on my Carryall 750k interface, I am noticing apparently you cannot bind either global or local variables to any of the gadgets, I.E.:
g_slide=CreateSlider(h,v,x,y,zvideo,SLIDER_HORIZONTAL|SLIDER_TRACKBAR)
While I can modify this control, I must use this to read its value:
slidepos=slidervalue(g_slide)
Isn't there a way of building a Gadget and hardwiring a variable to it so I don't have to manually read the value of every gadget I need for later ? I.E.:
g_slide=CreateSlider(link(slidepos),h,v,x,y,zvideo,SLIDER_HORIZONTAL_SLIDER_TRACKBAR)
What would be a good example in coding this ?


grable(Posted 2016) [#2]
Why would you need to?

Its like this because the value is kept not by MaxGUI but by the system itself.
Windows GUI stuff is a kernel thing, so all state a window can have is kept internally.
Meaning you have to call an API function to get any value from it.

If its speed related it would actually be slower, since that "link" would have to call the relevant API in addition to the abstraction cost itself.

You could build something like that link yourself though, by using function pointers. But i see no value in doing that.
It would just be an abstraction on top of another abstraction ;)

EDIT: And even then it would still be a function call. Its impossible to make it look like a variable, since that would require language level support for it.

EDIT2: And if that link was to be totally generic, it would need some way of figuring out which gadget it was operating on. Leading to the very same "API" as the original.
Unless of course you created functions at runtime, JIT style...


dw817(Posted 2016) [#3]
That's quite a brainweaver there, Grable. Just saying it should be an available option - and was hoping it could be done. :)

Actually, it can be done w virtual variables. I didn't see that until you you mentioned, "Its impossible to make it look like a variable."

You do remember my function ?
addmenu "file,n@new state,o@open state,z@close state,-,s@save as ...,q@exit"
addmenu "help,instructions,-,about,author,credits,-,website"
Certainly a lot faster than manually typing out for each of them:
CreateMenu "New State",menuid+n,gadget[menuid],"N",modifier_command



grable(Posted 2016) [#4]
That is still a function call. What you want is to type "something" and have that something not only act like a function but also return a value.
Which is something you can only do IF the language supports it.

The furthest you could reduce it down to would be
something()
But that would require you to hardcode each and every function to directly call the API on a global.

IE not very generic ;)

And for just saving you some typing, i really see no value in doing it in the language proper.
I would instead build a parser/compiler and interpreter/virtual machine, then i could decide the rules of how everything works myself.

IE what you seem to want is a scripting language.


dw817(Posted 2016) [#5]
Writing a Game Making programming language is in my list. But I have many other projects to finish first.

(1) Carryall 750k Method (this is the one using MaxGUI)
(2) Vector Editor & Builder (make your own vector images with arc ability)
(3) sample game based on Bill Budge's Bomber game (to demonstrate vectors)
(4) Tilemaster 2016 (comprehensive at-the-pixel level editor)
(5) Back on course, S3 or - a game programming language. Perhaps both.


jsp(Posted 2016) [#6]
Not sure if I correctly understood what you wanted to do, but couldn't you just set your variable when the event from the slider occured?

Every time the event pops up the variable is set.
You can use even a hook instead of the Wait-Event-Queue.

SuperStrict

Import MaxGui.Drivers

Global SliderPos:Int

Local Window1:TGadget = CreateWindow("Window1",404,205,335,211,Null,WINDOW_TITLEBAR|WINDOW_RESIZABLE |WINDOW_STATUS |WINDOW_CLIENTCOORDS )
	Local SL2:TGadget = CreateSlider(38,28,247,40,Window1,SLIDER_HORIZONTAL | SLIDER_TRACKBAR )
		SetSliderRange( SL2,1 ,10 )
		SetSliderValue( SL2,1 )

Repeat
	WaitEvent()
	Select EventID()
		Case EVENT_WINDOWCLOSE
			Select EventSource()
				Case Window1	Window1_WC( Window1 )
			End Select

		Case EVENT_GADGETACTION
			Select EventSource()
				Case SL2	SL2_GA( SL2 , EventData() )
			End Select

	End Select
Forever

Function Window1_WC( Window:TGadget )
	DebugLog "Window Window1 wants to be closed"
	End
End Function

Function SL2_GA( Slider:TGadget , Number:Int )
'Slider Range was initially set to: 1 as Start and: 10 as End Value
	DebugLog "Slider SL2 changed to " + Number
	SliderPos=SliderValue( Slider )
End Function



degac(Posted 2016) [#7]
I think dw817 would like to 'transmit' the value to other gadgets, automatically (sort of).

Imagine to have a slider: when you move the knob, a label_text is changed accordingly AND a (for example) a ListBox() is moving its content to show a specific 'range' of value (don't know if this is possible!).
It's sure you can do this like in the example posted by jsp (just put a SetGadgetText(label,SliderPos) and other in the SL2_GA() function.
An 'automatic' solution - like SetGadgetLink(my_slider,this_label) (and you can add more item to the 'queue' to receivers) is 'good to see'

I've done something similar for one of my GUI (just graphics, in game).
I've tried to do something in the past, the idea was to implement in MaxGUI, but then I gave up (no time!), mainly because many gadgets have not 'exposed' their inner value (ie: progressBar position, you need to find where is stored the current value, same for ListBox() etc)

This was my experiment




dw817(Posted 2016) [#8]
Hi Degac. I tried your program. I'm not really understanding the source-code, but you are correct, I want to have a value I can read or set. Just by changing a variable it immediately appears as an effect in the gadgets - or I can read the variable solely to retrieve the status and position of the gadget.

I have also already written code to this effect and am continuing on.

Thanks for your submit.


grable(Posted 2016) [#9]
It looks to be an Event Multiplexer of sorts. Getting a single event from a Source gadget and "sending" it to other gadgets by updating them with the state from the event.

Not exactly what your looking for if my understanding of your post is correct, but interesting nonetheless.


grable(Posted 2016) [#10]
Building on the concepts of degacs post, heres something using variables as intermediaries.
Its not automatic though. One has to register and link gadgets with variables explicitly, and periodically call a Sync() method to update gadgets->variables or variables->gadgets depending on the current event.
But i think its pretty close to your original requirement ;)



EDIT: Fixed some bugs and added some more abstractions.


degac(Posted 2016) [#11]
@Grable

Wow... just read your code... vodoo magic in some places :D (pointer & co)
Finding the progressbar value seems so easy now! :)
Thanks a lot, something interesting to explore!


Kryzon(Posted 2016) [#12]
An abstraction that helped me a lot when working on a personal software was "properties", which would be something like a "smart variable" or a class that wraps a variable.
You can have Bool properties, Int properties, String properties etc. These properties belong to the document that the user is editing, like a "scene" for example.
The GUI of your application serves two purposes: to represent the state of properties visually to the user and to allow the user to manipulate these properties.
In the case of an integer value, a slider type of gadget can be used for that.
In the case of a boolean value, a check box is used for that. When the user toggles the check box, internally that boolean property is being modified.

When a property changes, you may want to run some specific code to do something.
You subscribe an object and a function from that object to the property. If I'm not mistaken this association takes the form of a "delegate", an object that can invoke that function.
When the property changes, it invokes each delegate that was assigned to it (with each delegate representing functions that want to be run when the property changes), so the functions 'run' and do what they're meant to.


EDIT: Added a 'BaseProperty' type with essential functionality that all properties should have (the subscriber list and notification), and all properties 'extend' this base property type.
There's plenty that can be improved in that code since it's just an example, it's not a final product.

The benefit of this abstraction is that it's got your back when your program becomes complex. You can assign the same property to several gadgets, like for example, having different colour pickers that all change the same R, G and B byte-value properties.
BlitzMax doesn't have many language features to help with this, we need to use static functions. You can do more elegant (and efficient) solutions with C++ by using templates (i.e like this).

Further reading:
- https://en.wikipedia.org/wiki/Model–view–controller (and its variations)
- https://en.wikipedia.org/wiki/Delegate_(CLI)