NiftyGui: File Selector

Hello,

I implemented a file selector. Perhaps it may help the one or the other. Included are:

  • layout guis without xml
  • using the ControlBuilder
  • Programming your own control

Have fun

Michael

The main program:
[java]import java.io.File;

import com.jme3.app.SimpleApplication;
import com.jme3.niftygui.NiftyJmeDisplay;

import de.lessvoid.nifty.Nifty;
import de.lessvoid.nifty.builder.ControlBuilder;
import de.lessvoid.nifty.builder.ControlDefinitionBuilder;
import de.lessvoid.nifty.builder.LayerBuilder;
import de.lessvoid.nifty.builder.PanelBuilder;
import de.lessvoid.nifty.builder.ScreenBuilder;
import de.lessvoid.nifty.controls.button.builder.ButtonBuilder;
import de.lessvoid.nifty.controls.dropdown.builder.DropDownBuilder;
import de.lessvoid.nifty.controls.listbox.builder.ListBoxBuilder;
import de.lessvoid.nifty.controls.textfield.builder.TextFieldBuilder;
import de.lessvoid.nifty.screen.Screen;

public class FileSelector extends SimpleApplication implements FileSelectorObserver {

private Nifty nifty;
private Screen screen;
public static void main(String[] args){
	FileSelector app = new FileSelector();
	app.setPauseOnLostFocus(false);
	app.start();
}

public void simpleInitApp() {
	NiftyJmeDisplay niftyDisplay = new NiftyJmeDisplay(assetManager,
			inputManager,
			audioRenderer,
			guiViewPort);
	nifty = niftyDisplay.getNifty();
	nifty.loadStyleFile("nifty-default-styles.xml");
	nifty.loadControlFile("nifty-default-controls.xml");

	guiViewPort.addProcessor(niftyDisplay);

	registerControl();
	screen = new ScreenBuilder("start") {{
		layer(new LayerBuilder("baseLayer") {{
			childLayoutCenter();

			control(new ControlBuilder("fileSelector","FileSelectionControl") {{
				set("textButtonCancel", "CANCEL");
				set("textButtonOpen", "OPEN");
				set("filterText", "Text Files (*.txt)");
				set("filterEnding", ".txt");
			}});
		}});
	}}.build(nifty);
	nifty.gotoScreen("start");
	screen.findControl("fileSelector", FileSelectionController.class).setDirectory(new File("./"));
	screen.findControl("fileSelector", FileSelectionController.class).setFileSelectorObserver(this);
	flyCam.setEnabled(false);

	inputManager.setCursorVisible(true);
}

private void registerControl() {
	new ControlDefinitionBuilder("FileSelectionControl") {{
		controller("FileSelectionController");
		panel(new PanelBuilder() {{
			childLayoutVertical();
			focusable(false);
			width("600px");
			panel(new PanelBuilder() {{
				childLayoutVertical();
				focusable(false);
				panel(new PanelBuilder() {{
					height("30px");
					childLayoutHorizontal();
					control(new DropDownBuilder("#rootDropBox") {{
						width("140px");
						height("22px");
						marginLeft("10px");
						marginRight("10px");

						set("vertical","on");
						set("#panel#listbox#horizontal","off");
						set("displayItems","3");
						font("aurulent-sans-16.fnt");
						focusable(false);
					}});
					control(new TextFieldBuilder("#directory") {{
						alignLeft();
						textHAlignRight();
						focusable(true);
						font("aurulent-sans-16.fnt");
						width("430px");
					}});
				}});
				panel(new PanelBuilder() {{
					width("100%");
					childLayoutCenter();
					control(new ListBoxBuilder("#listFiles") {{
						width("580px");
						set("vertical","on");
						set("horizontal","off");
						marginLeft("10px");
						marginRight("10px");
						backgroundColor("#0000");
						set("displayItems","12");
						font("aurulent-sans-16.fnt");
						focusable(false);
					}});
				}});
				panel(new PanelBuilder() {{
					height("6px");
				}});
				panel(new PanelBuilder() {{
					width("100%");
					height("25px");
					childLayoutHorizontal();
					control(new DropDownBuilder("#fileTypeDropBox") {{
						width("430px");
						height("22px");
						marginLeft("10px");
						marginRight("10px");
						set("vertical","on");
						set("horizontal","off");
						set("displayItems","2");
						font("aurulent-sans-16.fnt");
						focusable(false);
					}});
					control(new ButtonBuilder("#buttonCancel","$textButtonCancel") {{
						width("140px");
						height("22px");
					}});
				}});
				panel(new PanelBuilder() {{
					width("100%");
					height("25px");
					childLayoutHorizontal();
					control(new TextFieldBuilder("#filename") {{
						alignLeft();
						textHAlignLeft();
						font("aurulent-sans-16.fnt");
						width("430px");						
						height("22px");
						marginLeft("10px");
						marginRight("10px");
						focusable(true);
					}});
					control(new ButtonBuilder("#buttonOpen","$textButtonOpen") {{
						width("140px");
						height("22px");
					}});
				}});
			}});
		}});
	}}.registerControlDefintion(nifty);


}

@Override
public void selected(boolean ok, File directory, File file) {
	System.out.println("Selected: ");
	System.out.println("ok: " + ok);
	System.out.println("directory: " + directory);
	System.out.println("file: " + file);
	screen.findElementByName("baseLayer").hide();
}

}
[/java]

The Controller:
[java]
import java.io.File;
import java.io.FileFilter;
import java.util.Properties;

import org.bushe.swing.event.EventTopicSubscriber;

import de.lessvoid.nifty.Nifty;
import de.lessvoid.nifty.controls.Button;
import de.lessvoid.nifty.controls.ButtonClickedEvent;
import de.lessvoid.nifty.controls.Controller;
import de.lessvoid.nifty.controls.DropDown;
import de.lessvoid.nifty.controls.DropDownSelectionChangedEvent;
import de.lessvoid.nifty.controls.ListBox;
import de.lessvoid.nifty.controls.ListBoxSelectionChangedEvent;
import de.lessvoid.nifty.controls.TextField;
import de.lessvoid.nifty.controls.WindowClosedEvent;
import de.lessvoid.nifty.elements.Element;
import de.lessvoid.nifty.input.NiftyInputEvent;
import de.lessvoid.nifty.screen.Screen;
import de.lessvoid.xml.xpp3.Attributes;

public class FileSelectionController implements Controller {
Nifty nifty;
Screen niftyScreen;
String id;
File currentDirectory;
File[] directories;
File[] roots;
String filterText;
String filterEnding;
FileSelectorObserver fileSelectorObserver;
ListBoxSelectionChangedEvent lastListEvent = null;
EventTopicSubscriber<ListBoxSelectionChangedEvent> eventHandlerListBox;
EventTopicSubscriber<ButtonClickedEvent> eventHandlerButton;
EventTopicSubscriber<DropDownSelectionChangedEvent> eventHandlerRoot;
EventTopicSubscriber<WindowClosedEvent> eventHandlerClosed;
EventTopicSubscriber<NiftyInputEvent> eventHandlerDirectory;
boolean isClosing = false;

@Override
public void bind(Nifty nifty, Screen niftyScreen, Element arg2, Properties arg3,
		Attributes arg4) {
	this.nifty = nifty;
	this.niftyScreen = niftyScreen;
}

@Override
public void init(Properties arg0, Attributes arg1) {
	id = arg0.getProperty("id");
	filterText = arg0.getProperty("filterText");
	filterEnding = arg0.getProperty("filterEnding");

	roots = File.listRoots();
	DropDown&lt;String&gt; dropDown = nifty.getCurrentScreen().findNiftyControl(id+"#rootDropBox", DropDown.class);
	if (dropDown != null) {
		dropDown.removeAllItems(dropDown.getItems());
		if (dropDown.getItems().size()==0) {
			for (int i=0; i &lt; roots.length; i++){
				dropDown.addItem(roots[i].getAbsolutePath());
			}
		}
		dropDown.getElement().layoutElements();
	}
	dropDown = nifty.getCurrentScreen().findNiftyControl(id+"#fileTypeDropBox", DropDown.class);
	if (dropDown != null) {
		dropDown.removeAllItems(dropDown.getItems());
		dropDown.addItem(filterText);
		dropDown.addItem("all files (*.*)");
		dropDown.getElement().layoutElements();
	}

	if (eventHandlerListBox == null) {
		eventHandlerListBox = new EventTopicSubscriber&lt;ListBoxSelectionChangedEvent&gt;() {
			@Override
			public void onEvent(String arg0,
					ListBoxSelectionChangedEvent arg1) {
				if (arg1.getSelectionIndices().size() &gt; 0)
					if (!arg1.equals(lastListEvent)) {
						lastListEvent = arg1;
						int index = (Integer)arg1.getSelectionIndices().get(0);
						if (currentDirectory.getParentFile() != null) {
							if (index == 0)
								newDirectory(currentDirectory.getParentFile());
							else {
								if (directories[index-1].isDirectory())
									newDirectory(directories[index-1]);
								else
									newFile(directories[index-1]);
							}
						}
						else {
							if (directories[index].isDirectory())
								newDirectory(directories[index]);
							else
								newFile(directories[index]);
						}
					}
			}

		};
		nifty.subscribe(niftyScreen, id + "#listFiles", ListBoxSelectionChangedEvent.class, eventHandlerListBox);
	}
	if (eventHandlerRoot == null) {
		eventHandlerRoot = new EventTopicSubscriber&lt;DropDownSelectionChangedEvent&gt;() {

			public void onEvent(String arg0, DropDownSelectionChangedEvent arg1) {
				if (arg0.equalsIgnoreCase(id + "#fileTypeDropBox"))
					newDirectory(currentDirectory);	
				else
					newDirectory(roots[arg1.getSelectionItemIndex()]);					
			}
		};
		nifty.subscribe(niftyScreen, id + "#fileTypeDropBox", DropDownSelectionChangedEvent.class, eventHandlerRoot);
		nifty.subscribe(niftyScreen, id + "#rootDropBox", DropDownSelectionChangedEvent.class, eventHandlerRoot);
	}

	if (eventHandlerButton == null) {
		eventHandlerButton = new EventTopicSubscriber&lt;ButtonClickedEvent&gt;() {

			@Override
			public void onEvent(String arg0, ButtonClickedEvent arg1) {
				if (arg0.endsWith("Open"))
					open();
				if (arg0.endsWith("Cancel"))
					cancel();
			}
		};
		nifty.subscribe(niftyScreen, id + "#buttonCancel", ButtonClickedEvent.class, eventHandlerButton);
		nifty.subscribe(niftyScreen, id + "#buttonOpen", ButtonClickedEvent.class, eventHandlerButton);
	}

	if (eventHandlerClosed == null) {
		eventHandlerClosed = new EventTopicSubscriber&lt;WindowClosedEvent&gt;() {
			@Override
			public void onEvent(String arg0, WindowClosedEvent arg1) {
				cancel();
			}
		};
		nifty.subscribe(niftyScreen, "windowFile", WindowClosedEvent.class, eventHandlerClosed);

	}
	if (eventHandlerDirectory == null) {
		eventHandlerDirectory = new EventTopicSubscriber&lt;NiftyInputEvent&gt;() {

			@Override
			public void onEvent(String arg0, NiftyInputEvent arg1) {
				if (arg0.equalsIgnoreCase(id + "#directory") &amp;&amp; arg1.toString().equalsIgnoreCase("SubmitText")) {
					TextField textField = nifty.getCurrentScreen().findNiftyControl(id+"#directory", TextField.class);
					File file = new File(textField.getRealText());
					newDirectory(file);
				}
				if (arg0.equalsIgnoreCase(id + "#filename") ) {
					Button b = nifty.getCurrentScreen().findNiftyControl(id+"#buttonOpen", Button.class);
					b.setEnabled(true);
				}

			}
		};
		nifty.subscribe(niftyScreen, id + "#directory", NiftyInputEvent.class, eventHandlerDirectory);
		nifty.subscribe(niftyScreen, id + "#filename", NiftyInputEvent.class, eventHandlerDirectory);
	}
}

@Override
public boolean inputEvent(NiftyInputEvent arg0) {
	// TODO Auto-generated method stub
	return true;
}

@Override
public void onFocus(boolean arg0) {
	// TODO Auto-generated method stub
}

@Override
public void onStartScreen() {
	// TODO Auto-generated method stub
}

public void newDirectory(File newDirectory) {
	currentDirectory = newDirectory;
	TextField textField = nifty.getCurrentScreen().findNiftyControl(id+"#directory", TextField.class);
	textField.setText(currentDirectory.getAbsolutePath());
	textField = nifty.getCurrentScreen().findNiftyControl(id+"#filename", TextField.class);
	textField.setText("");
	Button b = nifty.getCurrentScreen().findNiftyControl(id+"#buttonOpen", Button.class);
	b.setEnabled(false);
	ListBox&lt;String&gt; listBox = nifty.getCurrentScreen().findNiftyControl(id+"#listFiles", ListBox.class);
	listBox.removeAllItems(listBox.getItems());
	if (currentDirectory.getParentFile() != null) 
		listBox.addItem("..");
	DropDown dropDown = nifty.getCurrentScreen().findNiftyControl(id+"#fileTypeDropBox", DropDown.class);
	if (dropDown.getSelectedIndex() == 0)

		directories = currentDirectory.listFiles(new FileFilter() {
			@Override
			public boolean accept(File pathname) {
				return pathname.getName().toLowerCase().endsWith(filterEnding) | pathname.isDirectory();
			}
		});
	else
		directories = currentDirectory.listFiles();

	for (int i=0; i &lt; directories.length; i++)
		listBox.addItem(directories[i].getName());
	listBox.selectItemByIndex(-1);
}

protected void newFile(File file) {
	TextField textField = nifty.getCurrentScreen().findNiftyControl(id+"#filename", TextField.class);
	textField.setText(file.getName());
	Button b = nifty.getCurrentScreen().findNiftyControl(id+"#buttonOpen", Button.class);
	b.setEnabled(true);
}

protected void open() {
	if (!isClosing) {
		isClosing = true;
		TextField textField = nifty.getCurrentScreen().findNiftyControl(id+"#filename", TextField.class);
		String filename = textField.getRealText().trim();
		if (filename.length() &gt; 0) {
			File currentFile = new File(currentDirectory, filename);
			if (fileSelectorObserver != null) {
				fileSelectorObserver.selected(true, currentDirectory, currentFile);
			}
		}
		else {
			if (fileSelectorObserver != null) {
				fileSelectorObserver.selected(false, null, null);
			}
		}
		close();
	}
}

protected void cancel() {
	if (!isClosing) {
		isClosing = true;
		if (fileSelectorObserver != null) {
			fileSelectorObserver.selected(false, null, null);
		}
		close();
	}
}

public void setFileSelectorObserver(FileSelectorObserver fileSelectorObserver) {
	this.fileSelectorObserver = fileSelectorObserver;
}

private void close() {
}

public void setDirectory(File file) {
	if (file != null)
		newDirectory(file);
}

}
[/Java]

An interface
[java]
import java.io.File;

public interface FileSelectorObserver {
public void selected(boolean ok, File directory, File file);
}
[/java]

3 Likes

… it looks like this …

Hey! cool :smiley: . Why don’t you send a pull request to nifty-gui on github with this new control ? It would be cool if it were in the standard control library!

1 Like