////////////////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////
  // Construct The Text Pane
  public ScriptEditorPane(ProjectPreferences preferences) {
    mPreferences = preferences;
    mFont = new Font(mPreferences.sSCRIPT_FONT_TYPE, Font.PLAIN, mPreferences.sSCRIPT_FONT_SIZE);
    setFont(mFont);
    // Set Lexxer And Editor
    setEditorKit(new ScriptEditorKit());
    // Set An Empty Border
    setBorder(BorderFactory.createEmptyBorder());
    // Init Drag & Drop
    initDnDSupport();
    // Allow The Focus To Leave The Pane
    // Only If The Script Syntax Is Valid
    setInputVerifier(
        new InputVerifier() {

          @Override
          public boolean verify(final JComponent anInput) {
            // Check If The Script Is Valid
            return true;
          }
        });

    // Register Document Actions
    // registerKeyboardAction(getDocument().getUndoAction(), KeyStroke.getKeyStroke(
    //        KeyEvent.VK_Z, InputEvent.CTRL_MASK), JComponent.WHEN_FOCUSED);
    // registerKeyboardAction(getDocument().getRedoAction(), KeyStroke.getKeyStroke(
    //        KeyEvent.VK_Y, InputEvent.CTRL_MASK), JComponent.WHEN_FOCUSED);
    // Register As Event Listener
    mEventCaster.append(this);
  }
 /**
  * *************************************************************************
  *
  * <p>************************************************************************
  */
 public ProjectEditorList() {
   super(JTabbedPane.TOP, JTabbedPane.WRAP_TAB_LAYOUT);
   addChangeListener(this);
   mEventMulticaster.append(this);
 }
/** @author Gregor Mehlmann */
public class ProjectEditorList extends JTabbedPane
    implements EventListener, ChangeListener, Observer {

  private final Observable mObservable = new Observable();
  private final LOGDefaultLogger mLogger = LOGDefaultLogger.getInstance();
  private final EventCaster mEventMulticaster = EventCaster.getInstance();

  WorkSpace.ClipBoard previousCB = null;

  ////////////////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////
  private class Observable extends java.util.Observable {

    public void update(Object obj) {
      setChanged();
      notifyObservers(obj);
    }
  }

  ////////////////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////
  @Override
  public void update(java.util.Observable obs, Object obj) {
    mObservable.update(obj);
  }

  ////////////////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////
  @Override
  public void update(final EventObject event) {
    // Do Nothing
  }

  ////////////////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////
  @Override
  public void stateChanged(ChangeEvent e) {
    if (getSelectedProject() != null) {
      mObservable.update(getSelectedProject());
    }

    // copy and paste of nodes between the different projects
    ProjectEditor projectEditor = ((ProjectEditor) getSelectedComponent());
    if (projectEditor != null) {
      if (previousCB != null) {
        WorkSpace.ClipBoard currentCB =
            projectEditor.getSceneFlowEditor().getWorkSpace().getClipBoard();
        currentCB.clear();
        for (Node node : previousCB) {
          currentCB.add(node);
        }
      }
      previousCB = projectEditor.getSceneFlowEditor().getWorkSpace().getClipBoard();
    }
  }

  /**
   * *************************************************************************
   *
   * <p>************************************************************************
   */
  public ProjectEditorList() {
    super(JTabbedPane.TOP, JTabbedPane.WRAP_TAB_LAYOUT);
    addChangeListener(this);
    mEventMulticaster.append(this);
  }

  public ProjectEditor getSelectedProjectEditor() {
    return (ProjectEditor) getSelectedComponent();
  }

  public ProjectData getSelectedProject() {
    if (getSelectedComponent() != null) {
      return ((ProjectEditor) getSelectedComponent()).getProject();
    } else {
      return null;
    }
  }

  public void add(ProjectData project) {
    // Create a new project editor from the given project
    ProjectEditor projectEditor = new ProjectEditor(project);
    // Add the new project editor as observer
    mObservable.addObserver(projectEditor);
    // Add the project editor to the list of project editors
    // and select it as a component in the tabbed pane
    addTab(project.getProjectName(), projectEditor);
    setSelectedComponent(projectEditor);
    // Initialize the workspace of the project editor's scene flow editor
    // TODO: push down into an init function
    //        projectEditor.getSceneFlowEditor().getWorkSpace().showNodesOnWorkSpace();
    //        projectEditor.getSceneFlowEditor().getWorkSpace().showEdgesOnWorkSpace();
    //
    // projectEditor.getSceneFlowEditor().getWorkSpace().showVariablesOnWorkSpace(project.getSceneFlow());
    //        projectEditor.getSceneFlowEditor().getWorkSpace().repaint();
    //
    //        // Revalidade and repaint
    //        revalidate();
    //        repaint();
  }

  public void saveCurrent() {
    ((ProjectEditor) getSelectedComponent()).save();
  }

  public void closeCurrent() {
    ProjectEditor projectEditor = ((ProjectEditor) getSelectedComponent());
    mObservable.deleteObserver(projectEditor);
    projectEditor.close();
    remove(projectEditor);
  }

  public void saveAll() {
    for (int i = 0; i < getTabCount(); i++) {
      ((ProjectEditor) getComponentAt(i)).save();
    }
  }

  public void closeAll() {
    // Delete all observers
    mObservable.deleteObservers();
    // Close all projects
    for (int i = 0; i < getTabCount(); i++) {
      ((ProjectEditor) getComponentAt(i)).close();
    }
  }
}
/** @author Gregor Mehlmann */
public class ScriptEditorPane extends JEditorPane implements EventListener, Observer {

  // The System Logger
  private final LOGDefaultLogger mLogger = LOGDefaultLogger.getInstance();
  // The Event Caster
  private final EventCaster mEventCaster = EventCaster.getInstance();
  // Init Drag & Drop Support
  private DropTargetListener mDropListener;
  private DropTarget mDropTarget;
  private int mValidActions;
  // Activity monitor
  private Font mFont = new Font("Courier New", Font.PLAIN, 12);
  private final ProjectPreferences mPreferences;

  ////////////////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////
  // Construct The Text Pane
  public ScriptEditorPane(ProjectPreferences preferences) {
    mPreferences = preferences;
    mFont = new Font(mPreferences.sSCRIPT_FONT_TYPE, Font.PLAIN, mPreferences.sSCRIPT_FONT_SIZE);
    setFont(mFont);
    // Set Lexxer And Editor
    setEditorKit(new ScriptEditorKit());
    // Set An Empty Border
    setBorder(BorderFactory.createEmptyBorder());
    // Init Drag & Drop
    initDnDSupport();
    // Allow The Focus To Leave The Pane
    // Only If The Script Syntax Is Valid
    setInputVerifier(
        new InputVerifier() {

          @Override
          public boolean verify(final JComponent anInput) {
            // Check If The Script Is Valid
            return true;
          }
        });

    // Register Document Actions
    // registerKeyboardAction(getDocument().getUndoAction(), KeyStroke.getKeyStroke(
    //        KeyEvent.VK_Z, InputEvent.CTRL_MASK), JComponent.WHEN_FOCUSED);
    // registerKeyboardAction(getDocument().getRedoAction(), KeyStroke.getKeyStroke(
    //        KeyEvent.VK_Y, InputEvent.CTRL_MASK), JComponent.WHEN_FOCUSED);
    // Register As Event Listener
    mEventCaster.append(this);
  }

  /*
  // Paint The Text Pane
  @Override
  protected final synchronized void paintComponent(final Graphics graphics) {
  super.paintComponent(graphics);

  // If there are visualization tasks then visualize them
  if (!mVisualisationTasks.isEmpty()) {
  // TODO: why create() and clone()?
  Graphics2D graphics2D = (Graphics2D) graphics.create();
  ArrayList<ScriptEditPanel.HighlightTask> visTasks = (ArrayList<ScriptEditPanel.HighlightTask>) mVisualisationTasks.clone();

  for (ScriptEditPanel.HighlightTask highlightTask : visTasks) {
  // draw activity cue
  if (highlightTask.getActivityTime() > 20) {
  graphics2D.setColor(highlightTask.mColor);
  graphics2D.fillRect(
  highlightTask.getXPos(),
  highlightTask.getYPos(),
  highlightTask.getWidth(),
  highlightTask.getHeight());
  } else {
  // Draw the fading away of the highlight
  Color c = new Color(
  highlightTask.mColor.getRed(),
  highlightTask.mColor.getGreen(),
  highlightTask.mColor.getBlue(),
  highlightTask.mColor.getTransparency() - (highlightTask.mColor.getTransparency() - 5 * highlightTask.getActivityTime()));
  graphics2D.setColor(c);
  graphics2D.fillRect(
  highlightTask.getXPos(),
  highlightTask.getYPos(),
  highlightTask.getWidth(),
  highlightTask.getHeight());
  }
  }
  graphics2D.dispose();
  }
  }*/
  ////////////////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////
  // Init Drag & Drop Support
  private void initDnDSupport() {
    mValidActions = DnDConstants.ACTION_COPY;
    mDropListener =
        new DropTargetListener() {

          @Override
          public void dragEnter(final DropTargetDragEvent dtde) {
            // Do Nothing Here
          }

          @Override
          public void dragExit(final DropTargetEvent dte) {
            // Do Nothing Here
          }

          @Override
          public void dropActionChanged(final DropTargetDragEvent dtde) {
            // Do Nothing Here
          }

          @Override
          public void dragOver(final DropTargetDragEvent dtde) {
            Object data = null;
            DataFlavor flavor = null;
            try {
              try {
                flavor = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType);
              } catch (ClassNotFoundException exc) {
                exc.printStackTrace();
              }
              data = dtde.getTransferable().getTransferData(flavor);
            } catch (UnsupportedFlavorException | IOException exc) {
              exc.printStackTrace();
              dtde.rejectDrag();
            }

            if (data instanceof ActiconAction) {
              dtde.acceptDrag(dtde.getDropAction());
              setCaretPosition(viewToModel(dtde.getLocation()));

            } else if (data instanceof GesticonGesture) {
              dtde.acceptDrag(dtde.getDropAction());
              setCaretPosition(viewToModel(dtde.getLocation()));

            } else if (data instanceof VisiconViseme) {
              dtde.acceptDrag(dtde.getDropAction());
              setCaretPosition(viewToModel(dtde.getLocation()));

            } else {
              dtde.rejectDrag();
            }
          }

          ////////////////////////////////////////////////////////////////////
          ////////////////////////////////////////////////////////////////////
          ////////////////////////////////////////////////////////////////////
          @Override
          public final void drop(final DropTargetDropEvent dtde) {
            Object data = null;
            DataFlavor flavor = null;
            try {
              try {
                // Get The Data Flavour
                flavor = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType);
              } catch (ClassNotFoundException exc) {
                exc.printStackTrace();
              }
              // Transfer The Data
              data = dtde.getTransferable().getTransferData(flavor);
            } catch (UnsupportedFlavorException | IOException exc) {
              dtde.rejectDrop();
            }
            // Check The Data Type
            if (data instanceof ActiconAction) {
              // Compute the Drop Position
              int dropPosition = viewToModel(dtde.getLocation());
              // Insert The Acticon Action
              try {
                // Cast The Data To An Action
                ActiconAction action = (ActiconAction) data;
                // Insert The Text In Document
                getDocument().insertString(dropPosition, action.toScript(), null);
                // Set The Caret Position
                setCaretPosition(dropPosition);
                // Accept the drop
                dtde.acceptDrop(mValidActions);
                dtde.getDropTargetContext().dropComplete(true);
              } catch (BadLocationException | InvalidDnDOperationException exc) {
                exc.printStackTrace();
                // Reject The Drop
                dtde.rejectDrop();
              }
            } else if (data instanceof GesticonGesture) {
              // Compute the Drop Position
              int dropPosition = viewToModel(dtde.getLocation());
              // Insert The Gesticon Gesture
              try {
                // Cast The Data To A Gesture
                GesticonGesture gesture = (GesticonGesture) data;
                // Insert The Text In Document
                getDocument().insertString(dropPosition, gesture.toScript(), null);
                // Set The Caret Position
                setCaretPosition(dropPosition);
                // Accept the drop
                dtde.acceptDrop(mValidActions);
                dtde.getDropTargetContext().dropComplete(true);
              } catch (BadLocationException | InvalidDnDOperationException exc) {
                exc.printStackTrace();
                // Reject The Drop
                dtde.rejectDrop();
              }
            } else if (data instanceof VisiconViseme) {
              // Compute the Drop Position
              int modelDropPosition = viewToModel(dtde.getLocation());
              // TODO: Do Something Here
            } else {
              // Reject The Drop
              dtde.rejectDrop();
            }
          }
        };
    // Set The Drop Target
    mDropTarget = new DropTarget(this, mDropListener);
  }

  ////////////////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////
  @Override
  public void update(final Observable obs, final Object obj) {
    // Do Nothing
    mFont = new Font(mPreferences.sSCRIPT_FONT_TYPE, Font.PLAIN, mPreferences.sSCRIPT_FONT_SIZE);
    setFont(mFont);
  }

  ////////////////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////
  @Override
  public void update(final EventObject event) {
    // Do Nothing
    mFont = new Font(mPreferences.sSCRIPT_FONT_TYPE, Font.PLAIN, mPreferences.sSCRIPT_FONT_SIZE);
    setFont(mFont);
  }

  ////////////////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////
  private class HighlightTask extends VisualisationTask {

    private Color mColor = null;
    private Rectangle mRect = null;

    public HighlightTask(
        final int steps, final JComponent c, final Color col, final Rectangle rect) {
      super(steps, c);
      mColor = col;
      mRect = rect;
    }

    public int getXPos() {
      return mRect.x;
    }

    public int getYPos() {
      return mRect.y;
    }

    public int getWidth() {
      return mRect.width;
    }

    public int getHeight() {
      return mRect.height;
    }
  }
}