/**
  * This method should make the changes visible in the inner representation of the graph. Currently
  * it generates a totally new graph from an empty one.
  */
 public void refreshGraph() {
   if (generator == null) {
     return;
   }
   try {
     generator.generateGraph();
     setLabeller(generator.getLabeler());
     setGraph(generator.getGraph());
   } catch (InterruptedException ex) {
     errorHandler.reportException("Error while refreshing the graph", ex);
   }
 }
  /**
   * This method generates the dependency graph and sets an {@link EditorPart} to show the graph's
   * window.
   */
  @Override
  public void createPartControl(final Composite parent) {
    initGeneratorAndHandler(parent);
    editorComposite = new Composite(parent, SWT.NO_BACKGROUND | SWT.EMBEDDED);
    window = SWT_AWT.new_Frame(editorComposite);
    windowSize = new Dimension(parent.getSize().x, parent.getSize().y);

    parent.addListener(
        SWT.Resize,
        new Listener() {
          @Override
          public void handleEvent(org.eclipse.swt.widgets.Event event) {
            Point tmpSize = parent.getSize();
            windowSize = new Dimension(tmpSize.x, tmpSize.y);
            if (handler != null) {
              handler.changeWindowSize(windowSize);
            }
            if (window != null && drawArea != null) {
              drawArea.setPreferredSize(windowSize);
              window.setPreferredSize(windowSize);
              window.repaint();
            }
          }
        });

    project = ((IFileEditorInput) getEditorInput()).getFile().getProject();
    setPartName(getPartName() + " - " + project.getName());

    // get a reference to the satellite viewer
    satView =
        (SatelliteView)
            PlatformUI.getWorkbench()
                .getActiveWorkbenchWindow()
                .getActivePage()
                .findView(SatelliteView.ID);
    if (satView != null) {
      satView.setEditor(this);
    } else {
      try {
        satView =
            (SatelliteView)
                PlatformUI.getWorkbench()
                    .getActiveWorkbenchWindow()
                    .getActivePage()
                    .showView(SatelliteView.ID);
        satView.setEditor(this);
      } catch (PartInitException e) {
        errorHandler.reportException("Error while opening the view", e);
      }
    }
    initWindow();
  }
  /** This method creates the items to show on the {@link Frame} , and adds actions */
  protected void initWindow() {
    drawArea = new JPanel();
    window.add(drawArea, BorderLayout.CENTER);
    drawArea.setSize(windowSize.width, windowSize.height);
    drawArea.setPreferredSize(new Dimension(windowSize.width, windowSize.height));

    menuBar = new JMenuBar();
    window.add(menuBar, BorderLayout.NORTH);

    JMenu mnFile = new JMenu("File");

    ActionListener saveGraph =
        new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            String path = "";
            try {
              path =
                  project.getPersistentProperty(
                      new QualifiedName(ProjectBuildPropertyData.QUALIFIER, "Graph_Save_Path"));
            } catch (CoreException exc) {
              errorHandler.reportException("Error while reading persistent property", exc);
            }
            final String oldPath = path;
            Display.getDefault()
                .asyncExec(
                    new Runnable() {
                      @Override
                      public void run() {
                        FileDialog dialog = new FileDialog(editorComposite.getShell(), SWT.SAVE);
                        dialog.setText("Save Pajek file");
                        dialog.setFilterPath(oldPath);
                        dialog.setFilterExtensions(new String[] {"*.net", "*.dot"});
                        String graphFilePath = dialog.open();
                        if (graphFilePath == null) {
                          return;
                        }
                        String newPath =
                            graphFilePath.substring(
                                0, graphFilePath.lastIndexOf(File.separator) + 1);
                        try {
                          QualifiedName name =
                              new QualifiedName(
                                  ProjectBuildPropertyData.QUALIFIER, "Graph_Save_Path");
                          project.setPersistentProperty(name, newPath);

                          if ("dot"
                              .equals(
                                  graphFilePath.substring(
                                      graphFilePath.lastIndexOf('.') + 1,
                                      graphFilePath.length()))) {
                            GraphHandler.saveGraphToDot(graph, graphFilePath, project.getName());
                          } else {
                            GraphHandler.saveGraphToPajek(graph, graphFilePath);
                          }

                        } catch (BadLayoutException be) {
                          ErrorReporter.logExceptionStackTrace(
                              "Error while saving image to " + newPath, be);
                          errorHandler.reportErrorMessage("Bad layout\n\n" + be.getMessage());
                        } catch (Exception ce) {
                          ErrorReporter.logExceptionStackTrace(
                              "Error while saving image to " + newPath, ce);
                          errorHandler.reportException(
                              "Error while setting persistent property", ce);
                        }
                      }
                    });
          }
        };

    final JMenuItem mntmSave = new JMenuItem("Save (Ctrl+S)");
    mntmSave.addActionListener(saveGraph);
    mnFile.add(mntmSave);

    ActionListener exportImage =
        new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            String path = "";
            try {
              path =
                  project.getPersistentProperty(
                      new QualifiedName(ProjectBuildPropertyData.QUALIFIER, "Graph_Save_Path"));
            } catch (CoreException exc) {
              errorHandler.reportException("Error while reading persistent property", exc);
            }
            final String oldPath = path;
            Display.getDefault()
                .asyncExec(
                    new Runnable() {
                      @Override
                      public void run() {
                        ExportPreferencesDialog prefDialog =
                            new ExportPreferencesDialog(editorComposite.getShell());
                        ImageExportType mode = prefDialog.open();

                        FileDialog dialog = new FileDialog(editorComposite.getShell(), SWT.SAVE);
                        dialog.setText("Export image");
                        dialog.setFilterPath(oldPath);
                        dialog.setFilterExtensions(new String[] {"*.png"});
                        String graphFilePath = dialog.open();
                        if (graphFilePath == null) {
                          return;
                        }
                        String newPath =
                            graphFilePath.substring(
                                0, graphFilePath.lastIndexOf(File.separator) + 1);
                        try {
                          QualifiedName name =
                              new QualifiedName(
                                  ProjectBuildPropertyData.QUALIFIER, "Graph_Save_Path");
                          project.setPersistentProperty(name, newPath);
                          handler.saveToImage(graphFilePath, mode);
                        } catch (BadLayoutException be) {
                          errorHandler.reportException("Error while saving image", be);
                          errorHandler.reportErrorMessage(be.getMessage());
                        } catch (CoreException ce) {
                          errorHandler.reportException(
                              "Error while setting persistent property", ce);
                        }
                      }
                    });
          }
        };

    final JMenuItem mntmExportToImage = new JMenuItem("Export to image file (Ctrl+E)");
    mntmExportToImage.addActionListener(exportImage);
    mnFile.add(mntmExportToImage);

    layoutMenu = new JMenu("Layout");
    layoutGroup = new ButtonGroup();

    layoutListener =
        new ActionListener() {
          @Override
          public void actionPerformed(final ActionEvent e) {
            final IProgressMonitor monitor = Job.getJobManager().createProgressGroup();
            monitor.beginTask("Change layout", 100);
            if (!(e.getSource() instanceof LayoutEntry)) {
              errorHandler.reportErrorMessage(
                  "Unexpected error\n\nAn unusual error has been logged" + LOGENTRYNOTE);
              ErrorReporter.logError(
                  "The layout changing event's source is not of type \"LayoutEntry\"!");
              return;
            }
            final LayoutEntry layout = (LayoutEntry) e.getSource();
            if (handler.getVisualizator() != null) {
              drawArea.remove(handler.getVisualizator());
            }
            try {
              handler.changeLayout(layout, windowSize);
              drawArea.add(handler.getVisualizator());
              if (satView != null) {
                satView.add(handler.getSatelliteViewer());
              }
              window.pack();
            } catch (BadLayoutException exc) {
              layout.setSelected(false);
              chosenLayout.setSelected(true);
              if (exc.getType() == ErrorType.EMPTY_GRAPH || exc.getType() == ErrorType.NO_OBJECT) {
                return;
              }
              try {
                handler.changeLayout(chosenLayout, windowSize);
                drawArea.add(handler.getVisualizator());
                if (satView != null) {
                  satView.add(handler.getSatelliteViewer());
                }
                window.pack();
                monitor.done();
              } catch (BadLayoutException exc2) {
                monitor.done();
                if (exc2.getType() != ErrorType.CYCLIC_GRAPH
                    && exc2.getType() != ErrorType.EMPTY_GRAPH) {
                  errorHandler.reportException("Error while creating layout", exc2);
                } else {
                  errorHandler.reportErrorMessage(exc2.getMessage());
                }
              } catch (IllegalStateException exc3) {
                monitor.done();
                errorHandler.reportException("Error while creating layout", exc3);
              }
              if (exc.getType() != ErrorType.CYCLIC_GRAPH
                  && exc.getType() != ErrorType.EMPTY_GRAPH) {
                errorHandler.reportException("Error while creating layout", exc);
              } else {
                errorHandler.reportErrorMessage(exc.getMessage());
              }
            } catch (IllegalStateException exc) {
              layout.setSelected(false);
              chosenLayout.setSelected(true);
              try {
                handler.changeLayout(chosenLayout, windowSize);
                drawArea.add(handler.getVisualizator());
                if (satView != null) {
                  satView.add(handler.getSatelliteViewer());
                }
                window.pack();
                monitor.done();
              } catch (BadLayoutException exc2) {
                monitor.done();
                if (exc2.getType() != ErrorType.CYCLIC_GRAPH
                    && exc2.getType() != ErrorType.EMPTY_GRAPH) {
                  errorHandler.reportException("Error while creating layout", exc2);
                } else {
                  errorHandler.reportErrorMessage(exc2.getMessage());
                }
              } catch (IllegalStateException exc3) {
                monitor.done();
                errorHandler.reportException("Error while creating layout", exc3);
              }
              errorHandler.reportException("Error while creating layout", exc);
            }
            chosenLayout = layout.clone();
            monitor.done();
          }
        };

    JMenu findMenu = new JMenu("Find");
    final JMenuItem nodeByName = new JMenuItem("Node by name (Ctrl+F)");

    final GraphEditor thisEditor = this;
    nodeByName.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            Display.getDefault()
                .asyncExec(
                    new Runnable() {
                      @Override
                      public void run() {
                        if (wndFind != null) {
                          wndFind.close();
                        }
                        try {
                          wndFind =
                              new FindWindow<NodeDescriptor>(
                                  editorComposite.getShell(), thisEditor, graph.getVertices());
                          wndFind.open();
                        } catch (IllegalArgumentException e) {
                          errorHandler.reportException("", e);
                        }
                      }
                    });
          }
        });

    findMenu.add(nodeByName);

    JMenu tools = new JMenu("Tools");
    final JMenuItem findCircles = new JMenuItem("Show circles");
    final JMenuItem findPaths = new JMenuItem("Show parallel paths");
    final JMenuItem clearResults = new JMenuItem("Clear Results");

    findCircles.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent ev) {
            Job circlesJob =
                new Job("Searching for circles") {
                  @Override
                  protected IStatus run(IProgressMonitor monitor) {
                    if (graph == null) {
                      return null;
                    }
                    CircleCheck<NodeDescriptor, EdgeDescriptor> checker =
                        new CircleCheck<NodeDescriptor, EdgeDescriptor>(graph);
                    if (checker.isCyclic()) {
                      for (EdgeDescriptor e : graph.getEdges()) {
                        e.setColour(Color.lightGray);
                      }
                      for (Deque<EdgeDescriptor> st : checker.getCircles()) {
                        for (EdgeDescriptor e : st) {
                          e.setColour(NodeColours.DARK_RED);
                        }
                      }
                      refresh();
                    } else {
                      errorHandler.reportInformation("Result:\n\nThis graph is not cyclic!");
                    }

                    return Status.OK_STATUS;
                  } // end run
                }; // end job
            circlesJob.schedule();
          } // end actionPerformed
        });

    findPaths.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent ev) {
            Job pathsJob =
                new Job("Searching for parallel paths") {
                  @Override
                  protected IStatus run(IProgressMonitor monitor) {
                    if (graph == null) {
                      return null;
                    }
                    CheckParallelPaths<NodeDescriptor, EdgeDescriptor> checker = null;
                    checker = new CheckParallelPaths<NodeDescriptor, EdgeDescriptor>(graph);
                    if (checker.hasParallelPaths()) {
                      for (EdgeDescriptor e : graph.getEdges()) {
                        e.setColour(Color.lightGray);
                      }
                      for (Deque<EdgeDescriptor> list : checker.getPaths()) {
                        for (EdgeDescriptor e : list) {
                          e.setColour(NodeColours.DARK_RED);
                        }
                      }
                      refresh();
                    } else {
                      errorHandler.reportInformation(
                          "Result:\n\nThere are no parallel paths in this graph!");
                    }

                    return Status.OK_STATUS;
                  } // end run
                }; // end job
            pathsJob.schedule();
          } // end actionPerformed
        });

    clearResults.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent ev) {
            for (EdgeDescriptor e : graph.getEdges()) {
              e.setColour(Color.black);
            }
            refresh();
          }
        });

    tools.add(findCircles);
    tools.add(findPaths);
    tools.add(clearResults);

    menuBar.add(mnFile);
    menuBar.add(findMenu);
    menuBar.add(tools);
    menuBar.add(layoutMenu);

    // TODO implement refresh action
    /*
     * JMenuItem RefreshMenu=new JMenuItem("Refresh"); ActionListener
     * RefreshAction=new ActionListener() { public void
     * actionPerformed(ActionEvent ev) { GraphGenerator.schedule(); } };
     * RefreshMenu.addActionListener(RefreshAction);
     *
     * menuBar.add(RefreshMenu);
     */

    handlerService.activateHandler(
        GRAPH_SEARCHCMD_ID,
        new AbstractHandler() {
          @Override
          public Object execute(ExecutionEvent event) throws ExecutionException {
            nodeByName.getActionListeners()[0].actionPerformed(null);
            handlers.add(this);
            return null;
          }
        });

    handlerService.activateHandler(
        GRAPH_SAVECMD_ID,
        new AbstractHandler() {
          @Override
          public Object execute(ExecutionEvent event) throws ExecutionException {
            mntmSave.getActionListeners()[0].actionPerformed(null);
            handlers.add(this);
            return null;
          }
        });

    handlerService.activateHandler(
        GRAPH_EXPORTCMD_ID,
        new AbstractHandler() {
          @Override
          public Object execute(ExecutionEvent event) throws ExecutionException {
            mntmExportToImage.getActionListeners()[0].actionPerformed(null);
            handlers.add(this);
            return null;
          }
        });

    try {
      generator.generateGraph();
      setLabeller(generator.getLabeler());
      setGraph(generator.getGraph());
    } catch (InterruptedException ex) {
      errorHandler.reportException("Error while creating the graph", ex);
    }
  }