/*
 * Java-Gnome Bindings Library
 *
 * Copyright 2005 the Java-Gnome Team, all rights reserved.
 *
 * The Java-Gnome bindings library is free software distributed under
 * the terms of the GNU Library General Public License version 2.
 */
 
package draganddrop;

import org.gnu.gdk.Atom;
import org.gnu.gdk.DragAction;
import org.gnu.gdk.DragContext;
import org.gnu.gdk.ModifierType;
import org.gnu.gtk.*;
import org.gnu.gtk.event.*;

/**
 * @author Ismael Juma <ismael@juma.me.uk>
 */
public class DnDExample2 {

	private TextBuffer textBuffer;
	private TextView textView;
	private RadioButton stringRadio;
	private RadioButton intRadio;
	private static final int TARGET_INT = 0;
	private static final int TARGET_STRING = 1;
	private TargetEntry[] targetList;
	public DnDExample2(String[] args) {
		Gtk.init(args);
		targetList = new TargetEntry[]	{
				new TargetEntry("INTEGER", TargetFlags.NO_RESTRICTION, TARGET_INT),
				new TargetEntry("STRING", TargetFlags.NO_RESTRICTION, TARGET_STRING),
		};
		int winXSize = 450;
		int winYSize = 150;
		Window window = new Window(WindowType.TOPLEVEL);
		VBox vbox = new VBox(false, 5);
		HBox hbox = new HBox(false, 5);
		VBox radioBox = new VBox(false, 2);
		stringRadio = new RadioButton((RadioButton)null, "Send String", false);
		intRadio = new RadioButton(stringRadio, "Send int", false);
		textBuffer = new TextBuffer();
		textView = new TextView(textBuffer);
		radioBox.add(stringRadio);
		radioBox.add(intRadio);
		radioBox.add(textView);
		Button source = new Button("-[source]-", false);
		Label destination = new Label("-[destination]-");
		Label directionsLabel = new Label("drag from the source to the destination");
		vbox.add(hbox);
		vbox.add(radioBox);
		window.add(vbox);
		hbox.add(source);
		hbox.add(directionsLabel);
		hbox.add(destination);
		window.setDefaultSize(winXSize, winYSize);
		source.setDragSource(ModifierType.BUTTON1_MASK, targetList, DragAction.COPY);
		destination.setDragDestination(DestDefaults.MOTION.or(DestDefaults.HIGHLIGHT), targetList, DragAction.COPY);
		
		window.addListener(new LifeCycleListener() {
			public boolean lifeCycleQuery(org.gnu.gtk.event.LifeCycleEvent event) {
				if (event.getType() == LifeCycleEvent.Type.DELETE || event.getType() == LifeCycleEvent.Type.DESTROY) {
					Gtk.mainQuit();
				}
				return false;
			}

			public void lifeCycleEvent(LifeCycleEvent event) {
			}
		});
		
		//Note if we did not intend to override all the methods of the
		//interface, then we would use DragDestinationAdapter. Using that
		//adapter we only need to implement the methods we need to
		//override.
		destination.addListener(new DragTargetListener()	{
			public void dataReceived(ReceiveDragDataEvent event) {
				handleDataReceived(event);
			}
			public void destinationLeft(LeaveDragDestinationEvent event) {
				handleDestinationLeft(event);
			}

			public boolean dropped(DropDragEvent event) {
				return handleDropped(event);
			}

			public boolean motionOcurred(DragMotionEvent event) {
				return handleMotionOcurred(event);
			}
		});
		
		source.addListener(new DragOriginListener() {

			public void dragStarted(StartDragEvent event) {
				handleDragStarted(event);
			}

			public void dragEnded(EndDragEvent event) {
				handleDragEnded(event);				
			}

			public void dataRequested(RequestDragDataEvent event) {
				handleDataRequested(event);				
			}

			public void dataDeleted(DeleteDragDataEvent event) {
				handleDataDeleted(event);
			}

		});
		
		window.showAll();
		Gtk.main();
	}
	private void handleDragStarted(StartDragEvent event) {
		Widget w = (Widget) event.getSource();
		System.out.println(w.getName() + ": handleDragStarted");
	}
	
	private void handleDataDeleted(DeleteDragDataEvent event) {
		Widget w = (Widget) event.getSource();
		System.out.println(w.getName() + ": handleDragDeleted");
	}
	
	private void handleDestinationLeft(LeaveDragDestinationEvent event) {
		Widget w = (Widget) event.getSource();
		System.out.println(w.getName() + ": handleDestinationLeft");
	}
	
	private void handleDataReceived(ReceiveDragDataEvent event) {
		int iData = 0;
		String sData = null;
		boolean dndSuccess = false;
		boolean deleteSelectionData = false;
		String name = ((Widget) event.getSource()).getName();
		System.out.println(name + " handleDataReceived");
		SelectionData sd = event.getSelectionData();
		DragContext dc = event.getDragContext();
		if (dc.getAction() == DragAction.MOVE) {
			deleteSelectionData = true;
		}
		
		System.out.println("Receiving");
		switch (event.getTargetInfo()) {		
		case TARGET_INT:
			iData = sd.getInt();
			dndSuccess = true;
			textBuffer.setText("Received int: " + iData + ".");
			break;
		case TARGET_STRING:
			sData = sd.getText();
			dndSuccess = true;
			textBuffer.setText("Received String: '" + sData + "'.");
			break;
		}
		
		if (dndSuccess == false) {
			textBuffer.setText("DnD data transfer failed.");
		}
		
		dc.finish(dndSuccess, deleteSelectionData, event.getTime());
	}
	
	private void handleDataRequested(RequestDragDataEvent event) {
		Widget widget = (Widget) event.getSource();
		String name = widget.getName();
		System.out.println(name + ": handleDataRequested");
		String data = "This is data from the source";
		int integerData = 42;
		
		System.out.println("Sending");
		SelectionData sd = event.getSelectionData();
		
		switch (event.getTargetInfo()) {
		case TARGET_INT:
			sd.setInt(integerData);
			break;
		case TARGET_STRING:
			sd.setText(data);
			break;
			
		}

	}
	
	private boolean handleDropped(DropDragEvent event) {
		boolean isValidDropSite = true;
		Atom targetType;
		Widget widget = (Widget) event.getSource();
		String name = widget.getName();
		System.out.println(name + ": handleDropped");
		DragContext dc = event.getDragContext();
		int index = 0;
		if(stringRadio.getState() == true) {
			index = TARGET_STRING;
		}
		else {
			index = TARGET_INT;
		}
			
		if (dc.getTargets().length > index) {
			targetType = dc.getTargets()[index];
			widget.getDragData(dc, targetType, event.getTime());
		}
		
		else {
			isValidDropSite = false;
		}
		
		return isValidDropSite;
	}
	
	private boolean handleMotionOcurred(DragMotionEvent event) {
		//This line was commented out as it sends a lot of output to the command
		//line
		//System.out.println("handleMotionOcurred");
		return false;
	}
	
	private void handleDragEnded(EndDragEvent event) {
		Widget w = (Widget) event.getSource();
		System.out.println(w.getName() + ": handleDragEnded");		
	}
	
	public static void main(String[] args) {
		DnDExample2 example = new DnDExample2(args);
		
	}
}
