⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 abstractpluggableguiapplication.java

📁 具有不同语法高亮的编辑器实例
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * 04/25/2005
 *
 * AbstractPluggableGUIApplication.java - A GUI application able to be extended
 * by plugins.
 * Copyright (C) 2005 Robert Futrell
 * email@address.com
 * www.website.com
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
package org.fife.ui.app;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Paint;
import java.awt.Rectangle;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import org.fife.ui.OptionsDialog;
import org.fife.ui.SplashScreen;

/**
 * An extension of <code>AbstractGUIApplication</code> adding the ability to
 * add/remove plugins.
 */
public abstract class AbstractPluggableGUIApplication
    extends AbstractGUIApplication {

  /**
   * List of installed plugins.
   */
  private List pluginList;

  /**
   * The options dialog for plugins.
   */
  private PluginOptionsDialog pluginOptionsDialog;

  /**
   * The class loader used for plugin stuff.
   */
  private PluginClassLoader pluginClassLoader;

  private static final Color pluginTitlePanelBG1 = new Color(40, 93, 220);
  private static final Color pluginTitlePanelBG2 = new Color(200, 200, 255);

      /*****************************************************************************/

  /**
   * Constructor.
   *
   * @param jarFile The name (not full path) of the JAR file containing the
   *                main class of this application (e.g. "Foobar.jar").
   */
  public AbstractPluggableGUIApplication(String jarFile) {
    super(jarFile);
  }

      /*****************************************************************************/

  /**
   * Constructor.
   *
   * @param title The title for this frame.
   * @param jarFile The name (not full path) of the JAR file containing
   *        the main class of this application (e.g. "Foobar.jar").
   */
  public AbstractPluggableGUIApplication(String title, String jarFile) {
    super(title, jarFile);
  }

      /*****************************************************************************/

  /**
   * Constructor.  This constructor is useful when you are making a clone of
   * the current application (e.g., "Open in New Window...") and you want
   * the two instances to have the same properties.
   *
   * @param title The title for this frame.
   * @param jarFile The name (not full path) of the JAR file containing the
   *                main class of this application (e.g. "Foobar.jar").
   * @param prefs The preferences with which to initialize this application.
   */
  public AbstractPluggableGUIApplication(String title, String jarFile,
                                         GUIApplicationPreferences prefs) {
    super(title, jarFile, prefs);
  }

      /*****************************************************************************/

  /**
   * Adds a plugin to this GUI application.
   *
   * @param plugin The plugin to add.
   * @see #handleInstallPlugin
   * @see #removePlugin
   */
  public final void addPlugin(Plugin plugin) {

    if (pluginList == null) {
      pluginList = new ArrayList(1);
    }
    pluginList.add(plugin);

    // If it's a GUI plugin, we'll physically add it to
    // the GUI for you...
    if (plugin instanceof GUIPlugin) {
      GUIPlugin gp = (GUIPlugin) plugin;
      ( (MainContentPanel) mainContentPanel).addPlugin(gp);
    }
    else if (plugin instanceof StatusBarPlugin) {
      // FIXME: Get the constraints from the plugin itself.
      GridBagConstraints c = new GridBagConstraints();
      c.fill = GridBagConstraints.BOTH;
      c.weightx = 0.0;
      getStatusBar().addStatusBarComponent(
          (StatusBarPlugin) plugin, 0, c);
    }

    // And we let the plugin register any listeners, etc...
    plugin.install(this);

    // But your subclass must do everything else.
    handleInstallPlugin(plugin);

  }

      /*****************************************************************************/

  /**
   * Creates the panel that contains the main content (via the
   * <code>actualContentPane</code>.  The returned panel also contains
   * any GUI plugins.
   *
   * @param actualContentPane The panel that will contain the program's
   *        content.  This panel should be added to the returned panel.
   * @return The panel.
   */
  JPanel createMainContentPanel(JPanel actualContentPane) {
    MainContentPanel mcp = new MainContentPanel();
    mcp.setContentPanel(actualContentPane);
    return mcp;
  }

      /*****************************************************************************/

  /**
   * This is called in the GUI application's constructor.  It is a chance
   * for subclasses to do initialization of stuff that will be needed by
   * their menu bar before it gets created.
   *
   * @param prefs The preferences of the application.
   * @param splashScreen The "splash screen" for this application.  This
   *        value may be <code>null</code>.
   */
  protected void preMenuBarInit(GUIApplicationPreferences prefs,
                                SplashScreen splashScreen) {
    try {
      pluginClassLoader = new PluginClassLoader(this);
    }
    catch (IOException ioe) {
      displayException(ioe);
    }
  }

      /*****************************************************************************/

  /**
   * Returns an options dialog containing options for all installed
   * plugins.  This dialog is lazily created the first time this method
   * is called.
   *
   * @return The options dialog.
   */
  public synchronized OptionsDialog getPluginOptionsDialog() {
    return getPluginOptionsDialog(true);
  }

      /*****************************************************************************/

  /**
   * Workaround for an apparant javac bug - I could not simply make
   * <code>pluginOptionsDialog</code> protected and call
   * <code>pluginOptionsDialog.pack()</code> in a subclass without getting
   * a compiler warning about "Method pack is not public and cannot be
   * accessed outside of package"... But, I'd like a way for subclasses to
   * get to <code>pluginOptionsDialog</code> without it being created if it
   * hasn't already been.
   *
   * @param create Whether or not to create the dialog if it hasn't already
   *        been.
   * @return The plugin options dialog.
   */
  protected synchronized OptionsDialog getPluginOptionsDialog(
      boolean create) {
    if (pluginOptionsDialog == null && create) {
      pluginOptionsDialog = new PluginOptionsDialog(this);
    }
    if (pluginOptionsDialog != null) {
      pluginOptionsDialog.initialize();
    }
    return pluginOptionsDialog;
  }

      /*****************************************************************************/

  /**
   * Returns all installed plugins.  Note that this returns the actual
   * plugins and not deep copies, so any changes made to the plugin
   * array will affect the application itself.
   *
   * @return All installed plugins.  If no plugins are installed, a
   *         zero-length array is returned.
   * @see #addPlugin
   * @see #removePlugin
   */
  public Plugin[] getPlugins() {
    int count = pluginList == null ? 0 : pluginList.size();
    Plugin[] plugins = new Plugin[count];
    if (count > 0) {
      plugins = (Plugin[]) pluginList.toArray(plugins);
    }
    return plugins;
  }

      /*****************************************************************************/

  /**
   * Returns the location of the divider of the specified split pane.
   *
   * @param splitPane One of <code>GUIApplicationConstants.TOP</code>,
   *        <code>LEFT</code>, <code>BOTTOM</code>, or <code>RIGHT</code>.
   * @throws IllegalArgumentException If <code>splitPane</code> is
   *         invalid.
   * @see #setSplitPaneDividerLocation
   */
  public int getSplitPaneDividerLocation(int splitPane) {
    int dividerLocation = 0;
    switch (splitPane) {
      case TOP:
      case BOTTOM:
      case LEFT:
      case RIGHT:
        dividerLocation = ( (MainContentPanel) mainContentPanel).
            getDividerLocation(splitPane);
        break;
      default:
        throw new IllegalArgumentException("Bad splitPane value");
    }
    return dividerLocation;
  }

      /*****************************************************************************/

  /**
   * Does the dirty work of actually installing a plugin.  This method
   * should be overridden by subclasses to do stuff as appropriate for
   * a plugin.  A subclass of {@link org.fife.ui.app.GUIPlugin} will
   * already have been added to the GUI; everything else (such as adding
   * the plugin's popup menu to your menu bar) you must do yourself.
   * This default version of the method does nothing.
   *
   * @param plugin The plugin to install.
   */
  protected void handleInstallPlugin(Plugin plugin) {
  }

      /*****************************************************************************/

  /**
   * Tries to uninstall and remove the specified plugin.
   *
   * @param plugin The plugin to remove.
   * @return Whether the uninstall was successful.
   */
  public boolean removePlugin(Plugin plugin) {

    pluginList.remove(plugin);

    // If it's a GUI plugin...
    if (plugin instanceof GUIPlugin) {
      GUIPlugin gp = (GUIPlugin) plugin;
      return ( (MainContentPanel) mainContentPanel).removePlugin(gp);
    }

    else {
      throw new IllegalArgumentException(
          "Only GUIPlugins are currently supported");
    }

  }

      /*****************************************************************************/

  /**
   * This method sets the content pane.  It is overridden so it does not
   * meddle with the status bar, toolbar, etc.
   *
   * @param contentPane The new content pane.
   * @see #getContentPane
   */
  public void setContentPane(Container contentPane) {
    if (contentPane != null && !contentPane.equals(actualContentPane)) {
      MainContentPanel mcp = (MainContentPanel) mainContentPanel;
      if (actualContentPane != null) {
        mcp.removeContentPanel(actualContentPane);
      }
      mcp.setContentPanel(contentPane);
    }
  }

      /*****************************************************************************/

  /**
   * Sets the position of the divider for the specified split pane.  Note
   * that if no plugins are docked at the specified location (and thus no
   * split pane is there), this method does nothing.
   *
   * @param splitPane The split pane for which to set the divider
   *        location; one of <code>GUIApplicationConstants.TOP</code>,
   *        <code>LEFT</code>, <code>BOTTOM</code> or
   *        <code>RIGHT</code>.
   * @param pos The new position for the divider.
   * @see #getSplitPaneDividerLocation
   */
  public void setSplitPaneDividerLocation(int splitPane, int pos) {
    MainContentPanel mcp = (MainContentPanel) mainContentPanel;
    mcp.setDividerLocation(splitPane, pos);
  }

      /*****************************************************************************/
      /************************* INNER CLASSES *************************************/
      /*****************************************************************************/

  /**
   * A panel containing a bunch of <code>GUIPlugin</code>s contained
   * in a tabbed pane.
   */
  private final class PluginPanel
      extends JPanel {

    /**
     *
     */
    private static final long serialVersionUID = 5660451096830838506L;

    private JTabbedPane tabbedPane;
    private PluginTitlePanel titlePanel;

    public PluginPanel() {
      setLayout(new BorderLayout());
//			tabbedPane = new JTabbedPane();
      tabbedPane = new JTabbedPane(JTabbedPane.BOTTOM) {
        public void setUI(javax.swing.plaf.TabbedPaneUI ui) {
          // Keep using tabbed pane ui so laf stays the same,
          // but need to set a new one to pick up new tabbed
          // pane colors, fonts, etc.
          super.setUI(new PluginTabbedPaneUI());
        }
      };
      add(tabbedPane);
      titlePanel = new PluginTitlePanel("Hello world");
      tabbedPane.addChangeListener(titlePanel);
      add(titlePanel, BorderLayout.NORTH);
    }

    public boolean addPlugin(GUIPlugin plugin) {
      tabbedPane.addTab(plugin.getName(), plugin.getIcon(), plugin);
      return true;
    }

    public int containsPlugin(GUIPlugin plugin) {
      int count = tabbedPane.getTabCount();
      for (int i = 0; i < count; i++) {
        Component c = tabbedPane.getComponentAt(i);
        if (c.equals(plugin)) {
          return i;
        }
      }
      return -1; // Doesn't contain the specified plugin.
    }

    public int getPluginCount() {
      return tabbedPane.getTabCount();
    }

    public Plugin[] getPlugins() {
      int count = tabbedPane.getTabCount();
      Plugin[] plugins = new Plugin[count];
      for (int i = 0; i < count; i++) {
        plugins[i] = (Plugin)
            tabbedPane.getComponentAt(i);
      }
      return plugins;
    }

    public boolean removePlugin(GUIPlugin plugin) {
      int index = containsPlugin(plugin);
      if (index > -1) {
        tabbedPane.removeTabAt(index);
        return true;
      }
      return false;
    }

  }

      /*****************************************************************************/

  /**
   * Panel that displays the currently-active plugin in a plugin panel.
   */
  private static class PluginTitlePanel
      extends JPanel
      implements ChangeListener {

    private JLabel label;

    public PluginTitlePanel(String title) {
      super(new BorderLayout());
      setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
      label = new JLabel(title);
      label.setForeground(Color.WHITE);
      add(label);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -