wxMax - The Final Push...

BlitzMax Modules Forums/Brucey's Modules/wxMax - The Final Push...

Well folks, I've been working hard on tidying up a lot the ToDo list, in an attempt to ready wxMax for a proper release - ie. where you download a .zip, extract it, and you are ready to start using it.

The plan is to create a "binary" release for the various platforms, which will include the source, the static libs + headers, and of course the pre-compiled BlitzMax modules.

And probably a generic "source" release, with which you will be able to use to build your own.

---

Yes, there are some things that are outstanding :
* wxRichTextCtrl
* wxMediaCtrl
... and some of the 3rd-party modules I've included need some TLC before I'd consider them roadworthy.

But I think I've covered about 90% of the rest of wxWidgets, which should allow for a reasonable GUI Application to be constructed :-p


Note too that there are still issues running fullscreen graphics contexts via wxWidgets. But remember that wxMax is primarily for building Apps rather than games. (Hopefully at some point we'll get
those issues fixed).

---

Anyhoo, unless anyone can report anything terrible with the current code-base (how's the propgrid Plash?), I'll start sorting out the release process and things.

I'll most likely do a test release first for some of the more hard-core developers to try out before I throw it to the lions... any interested guinea-pigs?

Oh, and I'd like to add XRC support for the next version.

Oh, and I'd like to add XRC support for the next version.


Nice!
Was about to add that on the wishlist, now that wxMax is kind of complete :)

At least there are only about 60 or so XMLHandlers to write, plus BlitzMax initialization/wrap code for each, plus the XRC framework to implement.

One wonders why I've waited so long :-)

Still, it should be an interesting little sub-project. I'm still not entirely sure how to go about it. I'm thinking along the lines of having to subclass each handler (eg. wxButtonXmlHandler), and override the DoCreateResource() method, having it call-back into BlitzMax in order to create all the objects properly.

It works in my head... we'll just have to wait and see if it works in the code ;-)

Oh... Didn't know it was that many handlers.

(how's the propgrid Plash?)
The only thing I have found, since you fixed the SetValue methods, is that there is no wxColourProperty.SetValueColour() method.

And I'm still curious if you have tried to get Graphviz working in a wxGLCanvas..

there is no wxColourProperty.SetValueColour()

It's part of wxPGProperty - in reality it's calling SetValue(wxVariant), but we don't use those...

I'm still curious if you have tried to get Graphviz working in a wxGLCanvas..


How's about this ?
SuperStrict

Framework wx.wxApp
Import wx.wxFrame
Import wx.wxglmax2D
Import wx.wxTimer
Import BaH.Graphviz
Import BaH.GraphvizMax2D
Import wx.wxMouseEvent

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

	Method OnInit()

		canvas = MyCanvas(New MyCanvas.Create(Self, -1, GRAPHICS_BACKBUFFER|GRAPHICS_DEPTHBUFFER))
	
		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

	Field renderer:TGVGraphviz
	Field mx:Int
	Field my:Int
	Field mz:Int
	Field oldZ:Int
	Field buttons:Int[] = New Int[3]	

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


		EnablePolledInput(Self)

		ConnectAny(wxEVT_TIMER, OnTick)
		ConnectAny(wxEVT_MOUSE_EVENTS, OnMouse)

		timer.Start(17)
	End Method

	Function OnMouse(event:wxEvent)
		Local evt:wxMouseEvent = wxMouseEvent(event)
		Select evt.GetEventType()
			Case wxEVT_MOTION
				Local x:Int, y:Int
				evt.GetPosition(x, y)
				EmitEvent(CreateEvent( EVENT_MOUSEMOVE, event.parent, 0, 0, x, y))
			Case wxEVT_LEFT_DOWN
				EmitEvent(CreateEvent( EVENT_MOUSEDOWN, event.parent, 1))
			Case wxEVT_LEFT_UP
				EmitEvent(CreateEvent( EVENT_MOUSEUP, event.parent, 1))
			Case wxEVT_RIGHT_DOWN
				EmitEvent(CreateEvent( EVENT_MOUSEDOWN, event.parent, 2))
			Case wxEVT_RIGHT_UP
				EmitEvent(CreateEvent( EVENT_MOUSEUP, event.parent, 2))
			Case wxEVT_MIDDLE_DOWN
				EmitEvent(CreateEvent( EVENT_MOUSEDOWN, event.parent, 3))
			Case wxEVT_MIDDLE_UP
				EmitEvent(CreateEvent( EVENT_MOUSEUP, event.parent, 3))
			Case wxEVT_MOUSEWHEEL
				EmitEvent(CreateEvent(EVENT_MOUSEWHEEL, event.Parent, evt.GetWheelRotation()))
		End Select
		event.Skip()
	End Function
	
	Method SetupGraph()
	
		renderer = TGVGraphviz.Create(640, 480, Null)
		
		' we need to create an in-memory graph...
		' something simple:
		'
		'    node2  -->   node1
		'           /
		'    node3 /
		
		Local graph:TGVGraph = TGVGraph.Create()
		
		' create some nodes
		Local node1:TGVNode = graph.addNode("node1")
		Local node2:TGVNode = graph.addNode("node2")
		Local node3:TGVNode = graph.addNode("node3")
		
		' Add a tooltip :-)
		node1.setAttr("tooltip", "Hallo!")
		
		node2.setAttr(ATTR_FONTCOLOR, "red")
		node2.setAttr(ATTR_HTML_LABEL, "<TABLE BORDER=~q0~q CELLBORDER=~q1~q CELLSPACING=~q0~q>" + ..
			"<TR><TD>Left</TD><TD PORT=~qf1~q>Mid dle</TD><TD PORT=~qf2~q>Right</TD></TR></TABLE>")
		node3.setAttr(ATTR_NODE_SHAPE, "diamond")
		
		' join the nodes together
		graph.addEdge(node2, node1)
		graph.addEdge(node3, node1)
		
		' now to construct the graph..
		renderer.buildGraph(graph)

	End Method
	

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

	Method Render()

		SetGraphics CanvasGraphics2D( Self )
		
		If Not renderer Then
			SetupGraph()
			renderer.layout("dot")
			renderer.fit(800, 480)
		End If
		

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

		SetColor(255, 255, 255)
		
		mx = MouseX()
		my = MouseY()
		mz = MouseZ()

		' tell graphviz we've moved the mouse
		renderer.mouseMove(mx, my)
		
		For Local i:Int = 1 To 3
			If MouseDown(i)
				If Not buttons[i - 1] Then
					renderer.MouseDown(mx, my, i) ' mouse button press
					buttons[i - 1] = 1
				End If
			Else
				If buttons[i - 1] Then
					buttons[i - 1] = 0
					renderer.mouseUp(mx, my, i) ' mouse button release
				End If
			End If
		Next
		
		If mz <> oldZ Then
			If mz < oldZ Then
				renderer.mouseScroll(mx, my, -1) ' scroll up - zoom in
			Else
				renderer.mouseScroll(mx, my, 1) ' scroll down - zoom out
			End If
			oldZ = mz
		End If
		
		' refresh/redraw the graph
		renderer.refresh()
	
		' draw the current tooltip under the mouse - if there is one!
		renderer.drawTooltip(mx, my + 16)
		
		' get data for selected "node" (for anything else, returns Null)
		Local obj:TGViewObject = renderer.selectedObject(GV_VIEW_NODE)
		
		If obj Then
			SetImageFont(Null)
			SetColor 100, 100, 255
			
			DrawText obj.name, 400, 0
			DrawText obj.skind, 400, 15
			
			For Local i:Int = 0 Until obj.attributes.length
				DrawText obj.attributes[i].name + " : " + obj.attributes[i].value, 400, 60 + i * 15
			Next
		End If

		
		Flip

	End Method

	Function OnTick(event:wxEvent)
		wxWindow(event.parent).Refresh()
	End Function


End Type


Knocked it together in about 10 mins from a couple of other examples. It wants a bit of a tidy up.
Usual mouse controls... left button selects, scrollwheel zooms, hold right down to move the graph around.

Actually, I'm rather happy with the ease of getting it running on wx. I'm about half-way through building a native wxDC renderer for graphviz too, but this is nice for now.

<EDIT> - For anyone that wants to try this, as well as wxMax, you'll need these modules compiled too.

:o)

One thing to note about the graphviz renderer is that it wants to run a pre-render when you first initialize it, which for Max2D means you need to have a current context when you do. Which is why I had to put the call to SetupGraph() in the Render method - it only calls it once.

:o)

Awesome, now I just need to remember exactly what I was going to use it in..

Not sorted out your Greek to English translation yet? :-p

SuperStrict

Framework BaH.libcurl
Import BRL.StandardIO

Local curl:TCurlEasy = TCurlEasy.Create()

curl.setOptInt(CURLOPT_FOLLOWLOCATION, 1)
curl.setWriteString()' use the internal string  to store the content

curl.setProgressCallback(progressCallback) ' set the progress callback function

'curl.setOptString(CURLOPT_URL, "blitzmax.com")
curl.setOptString(CURLOPT_URL, "ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=*GREEKWORDHERE*&langpair=el%7Cen")

Local res:Int = curl.perform()

curl.cleanup()

Print curl.toString()

Function progressCallback:Int(data:Object, dltotal:Double, dlnow:Double, ultotal:Double, ulnow:Double)
	Print " ++++ " + dlnow + " bytes"
	Return 0	
End Function


Nope :( still getting "" as my translated text..

You need to convert your text to UTF-8 and the escape it ;-)

Then you should get something like this :
{"responseData": {"translatedText":"Hello world!"}, "responseDetails": null, "responseStatus": 200}

Which is the result of el->en doing the above on the text to be translated.

According to the docs, you really need to set the referrer :
curl.setOptString(CURLOPT_REFERER, "some.address.for.the.referer")


EDIT: I don't want to ask questions unrelated to this thread: follow.