package gconf;

import org.gnu.gconf.ConfClient;
import org.gnu.gconf.ConfClientListener;
import org.gnu.gconf.ConfClientPreloadType;
import org.gnu.gconf.ConfEntry;
import org.gnu.gconf.ConfException;
import org.gnu.gnome.Program;
import org.gnu.gtk.Button;
import org.gnu.gtk.Dialog;
import org.gnu.gtk.Entry;
import org.gnu.gtk.Frame;
import org.gnu.gtk.Gtk;
import org.gnu.gtk.GtkStockItem;
import org.gnu.gtk.HBox;
import org.gnu.gtk.Label;
import org.gnu.gtk.ResponseType;
import org.gnu.gtk.VBox;
import org.gnu.gtk.Window;
import org.gnu.gtk.WindowType;
import org.gnu.gtk.event.ButtonEvent;
import org.gnu.gtk.event.ButtonListener;
import org.gnu.gtk.event.EntryEvent;
import org.gnu.gtk.event.EntryListener;
import org.gnu.gtk.event.FocusEvent;
import org.gnu.gtk.event.FocusListener;
import org.gnu.gtk.event.LifeCycleEvent;
import org.gnu.gtk.event.LifeCycleListener;

public class BasicGConfApp {
	ConfClient client;
	Window win;
	

	public BasicGConfApp() {
		// get the default client.
		client = ConfClient.getInstance();
		
		// Tell ConfClient that we are interested in the given directory.
		// This means ConfClient will receive notifications of changes to 
		// this directory, and cache keys under this directory.
		try {
			client.addDirectory("/apps/basic-gconf-app", ConfClientPreloadType.NONE);
		} catch (ConfException e) {
			System.err.println("Error adding directory to ConfClient");
			Gtk.mainQuit();
		}
		
		createMainWindow();
		
		win.showAll();
	}
	
	private void createMainWindow() {
		win = new Window(WindowType.TOPLEVEL);
		win.setTitle("BasicGConfApp Main Window");
		win.addListener(new LifeCycleListener() {
			public void lifeCycleEvent(LifeCycleEvent event) {}
			public boolean lifeCycleQuery(LifeCycleEvent event) {
				if (event.isOfType(LifeCycleEvent.Type.DELETE) || event.isOfType(LifeCycleEvent.Type.DESTROY))
					Gtk.mainQuit();
				return false;
			}
		});
		
		VBox vbox = new VBox(false, 5);
		win.add(vbox);
		vbox.setBorderWidth(5);
		
		Frame frame = createConfigurableLabel(new ConfClientListener() {
			public void clientNotify(ConfEntry entry) {
				
			}
		}, "/apps/basic-gconf-app/foo");
		vbox.packStart(frame, true, true, 0);

		frame = createConfigurableLabel(new ConfClientListener() {
			public void clientNotify(ConfEntry entry) {
				
			}
		}, "/apps/basic-gconf-app/bar");
		vbox.packStart(frame, true, true, 0);

		frame = createConfigurableLabel(new ConfClientListener() {
			public void clientNotify(ConfEntry entry) {
				
			}
		}, "/apps/basic-gconf-app/baz");
		vbox.packStart(frame, true, true, 0);

		frame = createConfigurableLabel(new ConfClientListener() {
			public void clientNotify(ConfEntry entry) {
				
			}
		}, "/apps/basic-gconf-app/blah");
		vbox.packStart(frame, true, true, 0);
		
		Button prefs = new Button("_Prefs", true);
		vbox.packEnd(prefs, false, false, 0);
		prefs.addListener(new ButtonListener() {
			public void buttonEvent(ButtonEvent event) {
				if (event.isOfType(ButtonEvent.Type.CLICK))
					prefsClicked();
			}
		});
	}
	
	private Frame createConfigurableLabel(ConfClientListener list, String configKey) {
		Frame frame = new Frame("Value of " + configKey);
		Label label = new Label("");
		frame.add(label);
		try {
			String str = client.getString(configKey);
			if (str != null)
				label.setText(str);
			client.addListener(list, configKey);
		} catch (ConfException e) {
			
		}
		return frame;
	}
	
	private void prefsClicked() {
		Dialog dialog = new Dialog();
		dialog.setTitle("Preferences");
		Button cancel = new Button(GtkStockItem.CANCEL);
		dialog.addWidget(cancel, ResponseType.CANCEL.getValue());
		Button apply = new Button(GtkStockItem.APPLY);
		dialog.addWidget(apply, ResponseType.APPLY.getValue());
		//dialog.setDefaultResponse(ResponseType.APPLY.getValue());
		//dialog.setResizable(false);
		VBox vbox = new VBox(false, 5);
		vbox.setBorderWidth(5);
		dialog.getDialogLayout().packStart(vbox, true, true, 0);
		HBox hbox = createConfigEntry("/apps/basic-gconf-app/foo", true);
		vbox.packStart(hbox, false, false, 0);
		hbox = createConfigEntry("/apps/basic-gconf-app/bar", false);
		vbox.packStart(hbox, false, false, 0);
		hbox = createConfigEntry("apps/basic-gconf-app/baz", false);
		vbox.packStart(hbox, false, false, 0);
		hbox = createConfigEntry("apps/basic-gconf-app/blah", false);
		vbox.packStart(hbox, false, false, 0);
		dialog.showAll();
		int response = dialog.run();
		dialog.destroy();
	}
	
	private HBox createConfigEntry(String key, boolean focus) {
		HBox hbox = new HBox(false, 5);
		Label label = new Label(key);
		Entry entry = new Entry();
		entry.setData("key", key);
		hbox.packStart(label, false, false, 0);
		hbox.packStart(entry, false, false, 0);
		try {
			String str = client.getString(key);
			if (null != str) {
				entry.setText(str);
			}
		} catch (ConfException e) {
			
		}
		entry.addListener(new FocusListener() {
			public boolean focusEvent(FocusEvent event) {
				if (event.isOfType(FocusEvent.Type.FOCUS_OUT)) {
					Entry ent = (Entry)event.getSource();
					String k = (String)ent.getData("key");
					configEntryCommit(ent, k);
				}
				return true;
			}
		});
		entry.addListener(new EntryListener() {
			public void entryEvent(EntryEvent event) {
				if (event.isOfType(EntryEvent.Type.ACTIVATE)) {
					Entry ent = (Entry)event.getSource();
					String k = (String)ent.getData("key");
					configEntryCommit(ent, k);
				}
			}
		});
		return hbox;
	}
	
	private void configEntryCommit(Entry entry, String key) {
		String text = entry.getCharacters(0, -1);
		try {
			if (null != text)
				client.setString(key, text);
			else
				client.unset(key);
		} catch (ConfException e) {
			
		}
	}

	public static void main(String[] args) {
		Program prog = Program.initGnomeUI("BasicGConfApp", "1.0", args);

		BasicGConfApp app = new BasicGConfApp();

		Gtk.main();
	}
}
