Waxe: FileDialog

Note:

I’ve updated this post to work with Haxe 3 by changing:
import neko.FileSystem; and import cpp.FileSystem; to import sys.FileSystem;

and a change to support Waxe 3.0:
waxePanel.setSizer(sizer); to waxePanel.set_sizer(sizer);


To explore Waxe’s FileDialog class a little let’s add some functionality to the useless button from my NMEStage post. We’ll use the button to open a file dialog box and load in a .jpg or .png file and display it in on the NMEStage.

First let’s change the button’s text:

var button:Button = Button.create( waxePanel, null, 'Open a jpg or png');

And give it a function to perform when clicked:

button.onClick = showFileDialog;

Next up the showFileDialog method for our button it needs to take a single parameter of type Dynamic sent by the button when clicked:

private function showFileDialog( event:Dynamic )
{
}

Next we’ll make the file dialog inside the showFileDialog function:

var fileDialog:FileDialog = new FileDialog( frame , "Choose an image" , "" , "" , "PNG and JPG files|*.png;*.jpg|PNG files|*.png|JPG files|*.jpg");

In the FileDialog’s constructor we set it’s parent, the title text displayed in the FileDialog itself, default directory, default file, then a file filter string. Let’s take a closer look at the file filter string:

"PNG and JPG files|*.png;*.jpg|PNG files|*.png|JPG files|*.jpg"

The above string has 3 different filters, one that shows PNG and JPGs in the FileDialog, one that shows just PNGs and lastly one for just JPGs. Each filter takes the form:

|

multiple file filters are separated by a single | . Be careful of extra white spaces when listing file formats as this will stop filters working as expected.

With our FileDialog instanced we now need to show it. We do this with .showModal().

if( fileDialog.showModal() )
{
	trace( "Selected" );
}
else
{
	trace( "Cancelled" );
}

.showModal() returns a Bool when done. The Bool is true when a file has been selected, and false when the FileDialog has been cancelled without selecting a file. It also returns true if the user enters a file name with the keyboard and presses the open button, as it does not check whether the file exists when the user enters a file name we will have to check ourselves later.

Here’s what the showFileDialog method should look like so far:

private function showFileDialog( event:Dynamic )
{
	var fileDialog:FileDialog = new FileDialog( frame , "Choose an image" , "" , "" , "PNG and JPG files|*.png;*.jpg|PNG files|*.png|JPG files|*.jpg");

	//
	if( fileDialog.showModal() )
	{
		trace( "Selected" );
	}
	else
	{
		trace( "Cancelled" );
	}
}

To load the file we selected let’s replace “trace( “Selected” );” with some code to load our file:

// Build path
var path:String =  fileDialog.directory + "/" + fileDialog.file ;

// File Exists?
if( !FileSystem.exists(  path ) )
{
	trace( "File does not exist." );
	return;
}

loader = new nme.display.Loader( );
loader.contentLoaderInfo.addEventListener( nme.events.Event.COMPLETE , imageLoadComplete );
loader.load( new nme.net.URLRequest( path ) );

FileDialog has a number of useful properties for once the user has selected a file:

var path:String =  fileDialog.directory + "/" + fileDialog.file ;

Here we build the path of our file from FileDialogs directory and file properties.

Next I check to see if the file exists using Neko or Cpp’s FileSystem.exists method:

if( !FileSystem.exists(  path ) )
{
	trace( "File does not exist." );
	return;
}

Next the actual loading of the file using NME’s Loader class.

loader = new nme.display.Loader( );
loader.contentLoaderInfo.addEventListener( nme.events.Event.COMPLETE , imageLoadComplete );
loader.load( new nme.net.URLRequest( path ) );

Finally we need to add a handler for when loader completes it’s load operation:

private function imageLoadComplete( event:nme.events.Event ):Void
{
	nmeStage.stage.addChild( loader );
}

We’ll need to change the nmeStage from a local variable to an instance variable so we can access it the handler, then we can add our image to it’s stage.

Here’s the full source:

package;

import wx.App;
import wx.Button;
import wx.Frame;
import wx.NMEStage;
import wx.Panel;
import wx.Sizer;
import wx.BoxSizer;
import wx.FileDialog;

import nme.display.StageAlign;
import nme.display.StageScaleMode;
import nme.events.Event;
import nme.net.URLRequest;
import nme.display.Loader;

#if neko
import sys.FileSystem;
#end

#if cpp
import sys.FileSystem;
#end

class Main
{
	private var frame:Frame;
	private var loader:Loader;
	private var nmeStage:NMEStage;

	function new()
	{
		// Make an app window
		frame = Frame.create(null, "WaxeApp" , null , { width:400 , height:400 } );

		// Make a panel
		var waxePanel:Panel = Panel.create( frame );
		var button:Button = Button.create( waxePanel, null, 'Open a jpg or png');

		button.onClick = showFileDialog;

		// Make an NME stage
		nmeStage = NMEStage.create( waxePanel );
		nmeStage.stage.align = StageAlign.TOP_LEFT;
		nmeStage.stage.scaleMode = StageScaleMode.NO_SCALE;
		// Draw something on the NMEStage
		nmeStage.stage.graphics.beginFill( 0x000000 );
		nmeStage.stage.graphics.drawCircle( 50 , 50 , 50 );
		nmeStage.stage.graphics.endFill();

		// Auto position the panel and NMEStage with a sizer
		var sizer:Sizer = BoxSizer.create(true);
		waxePanel.set_sizer(sizer);
		sizer.add( button , 1 , Sizer.EXPAND | Sizer.BORDER_ALL , 5 );
		sizer.add( nmeStage , 3 , Sizer.EXPAND | Sizer.BORDER_ALL , 5);

		// Show your window
		App.setTopWindow( frame );
		frame.shown = true;
	}

	// Make and show the FileDialog
	private function showFileDialog( event:Dynamic )
	{
		var fileDialog:FileDialog = new FileDialog( frame , "Choose an image" , "" , "" , "PNG and JPG files|*.png;*.jpg|PNG files|*.png|JPG files|*.jpg");

		//
		if( fileDialog.showModal() )
		{
			// Build path
			var path:String =  fileDialog.directory + "/" + fileDialog.file ;

			// File Exists?
			if( !FileSystem.exists(  path ) )
			{
				trace( "File does not exist." );
				return;
			}

			loader = new nme.display.Loader( );
			loader.contentLoaderInfo.addEventListener( nme.events.Event.COMPLETE , imageLoadComplete );
			loader.load( new nme.net.URLRequest( path ) );
		}
		else
		{
			trace( "Cancelled" );
		}
	}

	// Loaded an Image
	private function imageLoadComplete( event:nme.events.Event ):Void
	{
		nmeStage.stage.addChild( loader );
	}

	// Entry
	public static function main()
	{
		App.boot( function(){ new Main(); } );
	}
}

7 Responses to Waxe: FileDialog

  1. cambiatablog says:

    Great! Thanx!

  2. Franky says:

    Very cool, thanks for sharing this.

  3. guish says:

    Thanks for sharing, this is great ! But it looks like NME+Waxe combination doesn’t work in most recent version of NME (3.4.4) ( and hxcpp – 2.10+) 😦

  4. Nick Holder says:

    That’s a shame. Looks like I’m still on NME 3.4.3 and Haxe 2.10 and it seems to compile ok.

  5. hak98 says:

    Thanks for the great example. I’m on Mac and I can get it to compile and run just fine (latest version of everything). However, I have a problem quitting the app. As an experiment I changed the button function to “wx.App.quit();” – what happens then is that an empty larger window gets opened – only if I close this new window and click the button again, the app terminates. Do I need to destroy the NMEStage somehow before exiting? Any ideas?

  6. Nick Holder says:

    Sorry for the delay in answering you post hak98, and unfortunately I don’t have any useful ideas for you right now.

  7. Nick Holder says:

    I just gave the code a go (on my WIn7 PC) with this showFileDialog:

    private function showFileDialog( event:Dynamic )
    {
    App.quit();
    }

    And it quit OK. Perhaps it’s different on mac or a later version of something has changed?

Leave a reply to cambiatablog Cancel reply