/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.jme3.gde.scenecomposer;

import com.jme3.asset.AssetManager;
import com.jme3.effect.ParticleEmitter;
import com.jme3.gde.core.assets.AssetDataObject;
import com.jme3.gde.core.assets.ProjectAssetManager;
import com.jme3.gde.core.assets.SpatialAssetDataObject;
import com.jme3.gde.core.scene.PreviewRequest;
import com.jme3.gde.core.scene.SceneApplication;
import com.jme3.gde.core.scene.SceneListener;
import com.jme3.gde.core.scene.SceneRequest;
import com.jme3.gde.core.sceneexplorer.SceneExplorerTopComponent;
import com.jme3.gde.core.sceneexplorer.nodes.JmeNode;
import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial;
import com.jme3.gde.core.sceneexplorer.nodes.NodeUtility;
import com.jme3.gde.core.sceneviewer.SceneViewerTopComponent;
import com.jme3.gde.scenecomposer.tools.MoveTool;
import com.jme3.gde.scenecomposer.tools.RotateTool;
import com.jme3.gde.scenecomposer.tools.ScaleTool;
import com.jme3.gde.scenecomposer.tools.SelectTool;
import com.jme3.math.Vector3f;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import java.io.IOException;
import java.util.Collection;
import java.util.concurrent.Callable;
import java.util.logging.Logger;
import javax.swing.ButtonGroup;
import javax.swing.border.TitledBorder;
import org.netbeans.api.progress.ProgressHandle;
import org.netbeans.api.progress.ProgressHandleFactory;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
import org.openide.windows.TopComponent;
import org.openide.windows.WindowManager;
import org.openide.util.ImageUtilities;
import org.netbeans.api.settings.ConvertAsProperties;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.NotifyDescriptor.Confirmation;
import org.openide.NotifyDescriptor.Message;
import org.openide.awt.Toolbar;
import org.openide.awt.ToolbarPool;
import org.openide.awt.UndoRedo;
import org.openide.filesystems.FileObject;
import org.openide.util.HelpCtx;
import org.openide.util.Lookup;
import org.openide.util.Lookup.Result;
import org.openide.util.LookupEvent;
import org.openide.util.LookupListener;
import org.openide.util.Utilities;

/**
 * TODO: some threading stuff
 */
@ConvertAsProperties(dtd = "-//com.jme3.gde.scenecomposer//SceneComposer//EN",
autostore = false)
@SuppressWarnings("unchecked")
public final class SceneComposerTopComponent extends TopComponent implements SceneListener, LookupListener {

    private static SceneComposerTopComponent instance;
    /** path to the icon used by the component and its open action */
    static final String ICON_PATH = "com/jme3/gde/scenecomposer/jme-logo24.png";
    private static final String PREFERRED_ID = "SceneComposerTopComponent";
    private final Result<JmeSpatial> result;
    ComposerCameraController camController;
    SceneComposerToolController toolController;
    SceneEditorController editorController;
    private SceneRequest sentRequest;
    private SceneRequest currentRequest;
    private HelpCtx ctx = new HelpCtx("sdk.scene_composer");
    private ProjectAssetManager.ClassPathChangeListener listener;

    public SceneComposerTopComponent() {
        initComponents();
        setName(NbBundle.getMessage(SceneComposerTopComponent.class, "CTL_SceneComposerTopComponent"));
        setToolTipText(NbBundle.getMessage(SceneComposerTopComponent.class, "HINT_SceneComposerTopComponent"));
        setIcon(ImageUtilities.loadImage(ICON_PATH, true));
        result = Utilities.actionsGlobalContext().lookupResult(JmeSpatial.class);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        spatialModButtonGroup = new ButtonGroup();
        sceneInfoPanel = new javax.swing.JPanel();
        sceneInfoLabel1 = new javax.swing.JLabel();
        sceneInfoLabel2 = new javax.swing.JLabel();
        jToolBar1 = new javax.swing.JToolBar();
        selectButton = new javax.swing.JToggleButton();
        moveButton = new javax.swing.JToggleButton();
        rotateButton = new javax.swing.JToggleButton();
        scaleButton = new javax.swing.JToggleButton();
        jSeparator5 = new javax.swing.JToolBar.Separator();
        jToggleScene = new javax.swing.JToggleButton();
        jToggleGrid = new javax.swing.JToggleButton();
        jSeparator8 = new javax.swing.JToolBar.Separator();
        jToggleSelectGeom = new javax.swing.JToggleButton();
        jToggleSelectTerrain = new javax.swing.JToggleButton();
        jSeparator7 = new javax.swing.JToolBar.Separator();
        moveToCursorButton = new javax.swing.JButton();
        jSeparator3 = new javax.swing.JToolBar.Separator();
        jLabel1 = new javax.swing.JLabel();
        resetCursorButton = new javax.swing.JButton();
        cursorToSelectionButton = new javax.swing.JButton();
        jSeparator2 = new javax.swing.JToolBar.Separator();
        jLabel2 = new javax.swing.JLabel();
        camToCursorSelectionButton = new javax.swing.JButton();
        jSeparator4 = new javax.swing.JToolBar.Separator();
        jLabel3 = new javax.swing.JLabel();
        showSelectionToggleButton = new javax.swing.JToggleButton();
        showGridToggleButton = new javax.swing.JToggleButton();
        jSeparator1 = new javax.swing.JToolBar.Separator();
        jPanel3 = new javax.swing.JPanel();
        jPanel4 = new javax.swing.JPanel();
        jToolBar2 = new javax.swing.JToolBar();
        createPhysicsMeshButton = new javax.swing.JButton();
        jCheckBox1 = new javax.swing.JCheckBox();
        jTextField1 = new javax.swing.JTextField();
        jLabel4 = new javax.swing.JLabel();
        jToolBar3 = new javax.swing.JToolBar();
        jButton1 = new javax.swing.JButton();
        fixedCheckBox = new javax.swing.JCheckBox();
        radiusSpinner = new javax.swing.JSpinner();
        heightSpinner = new javax.swing.JSpinner();
        jSeparator6 = new javax.swing.JSeparator();
        jLabel5 = new javax.swing.JLabel();
        emitButton = new javax.swing.JButton();
        jLabel6 = new javax.swing.JLabel();
        jButton2 = new javax.swing.JButton();
        jButton3 = new javax.swing.JButton();

        setBackground(new java.awt.Color(204, 204, 204));

        sceneInfoPanel.setBackground(new java.awt.Color(204, 204, 204));
        sceneInfoPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.sceneInfoPanel.border.title"))); // NOI18N

        org.openide.awt.Mnemonics.setLocalizedText(sceneInfoLabel1, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.sceneInfoLabel1.text")); // NOI18N

        org.openide.awt.Mnemonics.setLocalizedText(sceneInfoLabel2, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.sceneInfoLabel2.text")); // NOI18N

        javax.swing.GroupLayout sceneInfoPanelLayout = new javax.swing.GroupLayout(sceneInfoPanel);
        sceneInfoPanel.setLayout(sceneInfoPanelLayout);
        sceneInfoPanelLayout.setHorizontalGroup(
            sceneInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(sceneInfoLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(sceneInfoLabel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        sceneInfoPanelLayout.setVerticalGroup(
            sceneInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(sceneInfoPanelLayout.createSequentialGroup()
                .addComponent(sceneInfoLabel1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(sceneInfoLabel2)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jToolBar1.setBackground(new java.awt.Color(204, 204, 204));
        jToolBar1.setFloatable(false);
        jToolBar1.setRollover(true);

        spatialModButtonGroup.add(selectButton);
        selectButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/scenecomposer/icon_select.png"))); // NOI18N
        selectButton.setSelected(true);
        org.openide.awt.Mnemonics.setLocalizedText(selectButton, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.selectButton.text")); // NOI18N
        selectButton.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.selectButton.toolTipText")); // NOI18N
        selectButton.setFocusable(false);
        selectButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        selectButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        selectButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                selectButtonActionPerformed(evt);
            }
        });
        jToolBar1.add(selectButton);

        spatialModButtonGroup.add(moveButton);
        moveButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/scenecomposer/icon_arrow_out.png"))); // NOI18N
        org.openide.awt.Mnemonics.setLocalizedText(moveButton, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.moveButton.text")); // NOI18N
        moveButton.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.moveButton.toolTipText")); // NOI18N
        moveButton.setFocusable(false);
        moveButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        moveButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        moveButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                moveButtonActionPerformed(evt);
            }
        });
        jToolBar1.add(moveButton);

        spatialModButtonGroup.add(rotateButton);
        rotateButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/scenecomposer/icon_arrow_rotate_clockwise.png"))); // NOI18N
        org.openide.awt.Mnemonics.setLocalizedText(rotateButton, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.rotateButton.text")); // NOI18N
        rotateButton.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.rotateButton.toolTipText")); // NOI18N
        rotateButton.setFocusable(false);
        rotateButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        rotateButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        rotateButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                rotateButtonActionPerformed(evt);
            }
        });
        jToolBar1.add(rotateButton);

        spatialModButtonGroup.add(scaleButton);
        scaleButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/scenecomposer/icon_arrow_inout.png"))); // NOI18N
        org.openide.awt.Mnemonics.setLocalizedText(scaleButton, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.scaleButton.text")); // NOI18N
        scaleButton.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.scaleButton.toolTipText")); // NOI18N
        scaleButton.setFocusable(false);
        scaleButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        scaleButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        scaleButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                scaleButtonActionPerformed(evt);
            }
        });
        jToolBar1.add(scaleButton);
        jToolBar1.add(jSeparator5);

        jToggleScene.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/scenecomposer/snapScene.png"))); // NOI18N
        org.openide.awt.Mnemonics.setLocalizedText(jToggleScene, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.jToggleScene.text")); // NOI18N
        jToggleScene.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.jToggleScene.toolTipText")); // NOI18N
        jToggleScene.setFocusable(false);
        jToggleScene.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        jToggleScene.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToggleScene.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jToggleSceneActionPerformed(evt);
            }
        });
        jToolBar1.add(jToggleScene);

        jToggleGrid.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/scenecomposer/snapGrid.png"))); // NOI18N
        org.openide.awt.Mnemonics.setLocalizedText(jToggleGrid, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.jToggleGrid.text")); // NOI18N
        jToggleGrid.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.jToggleGrid.toolTipText")); // NOI18N
        jToggleGrid.setFocusable(false);
        jToggleGrid.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        jToggleGrid.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToggleGrid.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jToggleGridActionPerformed(evt);
            }
        });
        jToolBar1.add(jToggleGrid);
        jToolBar1.add(jSeparator8);

        jToggleSelectGeom.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/scenecomposer/selectGeometry.png"))); // NOI18N
        org.openide.awt.Mnemonics.setLocalizedText(jToggleSelectGeom, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.jToggleSelectGeom.text")); // NOI18N
        jToggleSelectGeom.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.jToggleSelectGeom.toolTipText")); // NOI18N
        jToggleSelectGeom.setFocusable(false);
        jToggleSelectGeom.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        jToggleSelectGeom.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToggleSelectGeom.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jToggleSelectGeomActionPerformed(evt);
            }
        });
        jToolBar1.add(jToggleSelectGeom);

        jToggleSelectTerrain.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/scenecomposer/selectTerrain.png"))); // NOI18N
        org.openide.awt.Mnemonics.setLocalizedText(jToggleSelectTerrain, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.jToggleSelectTerrain.text")); // NOI18N
        jToggleSelectTerrain.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.jToggleSelectTerrain.toolTipText")); // NOI18N
        jToggleSelectTerrain.setFocusable(false);
        jToggleSelectTerrain.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        jToggleSelectTerrain.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToggleSelectTerrain.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jToggleSelectTerrainActionPerformed(evt);
            }
        });
        jToolBar1.add(jToggleSelectTerrain);
        jToolBar1.add(jSeparator7);

        moveToCursorButton.setBackground(new java.awt.Color(204, 204, 204));
        moveToCursorButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/scenecomposer/move.gif"))); // NOI18N
        org.openide.awt.Mnemonics.setLocalizedText(moveToCursorButton, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.moveToCursorButton.text")); // NOI18N
        moveToCursorButton.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.moveToCursorButton.toolTipText")); // NOI18N
        moveToCursorButton.setFocusable(false);
        moveToCursorButton.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);
        moveToCursorButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        moveToCursorButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                moveToCursorButtonActionPerformed(evt);
            }
        });
        jToolBar1.add(moveToCursorButton);
        jToolBar1.add(jSeparator3);

        jLabel1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/scenecomposer/cursor.gif"))); // NOI18N
        org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.jLabel1.text")); // NOI18N
        jToolBar1.add(jLabel1);

        resetCursorButton.setBackground(new java.awt.Color(204, 204, 204));
        org.openide.awt.Mnemonics.setLocalizedText(resetCursorButton, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.resetCursorButton.text")); // NOI18N
        resetCursorButton.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.resetCursorButton.toolTipText")); // NOI18N
        resetCursorButton.setFocusable(false);
        resetCursorButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        resetCursorButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        resetCursorButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                resetCursorButtonActionPerformed(evt);
            }
        });
        jToolBar1.add(resetCursorButton);

        cursorToSelectionButton.setBackground(new java.awt.Color(204, 204, 204));
        org.openide.awt.Mnemonics.setLocalizedText(cursorToSelectionButton, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.cursorToSelectionButton.text")); // NOI18N
        cursorToSelectionButton.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.cursorToSelectionButton.toolTipText")); // NOI18N
        cursorToSelectionButton.setFocusable(false);
        cursorToSelectionButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        cursorToSelectionButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        cursorToSelectionButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cursorToSelectionButtonActionPerformed(evt);
            }
        });
        jToolBar1.add(cursorToSelectionButton);
        jToolBar1.add(jSeparator2);

        jLabel2.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/scenecomposer/camera.gif"))); // NOI18N
        org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.jLabel2.text")); // NOI18N
        jToolBar1.add(jLabel2);

        camToCursorSelectionButton.setBackground(new java.awt.Color(204, 204, 204));
        org.openide.awt.Mnemonics.setLocalizedText(camToCursorSelectionButton, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.camToCursorSelectionButton.text")); // NOI18N
        camToCursorSelectionButton.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.camToCursorSelectionButton.toolTipText")); // NOI18N
        camToCursorSelectionButton.setFocusable(false);
        camToCursorSelectionButton.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);
        camToCursorSelectionButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        camToCursorSelectionButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                camToCursorSelectionButtonActionPerformed(evt);
            }
        });
        jToolBar1.add(camToCursorSelectionButton);
        jToolBar1.add(jSeparator4);

        jLabel3.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/scenecomposer/box_wire.gif"))); // NOI18N
        org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.jLabel3.text")); // NOI18N
        jToolBar1.add(jLabel3);

        showSelectionToggleButton.setSelected(true);
        org.openide.awt.Mnemonics.setLocalizedText(showSelectionToggleButton, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.showSelectionToggleButton.text")); // NOI18N
        showSelectionToggleButton.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.showSelectionToggleButton.toolTipText")); // NOI18N
        showSelectionToggleButton.setFocusable(false);
        showSelectionToggleButton.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);
        showSelectionToggleButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        showSelectionToggleButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                showSelectionToggleButtonActionPerformed(evt);
            }
        });
        jToolBar1.add(showSelectionToggleButton);

        org.openide.awt.Mnemonics.setLocalizedText(showGridToggleButton, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.showGridToggleButton.text")); // NOI18N
        showGridToggleButton.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.showGridToggleButton.toolTipText")); // NOI18N
        showGridToggleButton.setFocusable(false);
        showGridToggleButton.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);
        showGridToggleButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        showGridToggleButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                showGridToggleButtonActionPerformed(evt);
            }
        });
        jToolBar1.add(showGridToggleButton);
        jToolBar1.add(jSeparator1);

        jPanel3.setBackground(new java.awt.Color(204, 204, 204));

        javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
        jPanel3.setLayout(jPanel3Layout);
        jPanel3Layout.setHorizontalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 133, Short.MAX_VALUE)
        );
        jPanel3Layout.setVerticalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 21, Short.MAX_VALUE)
        );

        jToolBar1.add(jPanel3);

        jPanel4.setBackground(new java.awt.Color(204, 204, 204));
        jPanel4.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.jPanel4.border.title"))); // NOI18N

        jToolBar2.setBackground(new java.awt.Color(204, 204, 204));
        jToolBar2.setFloatable(false);
        jToolBar2.setRollover(true);

        createPhysicsMeshButton.setBackground(new java.awt.Color(204, 204, 204));
        org.openide.awt.Mnemonics.setLocalizedText(createPhysicsMeshButton, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.createPhysicsMeshButton.text")); // NOI18N
        createPhysicsMeshButton.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.createPhysicsMeshButton.toolTipText")); // NOI18N
        createPhysicsMeshButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                createPhysicsMeshButtonActionPerformed(evt);
            }
        });
        jToolBar2.add(createPhysicsMeshButton);

        jCheckBox1.setBackground(new java.awt.Color(204, 204, 204));
        org.openide.awt.Mnemonics.setLocalizedText(jCheckBox1, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.jCheckBox1.text")); // NOI18N
        jToolBar2.add(jCheckBox1);

        jTextField1.setText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.jTextField1.text")); // NOI18N
        jToolBar2.add(jTextField1);

        org.openide.awt.Mnemonics.setLocalizedText(jLabel4, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.jLabel4.text")); // NOI18N
        jToolBar2.add(jLabel4);

        jToolBar3.setBackground(new java.awt.Color(204, 204, 204));
        jToolBar3.setFloatable(false);
        jToolBar3.setRollover(true);

        jButton1.setBackground(new java.awt.Color(204, 204, 204));
        org.openide.awt.Mnemonics.setLocalizedText(jButton1, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.jButton1.text")); // NOI18N
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });
        jToolBar3.add(jButton1);

        fixedCheckBox.setBackground(new java.awt.Color(204, 204, 204));
        fixedCheckBox.setSelected(true);
        org.openide.awt.Mnemonics.setLocalizedText(fixedCheckBox, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.fixedCheckBox.text")); // NOI18N
        fixedCheckBox.setEnabled(false);
        jToolBar3.add(fixedCheckBox);

        radiusSpinner.setModel(new javax.swing.SpinnerNumberModel(Float.valueOf(0.5f), null, null, Float.valueOf(0.1f)));
        jToolBar3.add(radiusSpinner);

        heightSpinner.setModel(new javax.swing.SpinnerNumberModel(Float.valueOf(1.8f), null, null, Float.valueOf(0.1f)));
        jToolBar3.add(heightSpinner);

        org.openide.awt.Mnemonics.setLocalizedText(jLabel5, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.jLabel5.text")); // NOI18N

        org.openide.awt.Mnemonics.setLocalizedText(emitButton, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.emitButton.text")); // NOI18N
        emitButton.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.emitButton.toolTipText")); // NOI18N
        emitButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                emitButtonActionPerformed(evt);
            }
        });

        org.openide.awt.Mnemonics.setLocalizedText(jLabel6, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.jLabel6.text")); // NOI18N

        jButton2.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/scenecomposer/play.gif"))); // NOI18N
        org.openide.awt.Mnemonics.setLocalizedText(jButton2, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.jButton2.text")); // NOI18N
        jButton2.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.jButton2.toolTipText")); // NOI18N
        jButton2.setFocusable(false);
        jButton2.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        jButton2.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton2ActionPerformed(evt);
            }
        });

        jButton3.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/scenecomposer/pause.gif"))); // NOI18N
        org.openide.awt.Mnemonics.setLocalizedText(jButton3, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.jButton3.text")); // NOI18N
        jButton3.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.jButton3.toolTipText")); // NOI18N
        jButton3.setFocusable(false);
        jButton3.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        jButton3.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jButton3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton3ActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4);
        jPanel4.setLayout(jPanel4Layout);
        jPanel4Layout.setHorizontalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jToolBar2, javax.swing.GroupLayout.DEFAULT_SIZE, 389, Short.MAX_VALUE)
            .addComponent(jToolBar3, javax.swing.GroupLayout.DEFAULT_SIZE, 389, Short.MAX_VALUE)
            .addGroup(jPanel4Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jSeparator6, javax.swing.GroupLayout.DEFAULT_SIZE, 377, Short.MAX_VALUE)
                    .addGroup(jPanel4Layout.createSequentialGroup()
                        .addGap(10, 10, 10)
                        .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(jPanel4Layout.createSequentialGroup()
                                .addComponent(jLabel6)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(jButton2)
                                .addComponent(jButton3))
                            .addGroup(jPanel4Layout.createSequentialGroup()
                                .addComponent(jLabel5)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(emitButton)))
                        .addGap(0, 0, Short.MAX_VALUE)))
                .addContainerGap())
        );
        jPanel4Layout.setVerticalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel4Layout.createSequentialGroup()
                .addComponent(jToolBar2, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jToolBar3, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jSeparator6, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel5)
                    .addComponent(emitButton))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel4Layout.createSequentialGroup()
                        .addGap(4, 4, 4)
                        .addComponent(jLabel6))
                    .addComponent(jButton2)
                    .addComponent(jButton3))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(sceneInfoPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
            .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(sceneInfoPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
        );
    }// </editor-fold>//GEN-END:initComponents

    private void showSelectionToggleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showSelectionToggleButtonActionPerformed
        if (toolController != null) {
            toolController.setShowSelection(showSelectionToggleButton.isSelected());
        }
    }//GEN-LAST:event_showSelectionToggleButtonActionPerformed

    private void showGridToggleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showGridToggleButtonActionPerformed
        if (toolController != null) {
            toolController.setShowGrid(showGridToggleButton.isSelected());
        }
    }//GEN-LAST:event_showGridToggleButtonActionPerformed

    private void moveToCursorButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_moveToCursorButtonActionPerformed
        if (editorController != null) {
            editorController.moveSelectedSpatial(toolController.getCursorLocation());
            toolController.selectedSpatialTransformed();
        }
    }//GEN-LAST:event_moveToCursorButtonActionPerformed

    private void resetCursorButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_resetCursorButtonActionPerformed
        if (toolController != null) {
            toolController.setCursorLocation(Vector3f.ZERO);
        }
    }//GEN-LAST:event_resetCursorButtonActionPerformed

    private void camToCursorSelectionButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_camToCursorSelectionButtonActionPerformed
        camController.setCamFocus(toolController.getCursorLocation());
    }//GEN-LAST:event_camToCursorSelectionButtonActionPerformed

    private void cursorToSelectionButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cursorToSelectionButtonActionPerformed
        if (toolController != null) {
            toolController.snapCursorToSelection();
        }
    }//GEN-LAST:event_cursorToSelectionButtonActionPerformed

    private void createPhysicsMeshButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_createPhysicsMeshButtonActionPerformed
        if (editorController != null) {
            if (jCheckBox1.isSelected()) {
                try {
                    editorController.createDynamicPhysicsMeshForSelectedSpatial(Float.parseFloat(jTextField1.getText()));
                } catch (Exception e) {
                }
            } else {
                editorController.createPhysicsMeshForSelectedSpatial();
            }
        }
    }//GEN-LAST:event_createPhysicsMeshButtonActionPerformed

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
        // TODO add your handling code here:
        if (editorController != null) {
            boolean auto = !fixedCheckBox.isSelected();
            float radius = (Float) radiusSpinner.getValue();
            float height = (Float) heightSpinner.getValue();
            editorController.createCharacterControlForSelectedSpatial(false, radius, height);
        }

    }//GEN-LAST:event_jButton1ActionPerformed

    private void selectButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectButtonActionPerformed
        SelectTool tool = new SelectTool();
        toolController.showEditTool(tool);
    }//GEN-LAST:event_selectButtonActionPerformed

    private void moveButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_moveButtonActionPerformed
        MoveTool tool = new MoveTool();
        toolController.showEditTool(tool);
    }//GEN-LAST:event_moveButtonActionPerformed

private void emitButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_emitButtonActionPerformed
    SceneApplication.getApplication().enqueue(new Callable<Object>() {

        public Object call() throws Exception {
            emit(editorController.getSelectedSpat().getLookup().lookup(Spatial.class));
            return null;
        }
    });

}//GEN-LAST:event_emitButtonActionPerformed

private void scaleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_scaleButtonActionPerformed
    ScaleTool tool = new ScaleTool();
    toolController.showEditTool(tool);
}//GEN-LAST:event_scaleButtonActionPerformed

    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed
        SceneApplication.getApplication().setPhysicsEnabled(true);
    }//GEN-LAST:event_jButton2ActionPerformed

    private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton3ActionPerformed
        SceneApplication.getApplication().setPhysicsEnabled(false);
    }//GEN-LAST:event_jButton3ActionPerformed

    private void rotateButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rotateButtonActionPerformed
        RotateTool tool = new RotateTool();
        toolController.showEditTool(tool);
    }//GEN-LAST:event_rotateButtonActionPerformed

private void jToggleSceneActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jToggleSceneActionPerformed
    toolController.setSnapToScene(jToggleScene.isSelected());
}//GEN-LAST:event_jToggleSceneActionPerformed

private void jToggleGridActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jToggleGridActionPerformed
    toolController.setSnapToGrid(jToggleGrid.isSelected());
}//GEN-LAST:event_jToggleGridActionPerformed

private void jToggleSelectTerrainActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jToggleSelectTerrainActionPerformed
    toolController.setSelectTerrain(jToggleSelectTerrain.isSelected());
}//GEN-LAST:event_jToggleSelectTerrainActionPerformed

private void jToggleSelectGeomActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jToggleSelectGeomActionPerformed
    toolController.setSelectGeometries(jToggleSelectGeom.isSelected());
}//GEN-LAST:event_jToggleSelectGeomActionPerformed
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton camToCursorSelectionButton;
    private javax.swing.JButton createPhysicsMeshButton;
    private javax.swing.JButton cursorToSelectionButton;
    private javax.swing.JButton emitButton;
    private javax.swing.JCheckBox fixedCheckBox;
    private javax.swing.JSpinner heightSpinner;
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton2;
    private javax.swing.JButton jButton3;
    private javax.swing.JCheckBox jCheckBox1;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JToolBar.Separator jSeparator1;
    private javax.swing.JToolBar.Separator jSeparator2;
    private javax.swing.JToolBar.Separator jSeparator3;
    private javax.swing.JToolBar.Separator jSeparator4;
    private javax.swing.JToolBar.Separator jSeparator5;
    private javax.swing.JSeparator jSeparator6;
    private javax.swing.JToolBar.Separator jSeparator7;
    private javax.swing.JToolBar.Separator jSeparator8;
    private javax.swing.JTextField jTextField1;
    private javax.swing.JToggleButton jToggleGrid;
    private javax.swing.JToggleButton jToggleScene;
    private javax.swing.JToggleButton jToggleSelectGeom;
    private javax.swing.JToggleButton jToggleSelectTerrain;
    private javax.swing.JToolBar jToolBar1;
    private javax.swing.JToolBar jToolBar2;
    private javax.swing.JToolBar jToolBar3;
    private javax.swing.JToggleButton moveButton;
    private javax.swing.JButton moveToCursorButton;
    private javax.swing.JSpinner radiusSpinner;
    private javax.swing.JButton resetCursorButton;
    private javax.swing.JToggleButton rotateButton;
    private javax.swing.JToggleButton scaleButton;
    private javax.swing.JLabel sceneInfoLabel1;
    private javax.swing.JLabel sceneInfoLabel2;
    private javax.swing.JPanel sceneInfoPanel;
    private javax.swing.JToggleButton selectButton;
    private javax.swing.JToggleButton showGridToggleButton;
    private javax.swing.JToggleButton showSelectionToggleButton;
    private javax.swing.ButtonGroup spatialModButtonGroup;
    // End of variables declaration//GEN-END:variables

    private void emit(Spatial root) {
        if (root instanceof ParticleEmitter) {
            ((ParticleEmitter) root).killAllParticles();
            ((ParticleEmitter) root).emitAllParticles();
        } else if (root instanceof Node) {
            Node n = (Node) root;
            for (Spatial child : n.getChildren()) {
                emit(child);
            }
        }

    }

    /**
     * Gets default instance. Do not use directly: reserved for *.settings files only,
     * i.e. deserialization routines; otherwise you could get a non-deserialized instance.
     * To obtain the singleton instance, use {@link #findInstance}.
     */
    public static synchronized SceneComposerTopComponent getDefault() {
        if (instance == null) {
            instance = new SceneComposerTopComponent();
        }
        return instance;
    }

    /**
     * Obtain the SceneComposerTopComponent instance. Never call {@link #getDefault} directly!
     */
    public static synchronized SceneComposerTopComponent findInstance() {
        TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID);
        if (win == null) {
            Logger.getLogger(SceneComposerTopComponent.class.getName()).warning(
                    "Cannot find " + PREFERRED_ID + " component. It will not be located properly in the window system.");
            return getDefault();
        }
        if (win instanceof SceneComposerTopComponent) {
            return (SceneComposerTopComponent) win;
        }
        Logger.getLogger(SceneComposerTopComponent.class.getName()).warning(
                "There seem to be multiple components with the '" + PREFERRED_ID
                + "' ID. That is a potential source of errors and unexpected behavior.");
        return getDefault();
    }

    @Override
    public int getPersistenceType() {
        return TopComponent.PERSISTENCE_ALWAYS;
    }

    @Override
    public HelpCtx getHelpCtx() {
        //this call is for single components:
        //HelpCtx.setHelpIDString(this, "com.jme3.gde.core.sceneviewer");
        return ctx;
    }

    @Override
    public UndoRedo getUndoRedo() {
        return Lookup.getDefault().lookup(UndoRedo.class);
    }

    @Override
    public void componentOpened() {
        super.componentOpened();
        Toolbar tb = ToolbarPool.getDefault().findToolbar("SceneComposer-Tools");
        if (tb != null) {
            if (!tb.isVisible()) {
                tb.setVisible(true);
            }
        }
        if (currentRequest == null) {
            close();
        }
    }

    @Override
    public void componentClosed() {
        super.componentClosed();
        if (currentRequest != null) {
            SceneApplication.getApplication().closeScene(currentRequest);
        }
        Toolbar tb = ToolbarPool.getDefault().findToolbar("SceneComposer-Tools");
        if (tb != null) {
            if (tb.isVisible()) {
                tb.setVisible(false);
            }
        }
    }

    @Override
    protected void componentActivated() {
        SceneViewerTopComponent.findInstance().requestVisible();
    }

    void writeProperties(java.util.Properties p) {
        // better to version settings since initial version as advocated at
        // http://wiki.apidesign.org/wiki/PropertyFiles
        p.setProperty("version", "1.0");
        // TODO store your settings
    }

    Object readProperties(java.util.Properties p) {
        if (instance == null) {
            instance = this;
        }
        instance.readPropertiesImpl(p);
        return instance;
    }

    private void readPropertiesImpl(java.util.Properties p) {
        String version = p.getProperty("version");
        // TODO read your settings according to their version
    }

    @Override
    protected String preferredID() {
        return PREFERRED_ID;
    }

    private void setSelectedObjectText(final String text) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                if (text != null) {
                    ((TitledBorder) jPanel4.getBorder()).setTitle("Utilities - " + text);
                } else {
                    ((TitledBorder) jPanel4.getBorder()).setTitle("Utilities - no spatial selected");
                }
            }
        });
    }

    /**
     * method to set the state of the ui items
     */
    private void setSceneInfo(final JmeNode jmeNode, final FileObject file, final boolean active) {
        final SceneComposerTopComponent inst = this;
        if (jmeNode != null) {
            ((TitledBorder) sceneInfoPanel.getBorder()).setTitle(jmeNode.getName());
            selectSpatial(jmeNode);
        } else {
            ((TitledBorder) sceneInfoPanel.getBorder()).setTitle("");
        }
        //XXX: wtf? why do i have to repaint?
        sceneInfoPanel.repaint();

        if (!active) {
            result.removeLookupListener(inst);
            showSelectionToggleButton.setSelected(true);
            showGridToggleButton.setSelected(false);
            sceneInfoLabel1.setText("");
            sceneInfoLabel2.setText("");
            sceneInfoLabel1.setToolTipText("");
            sceneInfoLabel2.setToolTipText("");
            close();
        } else {
            showSelectionToggleButton.setSelected(true);
            showGridToggleButton.setSelected(false);
            //TODO: threading
            if (file != null) {
                sceneInfoLabel1.setText("Name: " + file.getNameExt());
                sceneInfoLabel2.setText("Size: " + file.getSize() / 1024 + " kB");
                sceneInfoLabel1.setToolTipText("Name: " + file.getNameExt());
                sceneInfoLabel2.setToolTipText("Size: " + file.getSize() / 1024 + " kB");
            }
            open();
            requestActive();
        }
    }

    public void openScene(Spatial spat, AssetDataObject file, ProjectAssetManager manager) {
        cleanupControllers();
        SceneApplication.getApplication().addSceneListener(this);
        result.addLookupListener(this);
        Node node;
        if (spat instanceof Node) {
            node = (Node) spat;
        } else {
            node = new Node();
            node.attachChild(spat);
        }
        JmeNode jmeNode = NodeUtility.createNode(node, file, false);
        SceneRequest request = new SceneRequest(this, jmeNode, manager);
        request.setDataObject(file);
        request.setHelpCtx(ctx);
        this.sentRequest = request;
        request.setWindowTitle("SceneComposer - " + manager.getRelativeAssetPath(file.getPrimaryFile().getPath()));
        request.setToolNode(new Node("SceneComposerToolNode"));
        SceneApplication.getApplication().openScene(request);
    }

    public void addModel(Spatial model) {
        if (editorController != null) {
            editorController.addModel(model, toolController.getCursorLocation());
        } else {
            displayInfo("No scene opened!");
        }
    }

    public void addModel(SpatialAssetDataObject model) {
        if (editorController != null) {
            editorController.addModel(model, toolController.getCursorLocation());
        } else {
            displayInfo("No scene opened!");
        }
    }

    public void linkModel(AssetManager manager, String assetName) {
        if (editorController != null) {
            editorController.linkModel(manager, assetName, toolController.getCursorLocation());
        } else {
            displayInfo("No scene opened!");
        }
    }

    public void doMoveCursor(Vector3f vector) {
        if (toolController != null) {
            toolController.doSetCursorLocation(vector);
        } else {
            displayInfo("No scene opened!");
        }
    }

    /**
     * listener for node selection changes
     */
    public void resultChanged(LookupEvent ev) {
        if (currentRequest == null || !currentRequest.isDisplayed()) {
            return;
        }
        Collection<JmeSpatial> items = (Collection<JmeSpatial>) result.allInstances();
        for (JmeSpatial spatial : items) {
            selectSpatial(spatial);
            return;
        }
    }

    private void selectSpatial(JmeSpatial spatial) {
        if (editorController != null) {
            editorController.setSelectedSpat(spatial);
        }
        if (spatial == null) {
            setSelectedObjectText(null);
            return;
        } else {
            if (toolController != null) {
                toolController.setSelectedSpatial(spatial);
                toolController.updateSelection(spatial.getLookup().lookup(Spatial.class));
            }
        }
        if (spatial.getLookup().lookup(Node.class) != null) {
            setSelectedObjectText(spatial.getLookup().lookup(Node.class).getName());
        } else if (spatial.getLookup().lookup(Spatial.class) != null) {
            setSelectedObjectText(spatial.getLookup().lookup(Spatial.class).getName());
        } else {
            setSelectedObjectText(null);
        }
        SceneViewerTopComponent.findInstance().setActivatedNodes(new org.openide.nodes.Node[]{spatial});
        SceneExplorerTopComponent.findInstance().setSelectedNode(spatial);
    }

    private void cleanupControllers() {
        if (camController != null) {
            camController.disable();
            camController = null;
        }
        if (toolController != null) {
            toolController.cleanup();
            toolController = null;
        }
        if (editorController != null) {
            editorController.cleanup();
            editorController = null;
        }
    }

    /*
     * SceneListener
     */
    public void sceneOpened(SceneRequest request) {
        if (request.equals(sentRequest)) {
            currentRequest = request;
            if (editorController != null) {
                editorController.cleanup();
            }
            editorController = new SceneEditorController(request.getJmeNode(), request.getDataObject());
            setActivatedNodes(new org.openide.nodes.Node[]{request.getDataObject().getNodeDelegate()});
            setSceneInfo(request.getJmeNode(), editorController.getCurrentFileObject(), true);
            if (camController != null) {
                camController.disable();
            }
            if (toolController != null) {
                toolController.cleanup();
            }
            toolController = new SceneComposerToolController(request.getToolNode(), request.getManager(), request.getJmeNode());

            camController = new ComposerCameraController(SceneApplication.getApplication().getCamera(), request.getJmeNode());
            toolController.setEditorController(editorController);
            camController.setToolController(toolController);
            camController.setMaster(this);
            camController.enable();

            toolController.setCameraController(camController);
            SelectTool tool = new SelectTool();
            toolController.showEditTool(tool);
            toolController.setShowSelection(true);

            editorController.setToolController(toolController);
            toolController.refreshNonSpatialMarkers();

            editorController.setTerrainLodCamera();
            final SpatialAssetDataObject dobj = ((SpatialAssetDataObject) currentRequest.getDataObject());
            listener = new ProjectAssetManager.ClassPathChangeListener() {

                public void classPathChanged(final ProjectAssetManager manager) {
                    if (dobj.isModified()) {
                        Confirmation msg = new NotifyDescriptor.Confirmation(
                                "Classes have been changed, save and reload scene?",
                                NotifyDescriptor.OK_CANCEL_OPTION,
                                NotifyDescriptor.INFORMATION_MESSAGE);
                        Object result = DialogDisplayer.getDefault().notify(msg);
                        if (!NotifyDescriptor.OK_OPTION.equals(result)) {
                            return;
                        }
                        try {
                            dobj.saveAsset();
                        } catch (IOException ex) {
                            Exceptions.printStackTrace(ex);
                        }
                    }
                    Runnable call = new Runnable() {

                        public void run() {
                            ProgressHandle progressHandle = ProgressHandleFactory.createHandle("Reloading Scene..");
                            progressHandle.start();
                            try {
                                manager.clearCache();
                                final Spatial asset = dobj.loadAsset();
                                if (asset != null) {
                                    java.awt.EventQueue.invokeLater(new Runnable() {

                                        public void run() {
                                            SceneComposerTopComponent composer = SceneComposerTopComponent.findInstance();
                                            composer.openScene(asset, dobj, manager);
                                        }
                                    });
                                } else {
                                    Confirmation msg = new NotifyDescriptor.Confirmation(
                                            "Error opening " + dobj.getPrimaryFile().getNameExt(),
                                            NotifyDescriptor.OK_CANCEL_OPTION,
                                            NotifyDescriptor.ERROR_MESSAGE);
                                    DialogDisplayer.getDefault().notify(msg);
                                }
                            } finally {
                                progressHandle.finish();
                            }
                        }
                    };
                    new Thread(call).start();
                }
            };
//            currentRequest.getManager().addClassPathEventListener(listener);
        }
    }

    public void sceneClosed(SceneRequest request) {
        if (request.equals(currentRequest)) {
            setActivatedNodes(new org.openide.nodes.Node[]{});
            if (listener != null && request.getManager() != null) {
//                request.getManager().removeClassPathEventListener(listener);
                listener = null;
            }
            SceneApplication.getApplication().removeSceneListener(this);
            currentRequest = null;
            setSceneInfo(null, null, false);
            cleanupControllers();
        }
    }

    public void previewCreated(PreviewRequest request) {
    }

    public void displayInfo(String info) {
        Message msg = new NotifyDescriptor.Message(info);
        DialogDisplayer.getDefault().notifyLater(msg);
    }
}
