/**
   * Adds a component to the middle layer of the desktop--that is, the layer for session node
   * editors. Note: The comp is a SessionEditor
   */
  public void addSessionEditor(SessionEditorIndirectRef editorRef) {
    SessionEditor editor = (SessionEditor) editorRef;

    JInternalFrame frame = new TetradInternalFrame(null);

    frame.getContentPane().add(editor);
    framesMap.put(editor, frame);
    editor.addPropertyChangeListener(this);

    // Set the "small" size of the frame so that it has sensible
    // bounds when the users unmazimizes it.
    Dimension fullSize = desktopPane.getSize();
    int smallSize = Math.min(fullSize.width - MARGIN, fullSize.height - MARGIN);
    Dimension size = new Dimension(smallSize, smallSize);
    setGoodBounds(frame, desktopPane, size);
    desktopPane.add(frame);

    // Set the frame to be maximized. This step must come after the frame
    // is added to the desktop. -Raul. 6/21/01
    try {
      frame.setMaximum(true);
    } catch (Exception e) {
      throw new RuntimeException("Problem setting frame to max: " + frame);
    }

    desktopPane.setLayer(frame, 0);
    frame.moveToFront();
    frame.setTitle(editor.getName());
    frame.setVisible(true);

    setMainTitle(editor.getName());
  }
 /** Returns a reasonable divider location for the log output. */
 private int getDivider() {
   int height;
   if (desktopPane.getSize().height == 0) {
     Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
     height = size.height;
   } else {
     height = desktopPane.getSize().height;
   }
   return (int) (height * .80);
 }
  /** Constructs a new desktop. */
  public TetradDesktop() {
    setBackground(new Color(204, 204, 204));
    sessionNodeKeys = new ArrayList();
    // Create the desktop pane.
    this.desktopPane = new JDesktopPane();

    // Do layout.
    setLayout(new BorderLayout());
    desktopPane.setDesktopManager(new DefaultDesktopManager());
    desktopPane.setBorder(new BevelBorder(BevelBorder.LOWERED));
    desktopPane.addPropertyChangeListener(this);

    this.setupDesktop();
    TetradLogger.getInstance().addTetradLoggerListener(new LoggerListener());
  }
  /**
   * Randomly picks the location of a new window, such that it fits completely on the screen.
   *
   * @param desktopPane the desktop pane that the frame is being added to.
   * @param frame the JInternalFrame which is being added.
   * @param desiredSize the desired dimensions of the frame.
   */
  private static void setGoodBounds(
      JInternalFrame frame, JDesktopPane desktopPane, Dimension desiredSize) {
    RandomUtil randomUtil = RandomUtil.getInstance();
    Dimension desktopSize = desktopPane.getSize();

    Dimension d = new Dimension(desiredSize);
    int tx = desktopSize.width - d.width;
    int ty = desktopSize.height - d.height;

    if (tx < 0) {
      tx = 0;
      d.width = desktopSize.width;
    } else {
      tx = (int) (randomUtil.nextDouble() * tx);
    }

    if (ty < 0) {
      ty = 0;
      d.height = desktopSize.height;
    } else {
      ty = (int) (randomUtil.nextDouble() * ty);
    }

    frame.setBounds(tx, ty, d.width, d.height);
  }
  /** Returns true iff there exist a session in the desktop. */
  private boolean existsSession() {
    JInternalFrame[] allFrames = desktopPane.getAllFramesInLayer(0);

    for (JInternalFrame allFrame : allFrames) {
      Object o = allFrame.getContentPane().getComponents()[0];

      if (o instanceof SessionEditor) {
        return true;
      }
    }

    return false;
  }
  public SessionEditor getFrontmostSessionEditor() {
    JInternalFrame[] allFrames = desktopPane.getAllFramesInLayer(0);

    if (allFrames.length == 0) {
      return null;
    }

    JInternalFrame frontmostFrame = allFrames[0];
    Object o = frontmostFrame.getContentPane().getComponents()[0];

    boolean isSessionEditor = o instanceof SessionEditor;
    return isSessionEditor ? (SessionEditor) o : null;
  }
  public void closeEmptySessions() {
    JInternalFrame[] frames = desktopPane.getAllFramesInLayer(0);

    for (JInternalFrame frame : frames) {
      Object o = frame.getContentPane().getComponents()[0];

      if (o instanceof SessionEditor) {
        SessionEditor sessionEditor = (SessionEditor) o;
        SessionEditorWorkbench workbench = sessionEditor.getSessionWorkbench();
        Graph graph = workbench.getGraph();
        if (graph.getNumNodes() == 0) {
          frame.dispose();
        }
      }
    }
  }
  public void closeFrontmostSession() {
    JInternalFrame[] frames = desktopPane.getAllFramesInLayer(0);

    if (frames.length > 0) {
      frames[0].dispose();
      Map<SessionEditor, JInternalFrame> framesMap = this.framesMap;
      for (Iterator<SessionEditor> i = framesMap.keySet().iterator(); i.hasNext(); ) {
        SessionEditor key = i.next();
        JInternalFrame value = framesMap.get(key);
        if (value == frames[0]) {
          i.remove();
          break;
        }
      }
    }
  }
  public boolean existsSessionByName(String filename) {
    JInternalFrame[] allFrames = desktopPane.getAllFramesInLayer(0);

    for (JInternalFrame allFrame : allFrames) {
      Object o = allFrame.getContentPane().getComponents()[0];

      if (o instanceof SessionEditor) {
        SessionEditor editor = (SessionEditor) o;

        String editorName = editor.getName();
        if (editorName.equals(filename)) {
          return true;
        }
      }
    }

    return false;
  }
  /** Adds the given componet to the given layer. */
  public void addEditorWindow(EditorWindowIndirectRef windowRef) {
    final JInternalFrame window = (JInternalFrame) windowRef;

    Dimension desktopSize = desktopPane.getSize();
    Dimension preferredSize = window.getPreferredSize();

    int x = desktopSize.width / 2 - preferredSize.width / 2;
    int y = desktopSize.height / 2 - preferredSize.height / 2;

    window.setBounds(x, y, preferredSize.width, preferredSize.height);

    // This line sometimes hangs, so I'm putting it in a watch process
    // so it can be stopped by the user. Not ideal.
    //        Window owner = (Window) getTopLevelAncestor();
    //
    //        new WatchedProcess(owner) {
    //            public void watch() {
    getDesktopPane().add(window);
    window.setLayer(100);
    window.moveToFront();

    try {
      window.setVisible(true);
    } catch (Exception e) {
      if (e instanceof ClassCastException || e instanceof NullPointerException) {
        // skip. These is being caused apparently the workbench
        // having labeled nodes and edges. Can't find a
        // workaround--probably a Java bug. jdramsey
      } else {
        e.printStackTrace();
      }
    }

    // prevents the component from being hidden.
    //                window.addComponentListener(new PositionListener());
    //            }
    //        };
  }