MainWindow.java :  » Database-Client » SQL-Workbench » workbench » gui » Java Open Source

Java Open Source » Database Client » SQL Workbench 
SQL Workbench » workbench » gui » MainWindow.java
/*
 * MainWindow.java
 *
 * This file is part of SQL Workbench/J, http://www.sql-workbench.net
 *
 * Copyright 2002-2008, Thomas Kellerer
 * No part of this code maybe reused without the permission of the author
 *
 * To contact the author please send an email to: support@sql-workbench.net
 *
 */
package workbench.gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import javax.swing.Action;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import workbench.WbManager;
import workbench.db.ConnectionMgr;
import workbench.db.ConnectionProfile;
import workbench.db.WbConnection;
import workbench.gui.actions.AboutAction;
import workbench.gui.actions.ConfigureShortcutsAction;
import workbench.gui.actions.ShowManualAction;
import workbench.gui.actions.WbAction;
import workbench.gui.components.RunningJobIndicator;
import workbench.interfaces.Moveable;
import workbench.util.ExceptionUtil;
import workbench.gui.actions.AddMacroAction;
import workbench.gui.actions.AddTabAction;
import workbench.gui.actions.AssignWorkspaceAction;
import workbench.gui.actions.CloseWorkspaceAction;
import workbench.gui.actions.DataPumperAction;
import workbench.gui.actions.FileConnectAction;
import workbench.gui.actions.FileDisconnectAction;
import workbench.gui.actions.FileExitAction;
import workbench.gui.actions.FileNewWindowAction;
import workbench.gui.actions.LoadWorkspaceAction;
import workbench.gui.actions.ManageDriversAction;
import workbench.gui.actions.ManageMacroAction;
import workbench.gui.actions.NewDbExplorerPanelAction;
import workbench.gui.actions.NewDbExplorerWindowAction;
import workbench.gui.actions.RemoveTabAction;
import workbench.gui.actions.RunMacroAction;
import workbench.gui.actions.SaveAsNewWorkspaceAction;
import workbench.gui.actions.SaveWorkspaceAction;
import workbench.gui.actions.SelectTabAction;
import workbench.gui.actions.ShowDbExplorerAction;
import workbench.gui.actions.VersionCheckAction;
import workbench.gui.actions.ViewLineNumbers;
import workbench.gui.actions.WbAction;
import workbench.gui.components.ConnectionSelector;
import workbench.gui.components.WbMenu;
import workbench.gui.components.WbTabbedPane;
import workbench.gui.components.WbToolbar;
import workbench.gui.dbobjects.DbExplorerPanel;
import workbench.gui.menu.SqlTabPopup;
import workbench.gui.sql.SqlPanel;
import workbench.interfaces.Connectable;
import workbench.interfaces.DbExecutionListener;
import workbench.interfaces.FilenameChangeListener;
import workbench.interfaces.MacroChangeListener;
import workbench.interfaces.MainPanel;
import workbench.log.LogMgr;
import workbench.resource.ResourceMgr;
import workbench.resource.Settings;
import workbench.sql.MacroManager;
import workbench.util.FileDialogUtil;
import workbench.util.StringUtil;
import workbench.util.WbThread;
import workbench.util.WbWorkspace;
import workbench.gui.actions.FileSaveProfiles;
import workbench.gui.actions.InsertTabAction;
import workbench.gui.actions.OptionsDialogAction;
import workbench.gui.actions.ShowHelpAction;
import workbench.gui.actions.CreateNewConnection;
import workbench.gui.actions.DisconnectTabAction;
import workbench.gui.actions.ViewToolbarAction;
import workbench.gui.actions.WhatsNewAction;
import workbench.gui.dbobjects.DbExplorerWindow;
import workbench.interfaces.ToolWindow;
import workbench.util.NumberStringCache;

/**
 * The main window for the Workbench.
 * It will display several {@link workbench.gui.sql.SqlPanel}s in
 * a tabbed pane. Additionally one or more {@link workbench.gui.dbobjects.DbExplorerPanel} 
 * might also be displayed inside the JTabbedPane
 *
 * @author  support@sql-workbench.net
 */
public class MainWindow
  extends JFrame
  implements MouseListener, WindowListener, ChangeListener, DropTargetListener,
            MacroChangeListener, DbExecutionListener, Connectable, PropertyChangeListener, Moveable
{
  private static final String DEFAULT_WORKSPACE = "%ConfigDir%/Default.wksp";
  private static int instanceCount;
  private int windowId;

  private WbConnection currentConnection;
  private ConnectionProfile currentProfile;
  protected ConnectionSelector connectionSelector;

  private FileDisconnectAction disconnectAction;
  private CreateNewConnection createNewConnection;
  private DisconnectTabAction disconnectTab;
  private ShowDbExplorerAction dbExplorerAction;
  private NewDbExplorerPanelAction newDbExplorerPanel;
  private NewDbExplorerWindowAction newDbExplorerWindow;

  private WbTabbedPane sqlTab;
  private WbToolbar currentToolbar;
  private ArrayList<JMenuBar> panelMenus = new ArrayList<JMenuBar>(13);

  private String currentWorkspaceFile;

  private CloseWorkspaceAction closeWorkspaceAction;
  private SaveWorkspaceAction saveWorkspaceAction;
  private SaveAsNewWorkspaceAction saveAsWorkspaceAction;
  private LoadWorkspaceAction loadWorkspaceAction;
  private AssignWorkspaceAction assignWorkspaceAction;

  private boolean isProfileWorkspace;
  private boolean tabRemovalInProgress;

  // will indicate a connect or disconnect in progress
  // connecting and disconnecting is done in a separate thread
  // so that slow connections do not block the GUI
  private boolean connectInProgress;

  private AddMacroAction createMacro;
  private ManageMacroAction manageMacros;
  
  private List<ToolWindow> explorerWindows = new ArrayList<ToolWindow>();
  
  private RunningJobIndicator jobIndicator;
  protected WbThread connectThread;
    
  public MainWindow()
  {
    super(ResourceMgr.TXT_PRODUCT_NAME);
    this.windowId = ++instanceCount;
    
    sqlTab = new WbTabbedPane();
    sqlTab.setFocusable(false);
    
    String policy = Settings.getInstance().getProperty("workbench.gui.sqltab.policy", "wrap");
    if ("wrap".equalsIgnoreCase(policy))
    {
      sqlTab.setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT);
    }
    else if ("scroll".equalsIgnoreCase(policy))
    {
      sqlTab.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
    }
    
    this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);

    initMenu();
    setIconImage(ResourceMgr.getPicture("workbench16").getImage());
    
    this.getContentPane().add(this.sqlTab, BorderLayout.CENTER);

    this.restoreSettings();
    
    this.checkWorkspaceActions();

    this.sqlTab.addChangeListener(this);
    this.sqlTab.addMouseListener(this);

    this.addWindowListener(this);
    MacroManager.getInstance().addChangeListener(this);
    this.jobIndicator = new RunningJobIndicator(this);
    
    new DropTarget(this.sqlTab, DnDConstants.ACTION_COPY, this);
    sqlTab.enableDragDropReordering(this);
    Settings.getInstance().addPropertyChangeListener(this, Settings.PROPERTY_SHOW_TOOLBAR);
  }

  public void display()
  {
    this.restoreState();
    this.setVisible(true);
    this.addTab(true, false);
    this.updateGuiForTab(0);
    this.updateWindowTitle();
  }
  
  /**
   * The listener will be notified when the name of a tab changes.
   * This is used in the {@link workbench.gui.dbobjects.TableListPanel}
   * to display the available panels in the context menu
   * @see workbench.gui.dbobjects.EditorTabSelectMenu#fileNameChanged(Object, String)
   */
  public void addFilenameChangeListener(FilenameChangeListener aListener)
  {
    for (int i=0; i < this.sqlTab.getTabCount(); i++)
    {
      MainPanel panel = this.getSqlPanel(i);
      if (panel instanceof SqlPanel)
      {
        SqlPanel sql = (SqlPanel)panel;
        sql.addFilenameChangeListener(aListener);
      }
    }
  }

  /**
   * Remove the file name change listener.
   * @see #addFilenameChangeListener(FilenameChangeListener )
   */  
  public void removeFilenameChangeListener(FilenameChangeListener aListener)
  {
    for (int i=0; i < this.sqlTab.getTabCount(); i++)
    {
      MainPanel panel = this.getSqlPanel(i);
      if (panel instanceof SqlPanel)
      {
        SqlPanel sql = (SqlPanel)panel;
        sql.removeFilenameChangeListener(aListener);
      }
    }
  }

  /**
   * The listener will be notified when the current tab changes.
   * This is used in the {@link workbench.gui.dbobjects.TableListPanel}
   * to highlight the current tab the context menu
   * @see workbench.gui.dbobjects.TableListPanel#stateChanged(ChangeEvent)
   */
  public void addIndexChangeListener(ChangeListener aListener)
  {
    this.sqlTab.addChangeListener(aListener);
  }

  public void removeIndexChangeListener(ChangeListener aListener)
  {
    this.sqlTab.removeChangeListener(aListener);
  }

  public void addExecutionListener(DbExecutionListener l)
  {
    int count = this.sqlTab.getTabCount();
    for (int i = 0; i < count; i++)
    {
      MainPanel p = this.getSqlPanel(i);
      if (p instanceof SqlPanel)
      {
        ((SqlPanel)p).addDbExecutionListener(l);
      }
    }
  }
  
  public void removeExecutionListener(DbExecutionListener l)
  {
    int count = this.sqlTab.getTabCount();
    for (int i = 0; i < count; i++)
    {
      MainPanel p = this.getSqlPanel(i);
      if (p instanceof SqlPanel)
      {
        ((SqlPanel)p).removeDbExecutionListener(l);
      }
    }
  }
  
  protected void checkWorkspaceActions()
  {
    this.saveWorkspaceAction.setEnabled(this.currentWorkspaceFile != null);
    this.assignWorkspaceAction.setEnabled(this.currentWorkspaceFile != null && this.currentProfile != null);
    this.closeWorkspaceAction.setEnabled(this.currentWorkspaceFile != null);
  }

  private void initMenu()
  {
    this.disconnectAction = new FileDisconnectAction(this);
    this.disconnectAction.setEnabled(false);
    this.assignWorkspaceAction = new AssignWorkspaceAction(this);
    this.closeWorkspaceAction = new CloseWorkspaceAction(this);
    this.saveAsWorkspaceAction = new SaveAsNewWorkspaceAction(this);

    this.createNewConnection = new CreateNewConnection(this);
    this.disconnectTab = new DisconnectTabAction(this);
    
    this.loadWorkspaceAction = new LoadWorkspaceAction(this);
    this.saveWorkspaceAction = new SaveWorkspaceAction(this);
    
    this.createMacro = new AddMacroAction();
    
    this.createMacro.setEnabled(false);
    this.manageMacros = new ManageMacroAction(this);

    this.dbExplorerAction = new ShowDbExplorerAction(this);
    this.dbExplorerAction.setEnabled(false);

    this.newDbExplorerPanel = new NewDbExplorerPanelAction(this);
    this.newDbExplorerPanel.setEnabled(false);

    this.newDbExplorerWindow = new NewDbExplorerWindowAction(this);
    this.newDbExplorerWindow.setEnabled(false);

    int tabCount = this.sqlTab.getTabCount();
    for (int tab=0; tab < tabCount; tab ++)
    {
      MainPanel sql = (MainPanel)this.sqlTab.getComponentAt(tab);
      JMenuBar menuBar = this.createMenuForPanel(sql);
      this.panelMenus.add(menuBar);
    }
  }

  private JMenuBar createMenuForPanel(MainPanel aPanel)
  {
    HashMap<String, JMenu> menus = new HashMap<String, JMenu>(10);

    JMenuBar menuBar = new JMenuBar();
    menuBar.setBorderPainted(false);
    menuBar.putClientProperty("jgoodies.headerStyle", "Single");

    // Create the file menu for all tabs
    JMenu menu = new WbMenu(ResourceMgr.getString(ResourceMgr.MNU_TXT_FILE));
    menu.setName(ResourceMgr.MNU_TXT_FILE);
    menuBar.add(menu);
    menus.put(ResourceMgr.MNU_TXT_FILE, menu);

    WbAction action;

    action = new FileConnectAction(this);
    action.addToMenu(menu);
    this.disconnectAction.addToMenu(menu);
    menu.addSeparator();
    this.createNewConnection.addToMenu(menu);
    this.disconnectTab.addToMenu(menu);
    menu.addSeparator();
    
    action = new FileSaveProfiles();
    action.addToMenu(menu);

    action = new FileNewWindowAction();
    action.addToMenu(menu);

    // now create the menus for the current tab
    List actions = aPanel.getActions();

    // Create the menus in the correct order
    menu = new WbMenu(ResourceMgr.getString(ResourceMgr.MNU_TXT_EDIT));
    menu.setName(ResourceMgr.MNU_TXT_EDIT);
    menu.setVisible(false);
    menuBar.add(menu);
    menus.put(ResourceMgr.MNU_TXT_EDIT, menu);

    menu = new WbMenu(ResourceMgr.getString(ResourceMgr.MNU_TXT_VIEW));
    menu.setName(ResourceMgr.MNU_TXT_VIEW);
    menu.setVisible(true);
    menuBar.add(menu);
    menus.put(ResourceMgr.MNU_TXT_VIEW, menu);

    int tabCount = this.sqlTab.getTabCount();
    for (int i=0; i < tabCount; i ++)
    {
      action = new SelectTabAction(this.sqlTab, i);
      menu.add(action.getMenuItem());
    }

    menu = new WbMenu(ResourceMgr.getString(ResourceMgr.MNU_TXT_DATA));
    menu.setName(ResourceMgr.MNU_TXT_DATA);
    menu.setVisible(false);
    menuBar.add(menu);
    menus.put(ResourceMgr.MNU_TXT_DATA, menu);

    menu = new WbMenu(ResourceMgr.getString(ResourceMgr.MNU_TXT_SQL));
    menu.setName(ResourceMgr.MNU_TXT_SQL);
    menu.setVisible(false);
    menuBar.add(menu);
    menus.put(ResourceMgr.MNU_TXT_SQL, menu);

    if (aPanel instanceof SqlPanel)
    {
      final WbMenu macroMenu = new WbMenu(ResourceMgr.getString(ResourceMgr.MNU_TXT_MACRO));
      macroMenu.setName(ResourceMgr.MNU_TXT_MACRO);
      macroMenu.setVisible(true);
      menuBar.add(macroMenu);
      menus.put(ResourceMgr.MNU_TXT_MACRO, macroMenu);
      buildMacroMenu(macroMenu);
    }

    menu = new WbMenu(ResourceMgr.getString(ResourceMgr.MNU_TXT_WORKSPACE));
    menu.setName(ResourceMgr.MNU_TXT_WORKSPACE);
    menuBar.add(menu);
    menus.put(ResourceMgr.MNU_TXT_WORKSPACE, menu);
    menu.add(this.saveWorkspaceAction);
    menu.add(this.saveAsWorkspaceAction);
    menu.add(this.loadWorkspaceAction);
    menu.addSeparator();
    menu.add(this.closeWorkspaceAction);
    menu.addSeparator();
    menu.add(this.assignWorkspaceAction);

    WbMenu submenu = null;
    String menuName = null;
    for (int i=0; i < actions.size(); i++)
    {
      submenu = null;
      action = null;
      menuName = null;
      Object entry = actions.get(i);
      boolean menuSep = false;
      if (entry instanceof WbAction)
      {
        action = (WbAction)actions.get(i);
        menuName = action.getMenuItemName();
        menuSep = action.getCreateMenuSeparator();
      }
      else if (entry instanceof WbMenu)
      {
        submenu = (WbMenu)entry;
        menuName = submenu.getParentMenuId();
        menuSep = submenu.getCreateMenuSeparator();
      }

      if (menuName == null)
      {
        LogMgr.logWarning(this, "Action " + action.getClass() + " does not define a main menu entry!");
        continue;
      }
      menu = menus.get(menuName);
      if (menu == null)
      {
        menu = new WbMenu(ResourceMgr.getString(menuName));
        menuBar.add(menu);
        menus.put(menuName, menu);
      }

      if (menuSep)
      {
        menu.addSeparator();
      }
      if (action != null)
      {
        action.addToMenu(menu);
      }
      else if (submenu != null)
      {
        menu.add(submenu);
      }
      menu.setVisible(true);
    }

    menu = menus.get(ResourceMgr.MNU_TXT_FILE);
    menu.addSeparator();
    menu.add(new ManageDriversAction());
    menu.addSeparator();

    action = new FileExitAction();
    menu.add(action.getMenuItem());

    menu = menus.get(workbench.resource.ResourceMgr.MNU_TXT_VIEW);
    AddTabAction add = new AddTabAction(this);
    menu.addSeparator();
    menu.add(add.getMenuItem());
    InsertTabAction insert = new InsertTabAction(this);
    menu.add(insert.getMenuItem());

    RemoveTabAction rem = new RemoveTabAction(this);
    menu.add(rem.getMenuItem());
    menu.addSeparator();
    ViewLineNumbers v = new ViewLineNumbers();
    v.addToMenu(menu);

    WbAction vTb = new ViewToolbarAction();
    vTb.addToMenu (menu);

    menuBar.add(this.buildToolsMenu());
    menuBar.add(this.buildHelpMenu());

    aPanel.addToToolbar(this.dbExplorerAction, true);
    return menuBar;
  }

  /**
   * Removes or makes the toolbar visible depending on
   * {@link Settings#getShowToolbar}. This method will
   * <i>validate</i> this' {@link #getContentPane content pane}
   * in case a change on the toolbar's visibility is performed.
   */
  private void updateToolbarVisibility()
  {
    boolean needInvalidate = false;
    final Container content = this.getContentPane();
    if (this.currentToolbar != null)
    {
      content.remove(this.currentToolbar);
      this.currentToolbar = null;
      needInvalidate = true;
    }
    
    if (Settings.getInstance().getShowToolbar())
    {
      final MainPanel curPanel = this.getCurrentPanel();
      if (curPanel != null)
      {
        this.currentToolbar = curPanel.getToolbar();
        content.add(this.currentToolbar, BorderLayout.NORTH);
        needInvalidate = true;
      }
    }
    if (needInvalidate)
    {
      content.validate();
    }
  }

  public void propertyChange(PropertyChangeEvent evt)
  {
    if (Settings.PROPERTY_SHOW_TOOLBAR.equals(evt.getPropertyName()))
    {
      this.setShowToolbar(Settings.getInstance().getShowToolbar());
    }
  }
  
  private void setShowToolbar(final boolean show)
  {
    final MainPanel current = this.getCurrentPanel();
    if (current != null)
    {
      this.updateToolbarVisibility();
    }
  }
  
  private void checkViewMenu(int index)
  {
    JMenu view = getViewMenu(index);
    int count = view.getItemCount();
    MainPanel p = getCurrentPanel();
    boolean isExplorer = (p instanceof DbExplorerPanel);
    for (int i = 0; i < count; i++)
    {
      JMenuItem item = view.getItem(i);
      if (item == null) continue;
      Action a = item.getAction();
      if (a instanceof RemoveTabAction)
      {
        a.setEnabled(isExplorer || canCloseTab());
      }
    }
  }
  
  private void checkMacroMenuForPanel(int index)
  {
    MainPanel p = this.getSqlPanel(index);
    try
    {
      JMenu macro = this.getMacroMenu(index);
      setItemStates(macro, p.isConnected());
    }
    catch (Exception e)
    {
      LogMgr.logError("MainWindow.checkMacroMenuForPanel()", "Error during macro update", e);
    }
  }
  
  private void setMacroMenuEnabled(boolean enabled)
  {
    int count = this.sqlTab.getTabCount();
    for (int i=0; i < count; i++)
    {
      JMenu macro = this.getMacroMenu(i);
      setItemStates(macro, enabled);
    }
  }

  private void setItemStates(JMenu menu, boolean enabled)
  {
    if (menu != null)
    {
      int itemCount = menu.getItemCount();
      for (int in=2; in < itemCount; in++)
      {
        JMenuItem item = menu.getItem(in);
        if (item != null) item.setEnabled(enabled);
      }
    }
  }
  
  public void macroListChanged()
  {
    int count = this.sqlTab.getTabCount();
    for (int i=0; i < count; i++)
    {
      JMenu macros = this.getMacroMenu(i);
      if (macros != null)
      {
        this.buildMacroMenu(macros);
        MainPanel p = this.getSqlPanel(i);
        this.setItemStates(macros, p.isConnected());
      }
    }
  }

  private void buildMacroMenu(JMenu macroMenu)
  {
    macroMenu.removeAll();
    this.createMacro.addToMenu(macroMenu);
    this.manageMacros.addToMenu(macroMenu);

    List<String> macros = MacroManager.getInstance().getMacroList();
    if (macros == null || macros.size() == 0) return;

    macroMenu.addSeparator();

    Collections.sort(macros);
    int count = macros.size();
    RunMacroAction run = null;
    int maxItems = Settings.getInstance().getMaxMacrosInMenu();
    for (int i=0; (i < count && i < maxItems); i++)
    {
      String name = macros.get(i);
      run = new RunMacroAction(this, name, i+1);
      run.addToMenu(macroMenu);
    }
  }

  public int getCurrentPanelIndex()
  {
    return this.sqlTab.getSelectedIndex();
  }

  public int getIndexForPanel(MainPanel panel)
  {
    int tabCount = this.sqlTab.getTabCount();
    for (int i=0; i < tabCount; i++)
    {
      MainPanel p = this.getSqlPanel(i);
      if (p.getId().equals(panel.getId())) return i;
    }
    return -1;
  }
  
  public String[] getPanelLabels()
  {
    int tabCount = this.sqlTab.getTabCount();

    int realCount = 0;
    for (int i=0; i < tabCount; i++)
    {
      MainPanel p = this.getSqlPanel(i);
      if (p instanceof SqlPanel)
      {
        realCount ++;
      }
    }

    String[] result = new String[realCount];
    for (int i=0; i < realCount; i++)
    {
      MainPanel p = this.getSqlPanel(i);
      if (i < 9)
      {
        result[i] = p.getTabTitle() + " &" + NumberStringCache.getNumberString(i+1);
      }
      else
      {
        result[i] = p.getTabTitle() + " " + NumberStringCache.getNumberString(i+1);
      }
    }
    return result;
  }

  public MainPanel getCurrentPanel()
  {
    int index = this.sqlTab.getSelectedIndex();
    if (index >-1) return this.getSqlPanel(index);
    else return null;
  }

  public SqlPanel getCurrentSqlPanel()
  {
    MainPanel p = this.getCurrentPanel();
    if (p instanceof SqlPanel)
    {
      return (SqlPanel)p;
    }
    return null;
  }

  public MainPanel getSqlPanel(int anIndex)
  {
    try
    {
      return (MainPanel)this.sqlTab.getComponentAt(anIndex);
    }
    catch (Exception e)
    {
      LogMgr.logDebug("MainWindow.getSqlPanel()", "Invalid index [" + anIndex + "] specified!", e);
      return null;
    }
  }

  public void selectTab(int anIndex)
  {
    this.sqlTab.setSelectedIndex(anIndex);
  }

  private boolean isConnectInProgress()
  {
    return this.connectInProgress;
  }
  
  private void clearConnectIsInProgress()
  {
    this.connectInProgress = false;
  }

  private void setConnectIsInProgress() 
  { 
    this.connectInProgress = true; 
  }

  private void checkConnectionForPanel(final MainPanel aPanel)
  {
    if (aPanel.isConnected()) return;
    if (this.isConnectInProgress()) return;

    try
    {
      if (this.currentProfile != null && this.currentProfile.getUseSeparateConnectionPerTab())
      {
        createNewConnectionForPanel(aPanel);
      }
      else if (this.currentConnection != null)
      {
        aPanel.setConnection(this.currentConnection);
      }
    }
    catch (Exception e)
    {
      LogMgr.logError("MainWindow.checkConnectionForPanel()", "Error when checking connection", e);
    }
  }

  public void disconnectCurrentPanel()
  {
    if (this.currentProfile == null) return;
    if (this.currentProfile.getUseSeparateConnectionPerTab()) return;
    
    final MainPanel p = this.getCurrentPanel();
    WbConnection con = p.getConnection();
    if (con == this.currentConnection) return;
    
    Thread t = new WbThread("Disconnect panel " + p.getId())
    {
      public void run()
      {
        disconnectPanel(p);
      }
    };
    t.start();
  }
  
  protected void disconnectPanel(final MainPanel panel)
  {
    if (this.isConnectInProgress()) return;
    setConnectIsInProgress();
    showDisconnectInfo();
    showStatusMessage(ResourceMgr.getString("MsgDisconnecting"));
    try
    {
      WbConnection old = panel.getConnection();
      panel.disconnect();
      ConnectionMgr.getInstance().disconnect(old);
      panel.setConnection(currentConnection);
      int index = this.getIndexForPanel(panel);
      sqlTab.setForegroundAt(index, null);
    }
    catch (Throwable e)
    {
      LogMgr.logError("MainWindow.connectPanel()", "Error when disconnecting panel " + panel.getId(), e);
      String error = ExceptionUtil.getDisplay(e);
      WbSwingUtilities.showErrorMessage(this, error);
    }
    finally
    {
      showStatusMessage("");
      closeConnectingInfo();
      clearConnectIsInProgress();
    }

    EventQueue.invokeLater(new Runnable()
    {
      public void run()
      {
        createNewConnection.checkState();
        disconnectTab.checkState();
      }
    });
  }
  
  public boolean canUseSeparateConnection()
  {
    if (this.currentProfile == null) return false;
    return !this.currentProfile.getUseSeparateConnectionPerTab();
  }
  
  public boolean usesSeparateConnection()
  {
    if (!canUseSeparateConnection()) return false;
    final MainPanel current = this.getCurrentPanel();
    WbConnection conn = current.getConnection() ;
    
    return (currentConnection != null && conn != this.currentConnection);
  }
  
  public void createNewConnectionForCurrentPanel()
  {
    final MainPanel panel = getCurrentPanel();
    createNewConnectionForPanel(panel);
    EventQueue.invokeLater(new Runnable()
    {
      public void run()
      {
        int index = getIndexForPanel(panel);
        sqlTab.setForegroundAt(index, Color.BLUE);
      }
    });
  }
  
  protected void createNewConnectionForPanel(final MainPanel aPanel)
  {
    if (this.isConnectInProgress()) return;
    if (this.connectThread != null) return;
    
    this.connectThread = new WbThread("Panel Connect " + aPanel.getId())
    {
      public void run()
      {
        connectPanel(aPanel);
      }
    };
    this.connectThread.start();
  }
  
  /**
   * Connect the given panel to the database. This will always 
   * create a new physical connection to the database.
   */
  protected void connectPanel(final MainPanel aPanel)
  {
    if (this.isConnectInProgress()) return;
    this.setConnectIsInProgress();
    this.showConnectingInfo();
    try
    {
      WbConnection conn = this.getConnectionForTab(aPanel, true);
      int index = this.getIndexForPanel(aPanel);
      this.tabConnected(aPanel, conn, index);
    }
    catch (Throwable e)
    {
      LogMgr.logError("MainWindow.connectPanel()", "Error when connecting panel " + aPanel.getId(), e);
      showStatusMessage("");
      String error = ExceptionUtil.getDisplay(e);
      String msg = ResourceMgr.getFormattedString("ErrConnectFailed", error.trim());
      WbSwingUtilities.showErrorMessage(this, msg);
    }
    finally
    {
      closeConnectingInfo();
      clearConnectIsInProgress();
      this.connectThread = null;
    }
  }

  public void waitForConnection()
  {
    if (this.connectThread != null)
    {
      try
      {
        this.connectThread.join();
      }
      catch (Exception e)
      {
        e.printStackTrace();
      }
    }
  }
  
  private void tabConnected(final MainPanel panel, WbConnection conn, final int anIndex)
  {
    this.closeConnectingInfo();
    panel.setConnection(conn);
    
    WbSwingUtilities.waitForEmptyQueue();
    WbSwingUtilities.invoke(new Runnable()
    {
      public void run()
      {
        updateGuiForTab(anIndex);
      }
    });
  }

  protected void updateGuiForTab(int anIndex)
  {
    if (anIndex < 0) return;

    Container content = this.getContentPane();
    final MainPanel current = this.getSqlPanel(anIndex);
    if (current == null) return;

    JMenuBar menu = this.panelMenus.get(anIndex);
    if (menu == null) return;

    this.setJMenuBar(menu);

    this.updateToolbarVisibility();
  
    this.createNewConnection.checkState();
    this.disconnectTab.checkState();
    
    this.checkMacroMenuForPanel(anIndex);
    this.checkViewMenu(anIndex);
    SwingUtilities.invokeLater(new Runnable()
    {
      public void run()
      {
        current.panelSelected();
      }
    });
  }

  protected void tabSelected(final int index)
  {
    // Make sure this is executed on the EDT
    WbSwingUtilities.invoke(new Runnable()
    {
      public void run()
      {
        updateCurrentTab(index);
      }
    });
  }

  protected void updateCurrentTab(int index)
  {
    MainPanel current = getSqlPanel(index);
    if (current == null) return;
    this.updateGuiForTab(index);
    this.updateAddMacroAction();
    this.updateWindowTitle();
    this.checkConnectionForPanel(current);
  }
  
  protected void updateAddMacroAction()
  {
    SqlPanel sql = this.getCurrentSqlPanel();
    if (sql != null)
    {
      this.createMacro.setClient(sql.getEditor());
    }
  }

  public void restoreState()
  {
    String state = Settings.getInstance().getProperty(this.getClass().getName() + ".state", "0");
    int i = 0;
    try { i = Integer.parseInt(state); } catch (Exception e) { i = 0; }
    if (i == MAXIMIZED_BOTH)
    {
      this.setExtendedState(i);
    }
  }

  public void restoreSettings()
  {
    Settings s = Settings.getInstance();

    if (!s.restoreWindowSize(this))
    {
      this.setSize(950,750);
    }

    if (!s.restoreWindowPosition(this))
    {
      WbSwingUtilities.center(this, null);
    }
  }

  public void saveSettings()
  {
    Settings sett = Settings.getInstance();
    int state = this.getExtendedState();
    sett.setProperty(this.getClass().getName() + ".state", state);

    if (state != MAXIMIZED_BOTH)
    {
      sett.storeWindowPosition(this);
      sett.storeWindowSize(this);
    }
  }

  public void windowOpened(WindowEvent windowEvent)
  {
  }

  public void windowClosed(WindowEvent e)
  {
  }

  public void windowDeiconified(WindowEvent windowEvent)
  {
  }

  public void windowClosing(WindowEvent windowEvent)
  {
    WbManager.getInstance().windowClosing(this);
  }

  public void windowDeactivated(WindowEvent windowEvent)
  {
  }

  public void windowActivated(WindowEvent windowEvent)
  {
    // When switching between Applications (using Alt-Tab in Windows)
    // sometimes the main menu is selected (as if the Alt key was pressed
    // once to activate the menu). This is trying to workaround this bug
    // but does not really work in all cases. As this happens with other Java
    // applications as well, I think this is a JDK bug.
    
    // If the "oppositeWindow is not null, then we have a focus switch inside
    // our application, so we don't need to do anything
//    if (windowEvent.getOppositeWindow() != null) return;
//    
//    EventQueue.invokeLater(new Runnable()
//    {
//      public void run()
//      {
//        JMenu menu = null;
//        JMenuBar bar = null;
//    
//        int index = getCurrentPanelIndex();
//        if (panelMenus != null && index > -1)
//        {
//          bar = panelMenus.get(index);
//          if (bar != null)
//          {
//            try
//            {
//              menu = bar.getMenu(0);
//            }
//            catch (Throwable th)
//            {
//              menu = null;
//            }
//          }
//        }
//        try { if (menu != null) menu.setSelected(false); } catch (Throwable th) {}
//        try { if (bar != null) bar.setSelected(null); } catch (Throwable th) {}
//      }
//    });
  }

  public void windowIconified(WindowEvent windowEvent)
  {
  }

  /**
   *  Display a message in the status bar
   */
  public void showStatusMessage(final String aMsg)
  {
    final MainPanel current = this.getCurrentPanel();
    if (current == null) return;
    
    WbSwingUtilities.invoke(new Runnable()
    {
      public void run()
      {
        if (StringUtil.isEmptyString(aMsg))
          current.clearStatusMessage();
        else
          current.showStatusMessage(aMsg);
      }
    });
  }

  public void showLogMessage(String aMsg)
  {
    MainPanel current = this.getCurrentPanel();
    if (current != null) current.showLogMessage(aMsg);
  }

  public void connectBegin(final ConnectionProfile aProfile)
  {
    if (this.currentWorkspaceFile != null)
    {
      this.saveWorkspace(this.currentWorkspaceFile, true);
    }
    disconnect(false, false, false);

    // it is important to set this flag, otherwise
    // loading the workspace will already trigger a
    // panel switch which might cause a connect
    // to the current profile before the ConnectionSelector
    // has actually finished.
    // this has to be set AFTER calling disconnect(), because
    // disconnect respects this flag and does nothing...
    this.setConnectIsInProgress();
    
    this.currentProfile = aProfile;
    
    showStatusMessage(ResourceMgr.getString("MsgLoadingWorkspace"));
    loadWorkspaceForProfile(this.currentProfile);
    
    Settings.getInstance().setLastConnection(this.currentProfile);
    showStatusMessage(ResourceMgr.getString("MsgConnecting"));
  }

  private String getConnectionIdForPanel(MainPanel p)
  {
    return "Wb" + NumberStringCache.getNumberString(windowId) + "-" + p.getId();
  }

  /**
   * Return the internal ID that should be used when connecting 
   * to the given connection profile
   * @return an id specific for the current tab or a "global" id the connection
   *         is shared between all tabs of this window
   */
  public String getConnectionId(ConnectionProfile aProfile)
  {
    if (aProfile != null && aProfile.getUseSeparateConnectionPerTab())
    {
      return getConnectionIdForPanel(this.getCurrentPanel());
    }
    else
    {
      return "WbWin-" + NumberStringCache.getNumberString(windowId);
    }
  }

  private ConnectionSelector getSelector()
  {
    if (this.connectionSelector == null)
    {
      this.connectionSelector = new ConnectionSelector(this, this);
    }
    return this.connectionSelector;
  }
  
  public void connectTo(ConnectionProfile profile, boolean showDialog)
  {
    getSelector().connectTo(profile, showDialog);
  }

  /**
   *  Call-back function which gets executed on the AWT thread after
   *  the initial connection has been completed
   */
  public void connected(WbConnection conn)
  {
    if (this.currentProfile.getUseSeparateConnectionPerTab())
    {
      this.getCurrentPanel().setConnection(conn);
    }
    else
    {
      this.setConnection(conn);
    }
    this.setMacroMenuEnabled(true);
    this.updateWindowTitle();

    this.dbExplorerAction.setEnabled(true);
    this.newDbExplorerPanel.setEnabled(true);
    this.newDbExplorerWindow.setEnabled(true);

    this.disconnectAction.setEnabled(true);
    this.createNewConnection.checkState();
    this.disconnectTab.checkState();
    this.getCurrentPanel().clearLog();
    this.getCurrentPanel().showResultPanel();

    String warn = conn.getWarnings();
    if (warn != null)
    {
      this.getCurrentPanel().showLogMessage(warn);
    }
    selectCurrentEditor();
  }

  public void connectFailed(String error)
  {
    disconnected();
    this.updateWindowTitle();
    
    try
    {
      String msg = ResourceMgr.getFormattedString("ErrConnectFailed", error);
      WbSwingUtilities.showErrorMessage(this, msg);
    }
    catch (Throwable th)
    {
      LogMgr.logError("MainWindow.connectFailed()", "Could not display connection error!", th);
      WbSwingUtilities.showErrorMessage(this, error);
    }
  }

  public void connectCancelled()
  {
    if (this.exitOnCancel)
    {
      WbManager.getInstance().windowClosing(this);
    }
  }

  public void connectEnded()
  {
    for (int i=0; i < sqlTab.getTabCount(); i++)
    {
      MainPanel sql = getSqlPanel(i);
      sql.clearStatusMessage();
    }
    this.clearConnectIsInProgress();
  }

  private static final int CREATE_WORKSPACE = 0;
  private static final int LOAD_OTHER_WORKSPACE = 1;
  private static final int IGNORE_MISSING_WORKSPACE = 2;

  private int checkNonExistingWorkspace()
  {
    String[] options = new String[] { ResourceMgr.getString("LblCreateWorkspace"), ResourceMgr.getString("LblLoadWorkspace"), ResourceMgr.getString("LblIgnore")};
    JOptionPane ignorePane = new JOptionPane(ResourceMgr.getString("MsgProfileWorkspaceNotFound"), JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options);
    JDialog dialog = ignorePane.createDialog(this, ResourceMgr.TXT_PRODUCT_NAME);
    try
    {
      dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
      dialog.setResizable(true);
      dialog.pack();
      dialog.setVisible(true);
    }
    finally
    {
      dialog.dispose();
    }
    Object result = ignorePane.getValue();
    if (result == null) return CREATE_WORKSPACE;
    else if (result.equals(options[0])) return CREATE_WORKSPACE;
    else if (result.equals(options[1])) return LOAD_OTHER_WORKSPACE;
    else return IGNORE_MISSING_WORKSPACE;
  }

  private void handleWorkspaceLoadError(Throwable e, String realFilename)
  {
    String error = ExceptionUtil.getDisplay(e);
    String msg = StringUtil.replace(ResourceMgr.getString("ErrLoadingWorkspace"), "%error%", error);
    if (e instanceof OutOfMemoryError)
    {
      msg = ResourceMgr.getString("MsgOutOfMemoryError");
    }
    boolean create = WbSwingUtilities.getYesNo(this, msg);
    if (create)
    {
      this.currentWorkspaceFile = realFilename;
    }
    else
    {
      this.currentWorkspaceFile = null;
    }
  }

  private void loadDefaultWorkspace()
  {
    if (!this.loadWorkspace(DEFAULT_WORKSPACE))
    {
      resetWorkspace();
      this.currentWorkspaceFile = DEFAULT_WORKSPACE;
    }
  }

  private void resetWorkspace()
  {
    this.closeWorkspace(false);
    this.resetTabTitles();
  }
  
  private boolean resultForWorkspaceClose;
  
  public boolean loadWorkspace(String filename)
  {
    if (filename == null) return false;
    final String realFilename = FileDialogUtil.replaceConfigDir(filename);

    File f = new File(realFilename);
     if (!f.exists())
    {
      // if the file does not exist, set all variables as if it did
      // thus the file will be created automatically.
      this.resetWorkspace();
      this.currentWorkspaceFile = realFilename;
      this.updateWindowTitle();
      this.checkWorkspaceActions();
      return true;
    }

    this.currentWorkspaceFile = null;
    this.resultForWorkspaceClose = false;
    
    WbSwingUtilities.invoke(new Runnable()
    {
      public void run()
      {
        WbWorkspace w  = null;
        try
        {
          //removeAllPanels();
          
          w = new WbWorkspace(realFilename, false);
          int entryCount = w.getEntryCount();
          if (entryCount == 0) entryCount = 1;
          
          adjustTabCount(entryCount);

          int explorerCount = w.getDbExplorerVisibleCount();
          
          adjustDbExplorerCount(explorerCount);

          int count = sqlTab.getTabCount();
          for (int i=0; i < count; i++)
          {
            MainPanel p = getSqlPanel(i);
            p.readFromWorkspace(w,i);
            if (p instanceof SqlPanel)
            {
              SqlPanel sql = (SqlPanel)p;
              updateViewMenu(i, getPlainTabTitle(i));
            }
          }
          currentWorkspaceFile = realFilename;

          int newIndex = w.getSelectedTab();
          if (newIndex < sqlTab.getTabCount())
          {
            // the stateChanged event will be ignored as we
            // have the repainting for the tab suspended
            sqlTab.setSelectedIndex(newIndex);
          }
          resultForWorkspaceClose = true;
        }
        catch (Throwable e)
        {
          LogMgr.logWarning("MainWindow.loadWorkspace()", "Error loading workspace  " + realFilename, e);
          handleWorkspaceLoadError(e, realFilename);
        }
        finally
        {
          try { w.close(); } catch (Throwable th) {}
        }

        validate();
        updateWindowTitle();
        checkWorkspaceActions();
        updateAddMacroAction();
      }
    });
    
    return resultForWorkspaceClose;
  }

  private void loadWorkspaceForProfile(ConnectionProfile aProfile)
  {
    String realFilename = null;
    try
    {
      String workspaceFilename = aProfile.getWorkspaceFile();
      if (workspaceFilename != null && !workspaceFilename.endsWith(".wksp")) workspaceFilename += ".wksp";
      
      realFilename = FileDialogUtil.replaceConfigDir(workspaceFilename);
      if (realFilename == null) realFilename = "";
      
      File f = new File(realFilename);
      if (realFilename.length() > 0 && !f.exists())
      {
        int action = this.checkNonExistingWorkspace();
        if (action == LOAD_OTHER_WORKSPACE)
        {
          FileDialogUtil util = new FileDialogUtil();
          workspaceFilename = util.getWorkspaceFilename(this, false, true);
          aProfile.setWorkspaceFile(workspaceFilename);
        }
        else if (action == IGNORE_MISSING_WORKSPACE)
        {
          workspaceFilename = null;
          aProfile.setWorkspaceFile(null);
        }
        else
        {
          // start with an empty workspace
          // and create a new workspace file.
          if (!f.isAbsolute())
          {
            // if no directory was given, assume the configuration directory
            workspaceFilename = FileDialogUtil.CONFIG_DIR_KEY + "/" + workspaceFilename;
          }
          resetWorkspace();
        }
      }

      if (workspaceFilename != null && workspaceFilename.trim().length() > 0)
      {
        // loadWorkspace will replace the %ConfigDir% placeholder,
        // so we need to pass the original filename
        this.isProfileWorkspace = true;
        this.loadWorkspace(workspaceFilename);
      }
      else
      {
        this.loadDefaultWorkspace();
      }
    }
    catch (Throwable e)
    {
      LogMgr.logError("MainWindow.loadWorkspaceForProfile()", "Error reading workspace " + realFilename, e);
      this.handleWorkspaceLoadError(e, realFilename);
    }
  }

  public void disconnect(final boolean background, final boolean closeWorkspace, final boolean saveWorkspace)
  {
    if (this.isConnectInProgress()) return;
    this.setConnectIsInProgress();

    Runnable run = new Runnable()
    {
      public void run()
      {
        if (saveWorkspace) saveWorkspace(false);
        if (background) showDisconnectInfo();
        doDisconnect();
        if (closeWorkspace) closeWorkspace(background);
        if (background) closeConnectingInfo();
      }
    };
    
    if (background)
    {
      Thread t = new WbThread(run, "MainWindow Disconnect");
      t.start();
    }
    else
    {
      WbSwingUtilities.invoke(run);
    }
  }

  /**
   *  This does the real disconnect action.
   */
  private void doDisconnect()
  {
    try
    {
      ConnectionMgr mgr = ConnectionMgr.getInstance();
      WbConnection conn = null;

      for (int i=0; i < this.sqlTab.getTabCount(); i++)
      {
        final MainPanel sql = (MainPanel)this.sqlTab.getComponentAt(i);
        if (sql instanceof SqlPanel)
        {
          ((SqlPanel)sql).abortExecution();
        }
        conn = sql.getConnection();
        sql.disconnect();
        if (conn != null && !conn.isClosed())
        {
          showStatusMessage(ResourceMgr.getString("MsgDisconnecting"));
          mgr.disconnect(conn);
        }
      }
      this.closeExplorerWindows(true);
    }
    finally
    {
      // this must be called on the AWT thread
      // and it must be called synchronously!
      WbSwingUtilities.invoke(new Runnable()
      {
        public void run()
        {
          disconnected();
        }
      });
    }
  }

  private void disconnected()
  {
    this.currentProfile = null;
    this.currentConnection = null;
    this.closeWorkspace(false);
    this.setMacroMenuEnabled(false);
    this.updateWindowTitle();
    this.disconnectAction.setEnabled(false);
    this.createNewConnection.checkState();
    this.disconnectTab.checkState();
    this.dbExplorerAction.setEnabled(false);
    this.newDbExplorerPanel.setEnabled(false);
    this.newDbExplorerWindow.setEnabled(false);
    this.showStatusMessage("");
    for (int i=0; i < sqlTab.getTabCount(); i++)
    {
      sqlTab.setForegroundAt(i, null);
    }
    this.clearConnectIsInProgress();
  }


  public boolean abortAll()
  {
    boolean success = true;
    try
    {
      for (int i=0; i < this.sqlTab.getTabCount(); i++)
      {
        MainPanel sql = (MainPanel)this.sqlTab.getComponentAt(i);
        if (sql instanceof SqlPanel)
        {
          SqlPanel sp = (SqlPanel)sql;
          success = success && sp.abortExecution();
        }
      }
    }
    catch (Exception e)
    {
      LogMgr.logWarning("MainWindow.abortAll()", "Error stopping execution",e);
      success = false;
    }
    return success;
  }

  public void selectCurrentEditor()
  {
    MainPanel p = this.getCurrentPanel();
    if (p instanceof SqlPanel)
    {
      SqlPanel sql = (SqlPanel)p;
      sql.selectEditor();
    }
  }

  protected String getCurrentEditorFile()
  {
    String filename = null;

    MainPanel p  = this.getCurrentPanel();
    if (p instanceof SqlPanel)
    {
      SqlPanel sql = (SqlPanel)p;
      filename = sql.getCurrentFileName();
    }
    return filename;
  }
  
  protected void updateWindowTitle()
  {
    WbSwingUtilities.invoke(new Runnable()
    {
      public void run()
      {
        WindowTitleBuilder titleBuilder = new WindowTitleBuilder();
        String title = titleBuilder.getWindowTitle(currentProfile, currentWorkspaceFile, getCurrentEditorFile());
        setTitle(title);
        jobIndicator.baseTitleChanged();
      }
    });
  }

  protected void closeConnectingInfo()
  {
    getSelector().closeConnectingInfo();
  }

  protected void showDisconnectInfo()
  {
    getSelector().showDisconnectInfo();
  }

  /** Display a little PopupWindow to tell the user that the
   *  workbench is currently connecting to the DB
   */
  protected void showConnectingInfo()
  {
    getSelector().showConnectingInfo();
  }

  private void setConnection(WbConnection con)
  {
    int count = this.sqlTab.getTabCount();
    for (int i=0; i < count; i++)
    {
      MainPanel sql = (MainPanel)this.sqlTab.getComponentAt(i);
      sql.setConnection(con);
    }
    this.currentConnection = con;
    if (this.currentProfile == null) this.currentProfile = con.getProfile();
  }

  public void selectConnection()
  {
    selectConnection(false);
  }
  
  private boolean exitOnCancel = false;
  
  public void selectConnection(boolean exit)
  {
    this.exitOnCancel = exit;
    getSelector().selectConnection();
  }

  public JMenu getMacroMenu(int panelIndex)
  {
    JMenu menu = this.getMenu(ResourceMgr.MNU_TXT_MACRO, panelIndex);
    return menu;
  }

  public JMenu getViewMenu(int panelIndex)
  {
    return this.getMenu(ResourceMgr.MNU_TXT_VIEW, panelIndex);
  }

  public JMenu getMenu(String aName, int panelIndex)
  {
    if (panelIndex < 0 || panelIndex >= this.panelMenus.size()) return null;
    if (aName == null) return null;
    JMenuBar menubar = this.panelMenus.get(panelIndex);
    int count = menubar.getMenuCount();
    for (int k=0; k < count; k++)
    {
      JMenu item = menubar.getMenu(k);
      if (item == null) continue;
      if (aName.equals(item.getName())) return item;
    }
    return null;
  }

  private void updateViewMenu(int sqlTabIndex, String aName)
  {
    int panelCount = this.panelMenus.size();
    if (aName == null) aName = ResourceMgr.getDefaultTabLabel();
    for (int i=0; i < panelCount; i++)
    {
      JMenu view = this.getViewMenu(i);

      int count = view.getItemCount();
      for (int k=0; k < count; k++)
      {
        JMenuItem item = view.getItem(k);
        if (item == null) continue;
        Action ac = item.getAction();
        if (ac == null) continue;

        if (ac instanceof SelectTabAction)
        {
          SelectTabAction a = (SelectTabAction)ac;
          if (a.getIndex() == sqlTabIndex)
          {
            a.setMenuText(aName);
            break;
          }
        }
      }
      WbSwingUtilities.repaintNow(view);
    }
  }

  /**
   *  Add the approriate menu item to select a given tab
   *  to the View menu.
   */
  public void addToViewMenu(SelectTabAction anAction)
  {
    int panelCount = this.panelMenus.size();
    int lastActionIndex = -1;

    SelectTabAction lastAction = null;

    for (int i=0; i < panelCount; i++)
    {
      JMenu view = this.getViewMenu(i);

      // insert the item at the correct index
      // (if it is a SelectTabAction)
      // otherwise insert it after the last SelectTabAction
      int count = view.getItemCount();
      int inserted = -1;
      for (int k=0; k < count; k++)
      {
        JMenuItem item = view.getItem(k);
        if (item == null) continue;
        Action ac = item.getAction();
        if (ac == null) continue;
        if (!(ac instanceof SelectTabAction))
        {
          break;
        }
        SelectTabAction a = (SelectTabAction)ac;
        lastAction = a;
        lastActionIndex = k;

        if (a.getIndex() > anAction.getIndex())
        {
          view.insert(anAction.getMenuItem(), k);
          inserted = k;
          break;
        }
      }

      if (inserted == -1)
      {
        if (lastActionIndex == -1)
        {
          // no index found which is greater or equal than the new one
          // so add it to the end
          if (!(view.getItem(count -1).getAction() instanceof SelectTabAction))
          view.addSeparator();

          view.add(anAction.getMenuItem());
        }
        else if (lastAction != null && lastAction.getIndex() != anAction.getIndex())
        {
          // we found at least one SelectTabAction, so we'll
          // insert the new one right behind the last one.
          // (there might be other items in the view menu!)

          view.insert(anAction.getMenuItem(), lastActionIndex + 1);
        }
      }
      else
      {
        // renumber the shortcuts for the remaining actions
        int newIndex = anAction.getIndex() + 1;
        for (int k=inserted + 1; k < panelCount; k++)
        {
          SelectTabAction a = (SelectTabAction)view.getItem(k).getAction();
          a.setNewIndex(newIndex);
          newIndex ++;
        }
      }
    }
  }
  
  private WbConnection getConnectionForTab(MainPanel aPanel, boolean returnNew)
    throws Exception
  {
    if (this.currentConnection != null && !returnNew) return this.currentConnection;
    String id = this.getConnectionIdForPanel(aPanel);
    
    aPanel.showStatusMessage(ResourceMgr.getString("MsgConnectingTo") + " " + this.currentProfile.getName() + " ...");
    ConnectionMgr mgr = ConnectionMgr.getInstance();
    WbConnection conn = null;
    try
    {
      conn = mgr.getConnection(this.currentProfile, id);
    }
    finally
    {
      aPanel.clearStatusMessage();
    }
    return conn;
  }

  public void addDbExplorerTab(DbExplorerPanel explorer)
  {
    JMenuBar dbmenu = this.createMenuForPanel(explorer);

    this.sqlTab.add(explorer);
    explorer.setTabTitle(this.sqlTab, this.sqlTab.getTabCount() - 1);

    SelectTabAction action = new SelectTabAction(this.sqlTab, this.sqlTab.getTabCount() - 1);
    action.setMenuText(explorer.getTabTitle());
    this.panelMenus.add(dbmenu);
    this.addToViewMenu(action);
  }

  /**
   * Displays the DbExplorer. Either in a separate tab,
   * or as a new window. If an explorer window is already open
   * that instance will be re-used
   */
  public void showDbExplorer()
  {
    boolean useTab = Settings.getInstance().getShowDbExplorerInMainWindow();
    if (useTab)
    {
      int index = this.findFirstExplorerTab();
      if (index > -1)
      {
        this.selectTab(index);
      }
      else
      {
        this.newDbExplorerPanel(true);
      }
    }
    else
    {
      if (this.explorerWindows.size() > 0)
      {
        ToolWindow w = this.explorerWindows.get(0);
        w.activate();
      }
      else
      {
        this.newDbExplorerWindow();
      }
    }
  }

  /**
   * Returns the index of the las SQL Panel
   */
  public int getLastSqlPanelIndex()
  {
    int explorer = findFirstExplorerTab();
    if (explorer == -1)
      return this.sqlTab.getTabCount() - 1;
    else
      return explorer - 1;
  }

  /**
   *  Returns the index of the first explorer tab
   */
  private int findFirstExplorerTab()
  {
    int count = this.sqlTab.getTabCount();
    for (int i=0; i < count; i++)
    {
      Component c = this.sqlTab.getComponentAt(i);
      if (c instanceof DbExplorerPanel)
      {
        return i;
      }
    }
    return -1;
  }

  public void closeExplorerWindows(boolean doDisconnect)
  {
    for (ToolWindow w : explorerWindows)
    {
      if (doDisconnect)
      {
        WbConnection conn = w.getConnection();
        if (conn != this.currentConnection)
        {
          ConnectionMgr.getInstance().disconnect(conn);
        }
        w.closeWindow();
      }
    }
  }

  protected void removeAllPanels()
  {
    try
    {
      while (sqlTab.getTabCount() > 1)
      {
        removeTab(1);
      }
      MainPanel p = getSqlPanel(0);
      p.reset();
    }
    catch (Exception e)
    {
      LogMgr.logError("MainWindow.removeAllPanels()", "Error when removing all panels", e);
    }
  }
  
  public void newDbExplorerWindow()
  {
    DbExplorerPanel explorer = new DbExplorerPanel(this);
    explorer.restoreSettings();
    DbExplorerWindow w = explorer.openWindow(this.currentProfile.getName());
    if (this.currentProfile.getUseSeparateConnectionPerTab() || this.currentConnection == null)
    {
      explorer.connect(this.currentProfile);
    }
    else
    {
      explorer.setConnection(this.currentConnection);
    }
    this.explorerWindows.add(w);
  }

  public void explorerWindowClosed(DbExplorerWindow w)
  {
    this.explorerWindows.remove(w);
  }

  public void newDbExplorerPanel(boolean select)
  {
    DbExplorerPanel explorer = new DbExplorerPanel(this);
    explorer.restoreSettings();
    this.addDbExplorerTab(explorer);
    if (select)
    {
      // Switching to the new tab will initiate the connection if necessary
      this.sqlTab.setSelectedIndex(this.sqlTab.getTabCount() - 1);
    }
  }

  public ConnectionProfile getCurrentProfile() 
  { 
    return this.currentProfile; 
  }

  public JMenu buildHelpMenu()
  {
    JMenu result = new WbMenu(ResourceMgr.getString(ResourceMgr.MNU_TXT_HELP));
    result.setName(ResourceMgr.MNU_TXT_HELP);
    new ShowHelpAction().addToMenu(result);
    new ShowManualAction().addToMenu(result);
    result.addSeparator();

    result.add(WhatsNewAction.getInstance());
    new VersionCheckAction().addToMenu(result);
    new AboutAction().addToMenu(result);
    
    return result;
  }

  /**
   * Create the tools menu for a panel menu. This will be called
   * for each panel that gets added to the main window.
   * Actions that are singletons (like the db explorer stuff)
   * should not be created here
   */
  public JMenu buildToolsMenu()
  {
    JMenu result = new WbMenu(ResourceMgr.getString(ResourceMgr.MNU_TXT_TOOLS));
    result.setName(ResourceMgr.MNU_TXT_TOOLS);

    result.add(this.dbExplorerAction);
    result.add(this.newDbExplorerPanel);
    result.add(this.newDbExplorerWindow);
    result.addSeparator();

    result.add(new DataPumperAction(this));

    result.addSeparator();

    new OptionsDialogAction().addToMenu(result);
    new ConfigureShortcutsAction().addToMenu(result);

    return result;
  }

  private boolean checkMakeProfileWorkspace()
  {
    boolean assigned = false;
    boolean saveIt = WbSwingUtilities.getYesNo(this, ResourceMgr.getString("MsgAttachWorkspaceToProfile"));
    if (saveIt)
    {
      this.assignWorkspace();
      assigned = true;
    }
    return assigned;
  }

  private int getNumberOfExplorerPanels()
  {
    int count = 0;
    int num = this.sqlTab.getTabCount();
    for (int i=0; i < num; i++)
    {
      Component c = this.sqlTab.getComponentAt(i);
      if (c instanceof DbExplorerPanel) count++;
    }
    return count;
  }

  private void adjustDbExplorerCount(int newCount)
  {
    int count = this.getNumberOfExplorerPanels();
    if (count == newCount) return;
    if (newCount > count)
    {
      for (int i=0; i < (newCount - count); i++)
      {
        newDbExplorerPanel(false);
      }
    }
    else if (newCount < count)
    {
      for (int i=0; i < (count - newCount); i++)
      {
        this.removeLastTab(true);
      }
    }
  }
  /**
   *  Creates or removes SQL tabs until newCount tabs are displayed
   */
  private void adjustTabCount(int newCount)
  {
    int tabCount = this.sqlTab.getTabCount() - getNumberOfExplorerPanels();

    if (newCount > tabCount)
    {
      for (int i=0; i < (newCount - tabCount); i++)
      {
        this.addTab(false, false);
      }
    }
    else if (newCount < tabCount)
    {
      for (int i=0; i < (tabCount - newCount); i++)
      {
        this.removeLastTab(newCount == 1);
      }
    }
  }

  /**
   *  Sets the default title for all tab titles
   */
  private void resetTabTitles()
  {
    String defaultTitle = ResourceMgr.getDefaultTabLabel();
    int count = this.sqlTab.getTabCount();
    for (int i=0; i < count; i++)
    {
      MainPanel p = this.getSqlPanel(i);
      if (p == null) continue;
      if (p instanceof SqlPanel)
      {
        SqlPanel sql = (SqlPanel)p;
        sql.closeFile(true, false);
        this.setTabTitle(i, defaultTitle);
      }
    }
  }

  /**
   *  Returns true if at least one of the SQL panels is currently
   *  executing a SQL statement.
   *  This method calls isBusy() for each tab.
   */
  public boolean isBusy()
  {
    int count = this.sqlTab.getTabCount();
    for (int i=0; i < count; i++)
    {
      MainPanel p = this.getSqlPanel(i);
      if (p.isBusy()) return true;
    }
    return false;
  }

  public String getCurrentWorkspaceFile()
  {
    return this.currentWorkspaceFile;
  }

  public void loadWorkspace()
  {
    FileDialogUtil dialog = new FileDialogUtil();
    String filename = dialog.getWorkspaceFilename(this, false, true);
    if (filename == null) return;
    if (this.loadWorkspace(filename))
    {
      this.isProfileWorkspace = this.checkMakeProfileWorkspace();
    }
    else
    {
      this.isProfileWorkspace = false;
    }
  }

  public void closeWorkspace()
  {
    closeWorkspace(true);
  }
  
  /**
   *  Closes the current workspace.
   *  The tab count is reset to 1, the SQL history for the tab will be emptied
   *  and the workspace filename will be "forgotten".
   */
  public void closeWorkspace(boolean checkUnsaved)
  {
    this.currentWorkspaceFile = null;
    this.isProfileWorkspace = false;

    if (checkUnsaved)
    {
      int count = this.sqlTab.getTabCount();
      for (int i=0; i < count; i++)
      {
        MainPanel p = getSqlPanel(i);
        if (p.canCloseTab()) return;
      }
    }

    WbSwingUtilities.invoke(new Runnable()
    {
      public void run()
      {
        try
        {
          removeAllPanels();
        }
        catch (Exception e)
        {
          LogMgr.logError("MainWindow.closeWorkspace()", "Error when resetting workspace", e);
        }
        updateWindowTitle();
        checkWorkspaceActions();
      }
    });
  }

  /**
   *  This will assign the current workspace name to the current profile.
   */
  public void assignWorkspace()
  {
    if (this.currentWorkspaceFile == null) return;
    if (this.currentProfile == null) return;
    FileDialogUtil util = new FileDialogUtil();
    String filename = util.putConfigDirKey(this.currentWorkspaceFile);
    this.currentProfile.setWorkspaceFile(filename);
    this.isProfileWorkspace = true;
    this.updateWindowTitle();
  }

  public boolean saveWorkspace()
  {
    return saveWorkspace(true);
  }
  /**
   *  Save the currently loaded workspace
   */
  public boolean saveWorkspace(boolean checkUnsaved)
  {
    if (this.currentWorkspaceFile != null)
    {
      return this.saveWorkspace(this.currentWorkspaceFile, checkUnsaved);
    }
    return true;
  }

  /**
   *  Saves the current SQL history to a workspace with the given filename
   *  If filename == null, a SaveAs dialog will be displayed.
   *  If the workspace is saved with a new name (filename == null) the user
   *  will be asked if the workspace should be assigned to the current profile
   */
  public boolean saveWorkspace(String filename, boolean checkUnsaved)
  {
    WbWorkspace w = null;
    boolean interactive = false;

    if (filename == null)
    {
      interactive = true;
      FileDialogUtil util = new FileDialogUtil();
      filename = util.getWorkspaceFilename(this, true);
      if (filename == null) return true;
    }

    String realFilename = FileDialogUtil.replaceConfigDir(filename);

    // Make a backup of the existing workspace 
    // if saving of the workspace fails, the backup
    // will be renamed back to the original name
    // otherwise it will be deleted if no backups should be made
    File f = new File(realFilename);
    File bck = new File(realFilename + ".bck");
    try
    {
      bck.delete();
      f.renameTo(bck);
    }
    catch (Exception e)
    {
      LogMgr.logWarning("MainWindow.saveWorkspace()", "Error when creating backup file!", e);
    }


    try
    {
      int count = this.sqlTab.getTabCount();

      if (checkUnsaved)
      {
        for (int i=0; i < count; i++)
        {
          MainPanel p = (MainPanel)this.sqlTab.getComponentAt(i);
          if (!p.canCloseTab()) return false;
        }
      }
      w = new WbWorkspace(realFilename, true);
      int selected = this.sqlTab.getSelectedIndex();
      w.setSelectedTab(selected);
      for (int i=0; i < count; i++)
      {
        MainPanel p = getSqlPanel(i);
        p.saveToWorkspace(w,i);
      }
      if (WbManager.getInstance().outOfMemoryOcurred())
      {
        // sometimes when an OoM occurred, saving of the workspace
        // succeeds but the ZIP file is not written correctly. 
        // This tries to prevent the old file from beeing overwritten, just in case...
        bck.renameTo(new File(realFilename + ".saved"));
      }
      else if (!Settings.getInstance().getCreateWorkspaceBackup())
      {
        bck.delete();
      }
    }
    catch (Throwable e)
    {
      LogMgr.logError("MainWindow.saveWorkspace()", "Error saving workspace: " + filename, e);
      WbSwingUtilities.showErrorMessage(this, ResourceMgr.getString("ErrSavingWorkspace") + "\n" + ExceptionUtil.getDisplay(e));
    }
    finally
    {
      try { w.close(); } catch (Throwable th) {}
    }

    this.currentWorkspaceFile = filename;

    if (interactive)
    {
      this.checkMakeProfileWorkspace();
    }
    this.updateWindowTitle();
    this.checkWorkspaceActions();
    return true;
  }

  /**
   *  Invoked when the a different SQL panel has been selected
   *  This fires the tabSelected() method
   *  @param e  a ChangeEvent object
   *
   */
  public void stateChanged(ChangeEvent e)
  {
    if (e.getSource() == this.sqlTab)
    {
      if (this.tabRemovalInProgress) return;
      int index = this.sqlTab.getSelectedIndex();
      this.tabSelected(index);
    }
  }

  public MainPanel insertTab()
  {
    return addTab(true, true, false);
  }
  
  public MainPanel addTab()
  {
    return this.addTab(true, true, true);
  }

  /**
   *  Adds a new SQL tab to the main window. This will be inserted
   *  before the first DbExplorer tab
   *
   *  @param selectNew if true the new tab is automatically selected
   *  @param checkConnection if true, the panel will automatically be connected
   *  this is important if a Profile is used where each panel gets its own
   *  connection
   */
  public MainPanel addTab(boolean selectNew, boolean checkConnection)
  {
    return addTab(selectNew, checkConnection, true);
  }
  
  public MainPanel addTab(boolean selectNew, boolean checkConnection, boolean append)
  {
    int index = -1;
    if (append)
    {
      index = this.findFirstExplorerTab();
    }
    else
    {
      index = this.sqlTab.getSelectedIndex() + 1;
    }
    
    if (index == -1) index = sqlTab.getTabCount();
    final SqlPanel sql = new SqlPanel(index+1);
    sql.setConnectionClient(this);
    sql.addDbExecutionListener(this);

    if (checkConnection) this.checkConnectionForPanel(sql);

    JMenuBar menuBar = this.createMenuForPanel(sql);
    this.panelMenus.add(index, menuBar);
    this.sqlTab.add(sql, index);

    // setTabTitle needs to be called after adding the panel!
    // this will set the correct title with Mnemonics
    this.setTabTitle(index, ResourceMgr.getDefaultTabLabel());

    this.setMacroMenuEnabled(sql.isConnected());

    this.renumberTabs();

    sql.initDivider(sqlTab.getHeight() - sqlTab.getTabHeight());
    
    if (selectNew)   
    {
      // if no connection was created initially the switcht to a new 
      // panel will initiate the connection.
      this.sqlTab.setSelectedIndex(index);
    }

    return sql;
  }

  /**
   *  Returns the real title of a tab (without the index number)
   */
  private String getPlainTabTitle(int index)
  {
    String title = this.sqlTab.getTitleAt(index);
    int pos = title.lastIndexOf(' ');
    if (pos > -1)
    {
      title = title.substring(0, pos);
    }
    return title;
  }

  /**
   *  Sets the title of a tab and appends the index number to
   *  the title, so that a shortcut Ctrl-n can be defined
   */
  private void setTabTitle(int anIndex, String aName)
  {
    MainPanel p = this.getSqlPanel(anIndex);
    p.setTabName(aName);
    p.setTabTitle(this.sqlTab, anIndex);
    this.updateViewMenu(anIndex, p.getTabTitle());
  }

  public void removeLastTab(boolean includeExplorer)
  {
    int index = this.sqlTab.getTabCount() - 1;
    if (!includeExplorer)
    {
      while (this.getSqlPanel(index) instanceof DbExplorerPanel)
      {
        index --;
      }
    }
    this.closeTab(index);
  }

  public boolean canCloseTab()
  {
    int numTabs = this.getLastSqlPanelIndex();
    int currentIndex = this.sqlTab.getSelectedIndex();
    if (currentIndex > numTabs) return true;
    return numTabs > 0;
  }

  public boolean canRenameTab()
  {
    boolean canRename = (this.currentWorkspaceFile != null);
    MainPanel p = this.getCurrentPanel();
    canRename = canRename && (p instanceof SqlPanel);
    return canRename;
  }

  public void renameTab()
  {
    if (this.getCurrentPanel() instanceof DbExplorerPanel) return;

    int index = this.sqlTab.getSelectedIndex();

    String oldName = this.getPlainTabTitle(index);
    String newName = WbSwingUtilities.getUserInput(this.sqlTab, ResourceMgr.getString("MsgEnterNewTabName"), oldName);
    if (newName != null)
    {
      this.setTabTitle(index, newName);
    }
  }

  public void removeTab()
  {
    if (!canCloseTab()) return;
    int index = this.sqlTab.getSelectedIndex();
    this.closeTab(index);
  }

  private void renumberTabs()
  {
    int count = this.sqlTab.getTabCount();
    for (int i=0; i < count; i++)
    {
      MainPanel p = this.getSqlPanel(i);
      p.setTabTitle(sqlTab, i);
    }
    for (int panel=0; panel < count; panel++)
    {
      rebuildViewMenu(panel);
    }
  }

  /**
   * Rebuild the part of the view menu that handles the
   * selecting of tabs
   */
  private void rebuildViewMenu(int panel)
  {
    JMenu menu = this.getViewMenu(panel);
    JMenuItem item = menu.getItem(0);
    while (item != null && (item.getAction() instanceof SelectTabAction))
    {
      menu.remove(0);
      item = menu.getItem(0);
    }
    int count = this.sqlTab.getTabCount();
    for (int i=0; i < count; i++)
    {
      SelectTabAction a = new SelectTabAction(sqlTab, i);
      a.setMenuText(getPlainTabTitle(i));
      menu.insert(a, i);
    }
    if (this.sqlTab.getSelectedIndex() == panel)
    {
      WbSwingUtilities.repaintNow(menu);
    }
  }

  /**
   * Moves the current sql tab to the left (i.e. index := index - 1)
   * If index == 0 nothing happens
   */
  public void moveTabLeft()
  {
    int index = this.getCurrentPanelIndex();
    if (index <= 0) return;
    moveTab(index, index - 1);
  }

  /**
   * Moves the current sql tab to the right (i.e. index := index + 1)
   * If oldIndex denotes the last SQL Tab, nothing happens
   */
  public void moveTabRight()
  {
    int index = this.getCurrentPanelIndex();
    int lastIndex = this.getLastSqlPanelIndex();
    if (index >= lastIndex) return;
    moveTab(index, index + 1);
  }

  public void moveTab(int oldIndex, int newIndex)
  {
    SqlPanel p = (SqlPanel) this.getSqlPanel(oldIndex);
    JMenuBar oldMenu = this.panelMenus.get(oldIndex);
    this.sqlTab.remove(oldIndex);
    this.panelMenus.remove(oldIndex);
    this.panelMenus.add(newIndex, oldMenu);
    
    this.sqlTab.add(p, newIndex);
    this.sqlTab.setSelectedIndex(newIndex);
    
    renumberTabs();
    this.tabSelected(newIndex);
    this.validate();
  }
  
  /**
   * Removes the tab at the give location. If the current profile
   * uses a separate connection per tab, then a disconnect will be
   * triggered as well. This disconnect will be started in a
   * background thread.
   */
  public void closeTab(int index)
  {
    MainPanel panel = this.getSqlPanel(index);
    if (panel == null) return;
    if (!panel.canCloseTab()) return;
    removeTab(index);
  }
  
  /**
   * Removes the indicated tab without checking for modified file etc.
   */
  protected void removeTab(int index)
  {
    MainPanel panel = this.getSqlPanel(index);
    if (panel == null) return;

    int newTab = -1;

    boolean inProgress = this.isConnectInProgress();
    if (!inProgress) this.setConnectIsInProgress();
    try
    {
      this.tabRemovalInProgress = true;
      WbConnection conn = panel.getConnection();

      // this does not really close the connection
      // it simply tells the panel that it should
      // release anything attached to the connection!
      // the actual disconnect from the DB is done afterwards
      // through the ConnectionMgr in a separate thread
      panel.disconnect();
      try
      {
        panel.dispose();
      }
      catch (Throwable th)
      {
        LogMgr.logError("MainWindow.removeTab()", "Error when removing tab", th);
      }

      if (this.currentProfile != null && this.currentProfile.getUseSeparateConnectionPerTab()
         && conn != null)
      {
        final String id = conn.getId();
        Thread t = new WbThread("Panel " + panel.getId() + " disconnect thread")
        {
          public void run()
          {
            ConnectionMgr.getInstance().disconnect(id);
          }
        };
        t.start();
      }

      this.panelMenus.remove(index);
      this.sqlTab.remove(index);
      this.renumberTabs();
      newTab = this.sqlTab.getSelectedIndex();
    }
    catch (Throwable e)
    {
      LogMgr.logError("MainWindows.removeTab()", "Error removing tab index=" + index,e);
    }
    finally
    {
      this.tabRemovalInProgress = false;
      if (!inProgress) this.clearConnectIsInProgress();
    }
    if (newTab >= 0) 
    {
      this.tabSelected(newTab);
    }
    return;
  }

  public void mouseClicked(MouseEvent e)
  {
    if (e.getSource() == this.sqlTab && e.getButton() == MouseEvent.BUTTON3)
    {
      SqlTabPopup pop = new SqlTabPopup(this);
      pop.show(this.sqlTab,e.getX(),e.getY());
    }
  }

  public void mouseEntered(MouseEvent e)
  {
  }

  public void mouseExited(MouseEvent e)
  {
  }

  public void mousePressed(MouseEvent e)
  {
  }

  public void mouseReleased(MouseEvent e)
  {
  }

  public void executionEnd(WbConnection conn, Object source)
  {
    jobIndicator.jobEnded();
  }

  public void executionStart(WbConnection conn, Object source)
  {
    if (Settings.getInstance().getAutoSaveWorkspace())
    {
      this.saveWorkspace();
    }
    jobIndicator.jobStarted();
  }

  public void dragEnter(java.awt.dnd.DropTargetDragEvent dropTargetDragEvent)
  {
    dropTargetDragEvent.acceptDrag(DnDConstants.ACTION_COPY);
  }

  public void dragExit(java.awt.dnd.DropTargetEvent dropTargetEvent)
  {
  }

  public void dragOver(java.awt.dnd.DropTargetDragEvent dropTargetDragEvent)
  {
  }

  public void drop(java.awt.dnd.DropTargetDropEvent dropTargetDropEvent)
  {
    try
    {
      Transferable tr = dropTargetDropEvent.getTransferable();
      if (tr.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
      {
        dropTargetDropEvent.acceptDrop(DnDConstants.ACTION_COPY);
        List fileList = (List)tr.getTransferData(DataFlavor.javaFileListFlavor);
        if (fileList != null)
        {
          int files = fileList.size();
          for (int i=0; i < files; i++)
          {
            File file = (File)fileList.get(i);
            this.addTab(true, true, true);
            SqlPanel sql = this.getCurrentSqlPanel();
            sql.readFile(file.getAbsolutePath(), null);
          }
        }
      }
      else
      {
        dropTargetDropEvent.rejectDrop();
      }
    }
    catch (IOException io)
    {
      LogMgr.logError("MainWindow.drop()", "Error processing drop event", io);
      dropTargetDropEvent.rejectDrop();
    }
    catch (UnsupportedFlavorException ufe)
    {
      LogMgr.logError("MainWindow.drop()", "Error processing drop event", ufe);
      dropTargetDropEvent.rejectDrop();
    }
  }

  public void dropActionChanged(java.awt.dnd.DropTargetDragEvent dropTargetDragEvent)
  {
  }

}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.