Max GUI: Can a canvas be resized dynamically?

BlitzMax Forums/BlitzMax Beginners Area/Max GUI: Can a canvas be resized dynamically?

Leo Santos(Posted 2006) [#1]
Hi Everybody,

I'm running into a problem with Max GUI: Whenever I create a canvas inside a window, and then resize the window, the canvas doesn't update its size, even tough it's set with "Edge_Relative". Its borders actually follow the Window, but nothing gets rendered in the newly created area.

Here, an example code:


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

Strict

Local WindowMain:Tgadget = CreateWindow ("Test",50,50, 320,240, Null, Window_Titlebar|Window_Resizable|WIndow_Status)

Local Viewport:TGadget = CreateCanvas (10, 10, 290, 140, WindowMain, 1)
SetGadgetLayout Viewport,1,1,1,1

Local Timer:TTimer=CreateTimer(60)
Local X:Int=0

Repeat
	WaitEvent()
	Select EventID()
		Case Event_WindowCLose
			End
			
		Case Event_TimerTick
			x=x+1
			RedrawGadget(viewport)
		
		Case Event_GadgetPaint
			SetGraphics CanvasGraphics (Viewport)
			Cls
			DrawRect (X,10,30,30)
			Flip
			
	End Select
Forever

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


Help!
Leo.


Brucey(Posted 2006) [#2]
The canvas is a Graphics container. I imagine you'd have to recreate it fresh anytime you wanted to resize it.


skidracer(Posted 2006) [#3]
You mean while you are resizing? The canvas redraws ok for me in your test when you have finished resizing.

If you want to draw the canvas while resizing you will need to use event hooking.


skidracer(Posted 2006) [#4]
Oh, it's also not resizing the viewport, try this code:
Strict

Local WindowMain:Tgadget = CreateWindow ("Test",50,50, 320,240, Null, Window_Titlebar|Window_Resizable|WIndow_Status)

Local Viewport:TGadget = CreateCanvas (10, 10, 290, 140, WindowMain, 1)
SetGadgetLayout Viewport,1,1,1,1

Local Timer:TTimer=CreateTimer(60)
Local X:Int=0

Repeat
	WaitEvent()
	Select EventID()
		Case Event_WindowCLose
			End
			
		Case Event_TimerTick
			x=x+1
			RedrawGadget(viewport)
		
		Case Event_GadgetPaint
			SetGraphics CanvasGraphics (Viewport)
			SetViewport 0,0,GadgetWidth(viewport),GadgetHeight(viewport)
			Cls
			DrawRect (X,10,30,30)
			DrawLine 0,0,GadgetWidth(viewport),GadgetHeight(viewport)
			Flip
			
	End Select
Forever



Leo Santos(Posted 2006) [#5]
Yup! That works!

Thanks a lot!... and I'll take a look into event hooking to redraw while resizing, but that's a minor issue.

By the way, I'm really enjoying BlitzMax, but the documentation is a little...weak...sometimes...

See ya!
Leo.


CS_TBL(Posted 2006) [#6]
join the club :)


ImaginaryHuman(Posted 2006) [#7]
On some systems, when you resize the window it actually realtime scales the window contents even if your software isn't intending to do so. It does this on my iBook, but it doesn't do it on my iMac.


Dreamora(Posted 2006) [#8]
On windows, this is controlled through settings you can do (show content while window resize and others ... I've disabled all of them anyway ... eye candy that cost 5-10% speed for nothing usefull)


Beaker(Posted 2006) [#9]
skidracers example above, stops working as soon as I resize the window. This could be related to a bug I reported where SetViewPort would break (on my machine) when I had screen cloning turned on (a feature of my gfx card). In this case I don't have cloning turned on tho. :/

[EDIT: actually I see nothing until I comment out the SetViewPort line, and even then a window resize means I still see nothing again.]


ImaginaryHuman(Posted 2006) [#10]
Using event hooks alone won't fix it. As I found elsewhere, the resize gadget freezes all other events while the user is holding the mouse button down and only lets through WINDOW_RESIZE events when the mouse intially stops moving after having been moved. Timertick events do not flow through during the holding of the mouse button, or any other events, so nothing gets updated.

At the moment the only solution to this that I could come up with is to remove WINDOW_RESIZEABLE from the window tags when you create it, and then implement your own resize gadget. It's fairly simple ... when the user clicks in the gadget area and you get a relevant event for that, set a flag to say that they're clicking on the resize gadget, which only gets unset when you get the next mouseup event (which only resets the status if it was previously set to true). Then you use the delta of where the mouse was when the user first clicked it, subtracted from where the mouse now is, to find out how much difference to that the window size has changed. Then use SetGadgetShape() to resize the window to the new size. That should be called from within the TIMERTICK event, which only resizes the window if the mouse coords are different to what they were in the previous frame. I've tried this and it works fine. The only drawback is you don't have the `default look` for the resize gadget for the platform you're on, unless maybe you fake it.

I requested already that the resize gadget be allowed to let timertick events through. When you click and move the window's title bar, even though it handles moving the window it still lets TIMERTICK events through which is great. But it doesn't do it for the resize gadget, it just freezes everything into a modal operation until the user either stops moving the mouse or lets the button go.


skidracer(Posted 2006) [#11]
beaker, can you try modifying brl.mod/d3d7max2d.mod/d3d7max2d.bmx[316]:

	Method SetViewport( x,y,width,height )
		vp_rect=[x,y,x+width,y+height]
		
		If x=0 And y=0 And width=GraphicsWidth() And height=GraphicsHeight()
			device.SetRenderState D3DRS_CLIPPLANEENABLE,0
		Else
			Local err
			If device.SetClipPlane(0,[1.0,0.0,0.0,-Float(x)]) err=True
			If device.SetClipPlane(1,[-1.0,0.0,0.0,Float(x+width)]) err=True
			If device.SetClipPlane(2,[0.0,1.0,0.0,-Float(y)]) err=True
			If device.SetClipPlane(3,[0.0,-1.0,0.0,Float(y+height)]) err=True
			If err Notify "device does not support clipplanes"
			device.SetRenderState D3DRS_CLIPPLANEENABLE,15
		EndIf

	End Method




Beaker(Posted 2006) [#12]
No change, and no Notify thrown.