/*
 Load a panel given a random number of strings. Every string is put in a
 label. The labels can be shifted and shuffled by dragging and dropping.
*/
import java.awt.*;
import java.awt.datatransfer.*;			//StringSelection
import java.awt.dnd.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import javax.swing.border.*;


public class SectionSequencer extends JPanel{

	String[] sections; 
	
	SectionSequencer( String[] scts){
		if (null==scts || scts.length<1 ) { 
			System.err.println("array invalid");
			return;
		}
		sections = scts;
		int len = sections.length;
		setLayout( new GridLayout( len, 0, 10, 10 ) ); //rows,cols,hgap,vgap
		int txtLenMax=0;
		for(int i=0; i<len; i++){
			DragLabel aLabel = new DragLabel(scts[i]);
			add(aLabel); 
			txtLenMax = txtLenMax>(scts[i].length()*10) ? txtLenMax : (scts[i].length()*10);
		}
		setPreferredSize( new Dimension( txtLenMax,100 ));
		
	}

	static String oldString="start-string error";

	// THE DRAG SOURCE
		//DragSourceListener: 
   		// for originators of Drag and Drop operations to track the state of the user's gesture
		//DragGestureListener:
	    // responsible for starting the drag 
		// sourced from a DragGestureRecognizer 
		// invoked when an object of that (sub)class detects a drag initiating gesture
	    //DropTargetListener:
	    //  the label must also be able to have things dropped onto it
	private class DragLabel extends JLabel implements 
   		DragSourceListener,
	    DragGestureListener,
	    DropTargetListener{

		DragSource dragSource;
		DropTarget dropTarget;

		DragLabel( String s ){
			super(s);
			setBorder(new LineBorder( Color.black ));
			setForeground(Color.blue);
			setFont(new Font("verdana", Font.PLAIN, 15) );
			dragSource = new DragSource();
			//OLD: dragSource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY_OR_MOVE, this);
			dragSource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_MOVE, this);

			// captured by dragGestureRecognized
			class Muizer extends MouseAdapter{
				public void mousePressed(MouseEvent e){
					System.out.println("label pressed");
					setForeground(Color.darkGray);
				}
			}
			// ?? addMouseListener( new Muizer() );
			dropTarget = new DropTarget( this , this);
		}



		// to implement DragGestureListener:
		
		// fired when pressed target is moved for the 1e time
		public void dragGestureRecognized(DragGestureEvent e) {
		    StringSelection text = new StringSelection( getText() );
		    dragSource.startDrag(e,DragSource.DefaultCopyDrop, text, this);
			setForeground(Color.black);
			oldString = getText();
			//System.out.println("oldstring in constr set to :" + oldString);
			//System.out.println("DragLabel.dragGestureRecognized (dragevent)");
		}

		// to implement DragSourceListener:
		// fired when mouse has been released (whether or not on the target object)
		public void dragDropEnd (DragSourceDropEvent e){
			setForeground(Color.blue);
			setText(oldString);// or else in dragExit (dragevent)
			//System.out.println("DragLabel.dragDropEnd (dragevent)");
		}

		// fired just after label-enter & 1 label-dargover event
		public void dragEnter (DragSourceDragEvent e){
			//System.out.println("DragLabel.dragEnter (dragevent)");
		}

		public void dragExit (DragSourceEvent e){
			//System.out.println("DragLabel.dragExit (dragevent)");
		}

		public void dragOver (DragSourceDragEvent e){ 
			//System.out.println("DragLabel.dragOver (dragevent)");
		}

		public void dropActionChanged (DragSourceDragEvent e){
			//System.out.println("DragLabel.dropActionChanged (dragevent)");
		}

		// DROP TARGET METHODS
		public void dragEnter( DropTargetDragEvent e ){
			//old: e.acceptDrag (DnDConstants.ACTION_COPY_OR_MOVE);
			e.acceptDrag (DnDConstants.ACTION_MOVE);
			//System.out.println("DragLabel.dragEnter (dropevent)");
		}
		public void dragOver( DropTargetDragEvent e ){
			//System.out.println("DragLabel.dragOver (dropevent)");
		}
		public void dropActionChanged( DropTargetDragEvent e ){
			//System.out.println("DragLabel.dropActionChanged (dropevent)");
		}
		public void dragExit( DropTargetEvent e ) {
			//System.out.println("DragLabel.dragExit (dropevent)");
		}
		public void drop( DropTargetDropEvent e ) {
			//System.out.println("DragLabel.drop (dropevent)");
			try {
				Transferable tr = e.getTransferable(); // ie java.awt.datatransfer.Transferable
				if (tr.isDataFlavorSupported (DataFlavor.stringFlavor)) {
					//old: e.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
					e.acceptDrop(DnDConstants.ACTION_MOVE);
					String s = (String)tr.getTransferData (DataFlavor.stringFlavor);
					//System.out.println("RECEIVED:\t" + s + "\n");
					oldString = getText();
					setText(s);
					paintImmediately(getVisibleRect());
					e.getDropTargetContext().dropComplete(true);
				} else {
					System.err.println ("Rejected");
					e.rejectDrop();
				}
			} catch (IOException io) {
				io.printStackTrace();
				e.rejectDrop();
			} catch (UnsupportedFlavorException ufe){
				ufe.printStackTrace();
				e.rejectDrop();
			}
		}
	}

	public static void main(String args[]){

		JFrame frame = new JFrame("Test SectionSequencer");
		Container container = frame.getContentPane();
		container.setLayout(new FlowLayout() );
		
		String scts[] = { "header", "shop message", "product table", "footer" }; 
		SectionSequencer ss = new SectionSequencer(scts);
		container.setBackground(Color.white);
		container.add(ss);
		frame.setSize(300, 300);
		frame.setVisible(true);
	}	
}