package org.workcraft.plugins.stg.tools;

import java.awt.Rectangle;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;

import javax.swing.JOptionPane;
import javax.swing.JTextField;

import org.workcraft.dom.Node;
import org.workcraft.dom.visual.BoundingBoxHelper;
import org.workcraft.dom.visual.HitMan;
import org.workcraft.dom.visual.TransformHelper;
import org.workcraft.dom.visual.VisualModel;
import org.workcraft.exceptions.ArgumentException;
import org.workcraft.gui.events.GraphEditorMouseEvent;
import org.workcraft.gui.graph.tools.GraphEditor;
import org.workcraft.gui.graph.tools.SelectionTool;
import org.workcraft.plugins.petri.Place;
import org.workcraft.plugins.petri.VisualPlace;
import org.workcraft.plugins.stg.STG;
import org.workcraft.plugins.stg.VisualNamedTransition;

public class STGSelectionTool extends SelectionTool
{
	private boolean cancelInPlaceEdit = false;

	@Override
	public void mouseClicked(GraphEditorMouseEvent e)
	{
		boolean processed = false;
		if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() > 1) {
			VisualModel model = e.getEditor().getModel();
			Node node = HitMan.hitTestForSelection(e.getPosition(), model);
			if (node != null) {
				if (node instanceof VisualPlace) {
					Place place = ((VisualPlace) node).getReferencedPlace();
					toggleToken(place, e);
					processed = true;
				} else if (node instanceof VisualNamedTransition) {
					VisualNamedTransition transition = (VisualNamedTransition)node;
					editNameInPlace(e.getEditor(), transition, transition.getName());
					processed = true;
				}
			}
		}
		if (!processed) {
			super.mouseClicked(e);
		}
	}

	private void toggleToken(Place place, GraphEditorMouseEvent e) {
		if (place.getTokens() <= 1) {
			e.getEditor().getWorkspaceEntry().saveMemento();

			if (place.getTokens() == 1)
				place.setTokens(0);
			else
				place.setTokens(1);
		}
	}

	private void editNameInPlace (final GraphEditor editor, final VisualNamedTransition transition, String initialText) {
		final JTextField text = new JTextField(initialText);
		AffineTransform localToRootTransform = TransformHelper.getTransformToRoot(transition);
		Rectangle2D bbRoot = TransformHelper.transform(transition, localToRootTransform).getBoundingBox();
		Rectangle bbScreen = editor.getViewport().userToScreen(BoundingBoxHelper.expand(bbRoot, 1.0, 0.5));
		float fontSize = VisualNamedTransition.font.getSize2D() * (float)editor.getViewport().getTransform().getScaleY();
		text.setFont(VisualNamedTransition.font.deriveFont(fontSize));
		text.setBounds(bbScreen.x, bbScreen.y, bbScreen.width, bbScreen.height);
		text.setHorizontalAlignment(JTextField.CENTER);
		text.selectAll();
		editor.getOverlay().add(text);
		text.requestFocusInWindow();

		text.addKeyListener( new KeyListener() {
			@Override
			public void keyPressed(KeyEvent arg0) {
				if (arg0.getKeyCode() == KeyEvent.VK_ENTER) {
					editor.requestFocus();
				}
				else if (arg0.getKeyCode() == KeyEvent.VK_ESCAPE) {
					cancelInPlaceEdit = true;
					editor.requestFocus();
				}
			}

			@Override
			public void keyReleased(KeyEvent arg0) {
			}

			@Override
			public void keyTyped(KeyEvent arg0) {
			}
		});

		final STG model = (STG)editor.getModel().getMathModel();
		text.addFocusListener(new FocusListener() {
			@Override
			public void focusGained(FocusEvent arg0) {
				editor.getWorkspaceEntry().setCanModify(false);
				cancelInPlaceEdit = false;
			}

			@Override
			public void focusLost(FocusEvent arg0) {
				final String newName = text.getText();
				text.getParent().remove(text);
				if (!cancelInPlaceEdit) {
					try {
						model.setName(transition.getReferencedComponent(), newName, true);
						editor.getWorkspaceEntry().saveMemento();
					} catch (ArgumentException e) {
						JOptionPane.showMessageDialog(null, e.getMessage());
						editNameInPlace(editor, transition, newName);
					}
				}
				editor.getWorkspaceEntry().setCanModify(true);
				editor.repaint();
			}
		});
	}

}

@@ -923,16 +923,73 @@
 tg.STG;%0A
+import org.workcraft.plugins.stg.VisualImplicitPlaceArc;%0A
 import o
@@ -1088,17 +1088,17 @@
 tionTool
-%0A
+ 
 %7B%0A%09priva
@@ -1235,16 +1235,17 @@
 e;%0A%09%09if 
+(
 (e.getBu
@@ -1276,12 +1276,14 @@
 TON1
+)
  && 
+(
 e.ge
@@ -1300,19 +1300,59 @@
 t() %3E 1)
+)
  %7B%0A
+%09%09%09GraphEditor editor = e.getEditor();%0A
 %09%09%09Visua
@@ -1367,28 +1367,21 @@
 odel = e
-.getE
 ditor
-()
 .getMode
@@ -1601,16 +1601,21 @@
 place, e
+ditor
 );%0A%09%09%09%09%09
@@ -1628,24 +1628,279 @@
 sed = true;%0A
+%09%09%09%09%7D else if (node instanceof VisualImplicitPlaceArc) %7B%0A%09%09%09%09%09if (e.getKeyModifiers() == MouseEvent.CTRL_DOWN_MASK) %7B%0A%09%09%09%09%09%09Place place = ((VisualImplicitPlaceArc) node).getImplicitPlace();%0A%09%09%09%09%09%09toggleToken(place, editor);%0A%09%09%09%09%09%09processed = true;%0A%09%09%09%09%09%7D%0A
 %09%09%09%09%7D else i
@@ -2034,28 +2034,21 @@
 nPlace(e
-.getE
 ditor
-()
 , transi
@@ -2218,28 +2218,23 @@
 phEditor
-MouseEvent e
+ editor
 ) %7B%0A%09%09if
@@ -2265,28 +2265,21 @@
 ) %7B%0A%09%09%09e
-.getE
 ditor
-()
 .getWork

Allow Ctrl+double_click to toggle marking of implicit and explicit places.