wxglmax2d

BlitzMax Forums/Brucey's Modules/wxglmax2d

slenkar(Posted 2009) [#1]
Im trying to put a wxglmax2d canvas in a notebook
First I experimented with putting the canvas on a panel.

SuperStrict

Framework wx.wxApp
Import wx.wxFrame
Import wx.wxglmax2D
Import wx.wxTimer
Import wx.wxpanel
SetGraphicsDriver GLMax2DDriver()

New MyApp.run()


Type MyApp Extends wxApp

	Field frame:MyFrame

	Method OnInit:Int()

		' Create the main application windowType MyFrame Extends wxFrame

		frame = MyFrame(New MyFrame.Create(,,"", , , 640, 480))
		
		' Show it and tell the application that it's our main window
		frame.show(True)
		SetTopWindow(frame)

		Return True
	End Method

End Type

Type MyFrame Extends wxFrame

	Field canvas:MyCanvas
	Field panel:wxpanel
	Method OnInit()
	
		panel:wxpanel= wxpanel.CreatePanel(Self)
	Local sizer:wxboxsizer=wxboxsizer.createboxsizer(True)
	
		canvas = MyCanvas(New MyCanvas.Create(panel, -1, GRAPHICS_BACKBUFFER|GRAPHICS_DEPTHBUFFER))
	sizer.add(canvas,1,WXEXPAND| wxALL)
	panel.setsizer(sizer)
		ConnectAny(wxEVT_CLOSE, OnClose)
	End Method
	
	Function OnClose(event:wxEvent)
		MyFrame(event.parent).canvas.timer.Stop() ' we really need to stop the timer on Mac...
		event.Skip()
	End Function

End Type


Type MyCanvas Extends wxGLCanvas

	Field timer:wxTimer

	Method OnInit()
		SetBackgroundStyle(wxBG_STYLE_CUSTOM)
	
		timer = New wxTimer.Create(Self)


		ConnectAny(wxEVT_TIMER, OnTick)

		timer.Start(100)
	End Method

	Method OnPaint(event:wxPaintEvent)
		Render()
	End Method

	Method Render()

		SetGraphics CanvasGraphics2D( Self )

		SetClsColor(255, 255, 255)
		SetColor(0, 0, 0)
		
		Cls

		drawClock()
		
		Flip

	End Method

	Function OnTick(event:wxEvent)
		wxWindow(event.parent).Refresh()
	End Function
	
	
	Method drawClock()
	
		SetLineWidth(2)

		Local x:Int = 200, y:Int = 200
		Local radius:Int = 100
		' clock ticks
		For Local i:Int = 0 Until 12
			Local inset:Double = 0
		
			If i Mod 3 = 0 Then
				SetLineWidth(2)
				inset = 0.2 * radius
			Else
				inset = 0.1 * radius
				SetLineWidth(1)
			End If
			
			DrawLine x + (radius - inset) * Cos(i * 30), y + (radius - inset) * Sin(i * 30), ..
				x + radius * Cos(i * 30), y + radius * Sin (i * 30)
			
			' draw numbers
			inset = 0.3 * radius
			
			Local t:Int = (i + 2) Mod 12 + 1
			DrawText romanNumerals(t), x + (radius - inset) * Cos(i * 30) - 7, y + (radius - inset) * Sin(i * 30) - 6
		Next


		' clock hands
		Local hours:Int = CurrentTime()[0..2].toInt() Mod 12
		Local minutes:Int = CurrentTime()[3..5].toInt()
		Local seconds:Int = CurrentTime()[6..8].toInt()
		
		' hour hand:
		' the hour hand is rotated 30 degrees  per hour + 1/2 a degree per minute
		'
		SetLineWidth(4)

		DrawLine x, y, x + radius / 2 * Sin(30 * hours + minutes / 2.0), ..
				   y + radius / 2 * -Cos(30 * hours + minutes / 2.0)
		
		
		' minute hand:
		' the minute hand is rotated 6 degrees per minute + 1/10 a degree per second
		'
		SetLineWidth(2)
		DrawLine x, y, x + radius * 0.75 * Sin(6 * minutes + seconds / 10.0), ..
				   y + radius * 0.75 * -Cos(6 * minutes + seconds / 10.0)
		
		' seconds hand:
		' the second hand is rotated 6 degrees per second
		'
		SetColor(255, 0, 0)

		DrawLine x, y, x + radius * 0.7 * Sin(6 * seconds), ..
				   y + radius * 0.7 * -Cos(6 * seconds)


	End Method

	Method romanNumerals:String(value:Int)
		Local rn:String = ""
		
		While value > 9
			rn:+ "X"
			value:- 10
		Wend
	
		If value > 8 Then
			rn:+ "IX"
			value:- 9
		End If
		
		If value > 4 Then
			rn:+ "V"
			value:- 5
		End If
		
		If value > 3 Then
			rn:+ "IV"
			value:- 4
		End If
		
		While value > 0
			rn:+ "I"
			value:- 1
		Wend
		
		Return rn
	End Method

End Type


When you maximize the window the canvas doesnt expand.


I tried putting a frame in a note book but when you press the X it crashes the entire app/


Tommo(Posted 2009) [#2]
You can put a " Setviewport(0,0,graphicsWidth(),graphicsHeight()) " after " SetGraphics(...) " in your render method.


slenkar(Posted 2009) [#3]
thanks! it worked


slenkar(Posted 2009) [#4]
when you close the notebook page the app crashes:

SuperStrict

Framework wx.wxApp
Import wx.wxFrame
Import wx.wxglmax2D
Import wx.wxTimer
Import wx.wxPanel
Import wx.wxaui
SetGraphicsDriver GLMax2DDriver()

New MyApp.run()


Type MyApp Extends wxApp

	Field frame:MyFrame

	Method OnInit:Int()

		' Create the main application windowType MyFrame Extends wxFrame

		frame = MyFrame(New MyFrame.Create(,,"", , , 640, 480))
		
		' Show it and tell the application that it's our main window
		frame.show(True)
		SetTopWindow(frame)

		Return True
	End Method

End Type

Type MyFrame Extends wxFrame

	Field canvas:MyCanvas
	Field canvas_panel:wxPanel
	Field notebook_panel:wxPanel
	Field notebook:wxAuiNotebook
	Field canvas_sizer:wxBoxSizer
	Field notebook_sizer:wxBoxSizer
	
	Method OnInit()
	Local notebook_panel:wxPanel=wxPanel.CreatePanel(Self)
	notebook = New wxAuiNotebook.Create(notebook_panel, wxID_ANY,,,,, wxAUI_NB_DEFAULT_STYLE)
	notebook_sizer:wxBoxSizer=wxBoxSizer.createboxsizer(True)
	notebook_sizer.add(notebook,1, wxALL|wxEXPAND, 5)
	notebook_panel.setsizer(notebook_sizer)
	
		canvas_panel:wxPanel= wxPanel.CreatePanel(notebook)
	canvas_sizer:wxBoxSizer=wxBoxSizer.createboxsizer(True)
	
		canvas = MyCanvas(New MyCanvas.Create(canvas_panel, -1, GRAPHICS_BACKBUFFER|GRAPHICS_DEPTHBUFFER))
	canvas_sizer.add(canvas,1,WXEXPAND| wxALL,5)
	canvas_panel.setsizer(canvas_sizer)
		ConnectAny(wxEVT_CLOSE, OnClose)
		
		notebook.addpage(canvas_panel,"New",True)
	End Method
	
	Function OnClose(event:wxEvent)
		MyFrame(event.parent).canvas.timer.Stop() ' we really need to stop the timer on Mac...
		event.Skip()
	End Function

End Type


Type MyCanvas Extends wxGLCanvas

	Field timer:wxTimer

	Method OnInit()
		SetBackgroundStyle(wxBG_STYLE_CUSTOM)
	
		timer = New wxTimer.Create(Self)


		ConnectAny(wxEVT_TIMER, OnTick)

		timer.Start(100)
	End Method

	Method OnPaint(event:wxPaintEvent)
		Render()
	End Method

	Method Render()

		SetGraphics CanvasGraphics2D( Self )
		SetViewport(0,0,GraphicsWidth(),GraphicsHeight())
		SetClsColor(255, 255, 255)
		SetColor(0, 0, 0)
		
		Cls

		drawClock()
		
		Flip

	End Method

	Function OnTick(event:wxEvent)
		wxWindow(event.parent).Refresh()
	End Function
	
	
	Method drawClock()
	
		SetLineWidth(2)

		Local x:Int = 200, y:Int = 200
		Local radius:Int = 100
		' clock ticks
		For Local i:Int = 0 Until 12
			Local inset:Double = 0
		
			If i Mod 3 = 0 Then
				SetLineWidth(2)
				inset = 0.2 * radius
			Else
				inset = 0.1 * radius
				SetLineWidth(1)
			End If
			
			DrawLine x + (radius - inset) * Cos(i * 30), y + (radius - inset) * Sin(i * 30), ..
				x + radius * Cos(i * 30), y + radius * Sin (i * 30)
			
			' draw numbers
			inset = 0.3 * radius
			
			Local t:Int = (i + 2) Mod 12 + 1
			DrawText romanNumerals(t), x + (radius - inset) * Cos(i * 30) - 7, y + (radius - inset) * Sin(i * 30) - 6
		Next


		' clock hands
		Local hours:Int = CurrentTime()[0..2].toInt() Mod 12
		Local minutes:Int = CurrentTime()[3..5].toInt()
		Local seconds:Int = CurrentTime()[6..8].toInt()
		
		' hour hand:
		' the hour hand is rotated 30 degrees  per hour + 1/2 a degree per minute
		'
		SetLineWidth(4)

		DrawLine x, y, x + radius / 2 * Sin(30 * hours + minutes / 2.0), ..
				   y + radius / 2 * -Cos(30 * hours + minutes / 2.0)
		
		
		' minute hand:
		' the minute hand is rotated 6 degrees per minute + 1/10 a degree per second
		'
		SetLineWidth(2)
		DrawLine x, y, x + radius * 0.75 * Sin(6 * minutes + seconds / 10.0), ..
				   y + radius * 0.75 * -Cos(6 * minutes + seconds / 10.0)
		
		' seconds hand:
		' the second hand is rotated 6 degrees per second
		'
		SetColor(255, 0, 0)

		DrawLine x, y, x + radius * 0.7 * Sin(6 * seconds), ..
				   y + radius * 0.7 * -Cos(6 * seconds)


	End Method

	Method romanNumerals:String(value:Int)
		Local rn:String = ""
		
		While value > 9
			rn:+ "X"
			value:- 10
		Wend
	
		If value > 8 Then
			rn:+ "IX"
			value:- 9
		End If
		
		If value > 4 Then
			rn:+ "V"
			value:- 5
		End If
		
		If value > 3 Then
			rn:+ "IV"
			value:- 4
		End If
		
		While value > 0
			rn:+ "I"
			value:- 1
		Wend
		
		Return rn
	End Method

End Type




Brucey(Posted 2009) [#5]
My guess is that the timer ticks (or has already ticked and is in the process of raising an event) after the widget is destroyed.
It also crashes on the Mac, but if I comment out the timer start(), it doesn't crash.


slenkar(Posted 2009) [#6]
if you put a debuglog command in the OnClose function
youll see that it is never called even if it is put in the canvas type

I had a look through the constants like wxevt_destroy

and associated them with OnClose but the function is still never called.


Brucey(Posted 2009) [#7]
Ah. I suppose that is what the missing event wxWindowDestroyEvent is for :-)

the Close event is for a top-level window, I believe.

I'm looking into adding the event now.
Apologies.


slenkar(Posted 2009) [#8]
I tried to get the canvas on 'event closing' but the canvas seems to be already destroyed before I can free the timer:

SuperStrict

Framework wx.wxApp
Import wx.wxFrame
Import wx.wxglmax2D
Import wx.wxTimer
Import wx.wxPanel
Import wx.wxFlatNotebook
SetGraphicsDriver GLMax2DDriver()

New MyApp.run()


Type MyApp Extends wxApp

	Field frame:MyFrame

	Method OnInit:Int()

		' Create the main application windowType MyFrame Extends wxFrame

		frame = MyFrame(New MyFrame.Create(,,"", , , 640, 480))
		
		' Show it and tell the application that it's our main window
		frame.show(True)
		SetTopWindow(frame)

		Return True
	End Method

End Type

Type MyFrame Extends wxFrame

	Field canvas:MyCanvas
	Field canvas_panel:wxPanel
	Field notebook_panel:wxPanel
	Field notebook:wxFlatNotebook
	Field canvas_sizer:wxBoxSizer
	Field notebook_sizer:wxBoxSizer
	
	Method OnInit()
	Local notebook_panel:wxPanel=wxPanel.CreatePanel(Self)
	notebook = New wxFlatNotebook.Create(notebook_panel, wxID_ANY)
	notebook_sizer:wxBoxSizer=wxBoxSizer.createboxsizer(True)
	notebook_sizer.add(notebook,1, wxALL|wxEXPAND, 5)
	notebook_panel.setsizer(notebook_sizer)
	
		canvas_panel:wxPanel= wxPanel.CreatePanel(notebook)
	canvas_sizer:wxBoxSizer=wxBoxSizer.createboxsizer(True)
	
		canvas = MyCanvas(New MyCanvas.Create(canvas_panel, -1, GRAPHICS_BACKBUFFER|GRAPHICS_DEPTHBUFFER))
	canvas_sizer.add(canvas,1,WXEXPAND| wxALL,5)
	canvas_panel.setsizer(canvas_sizer)
	
			Connect(-1, wxEVT_COMMAND_FLATNOTEBOOK_PAGE_CLOSING, OnPageClosing)
		notebook.addpage(canvas_panel,"New",True)
		'notebook.deleteallpages()
	End Method
	
Function onpageclosing(event:wxEvent)

Local win:wxWindow=wxWindow(wxFlatNotebookEvent(event).parent)

Local fram:myFrame=myFrame(win)
Local page:wxWindow=fram.notebook.getpage(wxFlatNotebookEvent(event).getselection())
Local canv:mycanvas=mycanvas(page)
DebugLog "on page closing"
DebugLog canv.inty
EndFunction

End Type




Type MyCanvas Extends wxGLCanvas

	Field timer:wxTimer
	Field inty:Int
	Function OnClose(event:wxEvent)
		DebugLog "hey"
		MyFrame(event.parent).canvas.timer.Stop() ' we really need to stop the timer on Mac...
		event.Skip()
	End Function

	Method OnInit()
		SetBackgroundStyle(wxBG_STYLE_CUSTOM)
	
		timer = New wxTimer.Create(Self)
		inty=123
		ConnectAny(wxEVT_CLOSE, OnClose)
		ConnectAny(wxEVT_TIMER, OnTick)

		timer.Start(100)
	End Method

	Method OnPaint(event:wxPaintEvent)
		Render()
	End Method

	Method Render()

		SetGraphics CanvasGraphics2D( Self )
		SetViewport(0,0,GraphicsWidth(),GraphicsHeight())
		SetClsColor(255, 255, 255)
		SetColor(0, 0, 0)
		
		Cls

		drawClock()
		
		Flip

	End Method

	Function OnTick(event:wxEvent)
		wxWindow(event.parent).Refresh()
		
	End Function
	
	
	Method drawClock()
	
		SetLineWidth(2)

		Local x:Int = 200, y:Int = 200
		Local radius:Int = 100
		' clock ticks
		For Local i:Int = 0 Until 12
			Local inset:Double = 0
		
			If i Mod 3 = 0 Then
				SetLineWidth(2)
				inset = 0.2 * radius
			Else
				inset = 0.1 * radius
				SetLineWidth(1)
			End If
			
			DrawLine x + (radius - inset) * Cos(i * 30), y + (radius - inset) * Sin(i * 30), ..
				x + radius * Cos(i * 30), y + radius * Sin (i * 30)
			
			' draw numbers
			inset = 0.3 * radius
			
			Local t:Int = (i + 2) Mod 12 + 1
			DrawText romanNumerals(t), x + (radius - inset) * Cos(i * 30) - 7, y + (radius - inset) * Sin(i * 30) - 6
		Next


		' clock hands
		Local hours:Int = CurrentTime()[0..2].toInt() Mod 12
		Local minutes:Int = CurrentTime()[3..5].toInt()
		Local seconds:Int = CurrentTime()[6..8].toInt()
		
		' hour hand:
		' the hour hand is rotated 30 degrees  per hour + 1/2 a degree per minute
		'
		SetLineWidth(4)

		DrawLine x, y, x + radius / 2 * Sin(30 * hours + minutes / 2.0), ..
				   y + radius / 2 * -Cos(30 * hours + minutes / 2.0)
		
		
		' minute hand:
		' the minute hand is rotated 6 degrees per minute + 1/10 a degree per second
		'
		SetLineWidth(2)
		DrawLine x, y, x + radius * 0.75 * Sin(6 * minutes + seconds / 10.0), ..
				   y + radius * 0.75 * -Cos(6 * minutes + seconds / 10.0)
		
		' seconds hand:
		' the second hand is rotated 6 degrees per second
		'
		SetColor(255, 0, 0)

		DrawLine x, y, x + radius * 0.7 * Sin(6 * seconds), ..
				   y + radius * 0.7 * -Cos(6 * seconds)


	End Method

	Method romanNumerals:String(value:Int)
		Local rn:String = ""
		
		While value > 9
			rn:+ "X"
			value:- 10
		Wend
	
		If value > 8 Then
			rn:+ "IX"
			value:- 9
		End If
		
		If value > 4 Then
			rn:+ "V"
			value:- 5
		End If
		
		If value > 3 Then
			rn:+ "IV"
			value:- 4
		End If
		
		While value > 0
			rn:+ "I"
			value:- 1
		Wend
		
		Return rn
	End Method

End Type





slenkar(Posted 2009) [#9]
were you succesful?


DavidDC(Posted 2009) [#10]
What OS are you using?

I'm not using the latest svn update but it doesn't crash for me in XP(as long as you don't attempt to access canv.inty since canv is null).

In OnPageClosing accessing the canvas via MyFrame(event.parent).canvas might be a better way to go.