aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/java/sip/communicator/util/swing/SIPCommTabbedPane.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/java/sip/communicator/util/swing/SIPCommTabbedPane.java')
-rw-r--r--src/net/java/sip/communicator/util/swing/SIPCommTabbedPane.java469
1 files changed, 469 insertions, 0 deletions
diff --git a/src/net/java/sip/communicator/util/swing/SIPCommTabbedPane.java b/src/net/java/sip/communicator/util/swing/SIPCommTabbedPane.java
new file mode 100644
index 0000000..cac0463
--- /dev/null
+++ b/src/net/java/sip/communicator/util/swing/SIPCommTabbedPane.java
@@ -0,0 +1,469 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.util.swing;
+
+/*
+ * The following code borrowed from David Bismut, davidou@mageos.com Intern,
+ * SETLabs, Infosys Technologies Ltd. May 2004 - Jul 2004 Ecole des Mines de
+ * Nantes, France
+ */
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+
+import javax.swing.*;
+import javax.swing.border.*;
+import javax.swing.event.*;
+
+import net.java.sip.communicator.util.swing.event.*;
+import net.java.sip.communicator.util.swing.plaf.*;
+
+/**
+ * A JTabbedPane with some added UI functionalities. A close and max/detach
+ * icons are added to every tab, typically to let the user close or detach the
+ * tab by clicking on these icons.
+ *
+ * @author Yana Stamcheva
+ */
+public class SIPCommTabbedPane
+ extends JTabbedPane
+ implements ChangeListener
+{
+ private int overTabIndex = -1;
+
+ private int lastSelectedIndex;
+
+ /**
+ * Creates the <code>CloseAndMaxTabbedPane</code> with an enhanced UI if
+ * <code>enhancedUI</code> parameter is set to <code>true</code>.
+ *
+ * @param closingTabs support for closable tabs
+ * @param maximizingTabs support for maximisable tabs
+ */
+ public SIPCommTabbedPane(boolean closingTabs, boolean maximizingTabs)
+ {
+ super.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
+
+ UIManager.getDefaults()
+ .put("TabbedPane.tabAreaInsets", new Insets(0, 5, 0, 0));
+
+ UIManager.getDefaults()
+ .put("TabbedPane.contentBorderInsets", new Insets(0, 0, 0, 0));
+
+ this.setUI(new SIPCommTabbedPaneEnhancedUI());
+
+ if(closingTabs)
+ this.setCloseIcon(true);
+
+ if(maximizingTabs)
+ this.setMaxIcon(true);
+
+ this.addChangeListener(this);
+ }
+
+ /**
+ * Returns the index of the last tab on which the mouse did an action.
+ */
+ public int getOverTabIndex()
+ {
+ return overTabIndex;
+ }
+
+ /**
+ * Returns <code>true</code> if the close icon is enabled.
+ */
+ public boolean isCloseEnabled()
+ {
+ SIPCommTabbedPaneUI ui = (SIPCommTabbedPaneUI) this.getUI();
+ return ui.isCloseEnabled();
+ }
+
+ /**
+ * Returns <code>true</code> if the max/detach icon is enabled.
+ */
+ public boolean isMaxEnabled()
+ {
+ SIPCommTabbedPaneUI ui = (SIPCommTabbedPaneUI) this.getUI();
+ return ui.isMaxEnabled();
+ }
+
+ /**
+ * Override JTabbedPane method. Does nothing.
+ * @param tabLayoutPolicy The tab layout policy.
+ */
+ public void setTabLayoutPolicy(int tabLayoutPolicy)
+ {
+ }
+
+ /**
+ * Override JTabbedPane method. Does nothing.
+ * @param tabPlacement The tab placement.
+ */
+ public void setTabPlacement(int tabPlacement)
+ {
+ }
+
+ /**
+ * Sets whether the tabbedPane should have a close icon or not.
+ *
+ * @param b whether the tabbedPane should have a close icon or not
+ */
+ public void setCloseIcon(boolean b)
+ {
+ SIPCommTabbedPaneUI ui = (SIPCommTabbedPaneUI) this.getUI();
+ ui.setCloseIcon(b);
+ }
+
+ /**
+ * Sets whether the tabbedPane should have a max/detach icon or not.
+ *
+ * @param b whether the tabbedPane should have a max/detach icon or not
+ */
+ public void setMaxIcon(boolean b)
+ {
+ SIPCommTabbedPaneUI ui = (SIPCommTabbedPaneUI) this.getUI();
+ ui.setMaxIcon(b);
+ }
+
+ /**
+ * Detaches the <code>index</code> tab in a seperate frame. When the frame
+ * is closed, the tab is automatically reinserted into the tabbedPane.
+ *
+ * @param index index of the tabbedPane to be detached
+ */
+ public void detachTab(int index)
+ {
+ if (index < 0 || index >= getTabCount())
+ return;
+
+ final int tabIndex = index;
+ final JComponent c = (JComponent) getComponentAt(tabIndex);
+
+ final Icon icon = getIconAt(tabIndex);
+ final String title = getTitleAt(tabIndex);
+ final String toolTip = getToolTipTextAt(tabIndex);
+ final Border border = c.getBorder();
+
+ final JFrame frame = new SIPCommFrame()
+ {
+ protected void close(boolean isEscaped)
+ {
+ if (isEscaped)
+ return;
+
+ dispose();
+
+ insertTab(title, icon, c, toolTip, Math.min(tabIndex,
+ getTabCount()));
+
+ c.setBorder(border);
+ setSelectedComponent(c);
+ }
+ };
+
+ Window parentWindow = SwingUtilities.windowForComponent(this);
+
+ removeTabAt(index);
+
+ c.setPreferredSize(c.getSize());
+
+ frame.setTitle(title);
+ frame.getContentPane().add(c);
+ frame.setLocation(parentWindow.getLocation());
+ frame.pack();
+
+ WindowFocusListener windowFocusListener = new WindowFocusListener() {
+ long start;
+
+ long end;
+
+ public void windowGainedFocus(WindowEvent e) {
+ start = System.currentTimeMillis();
+ }
+
+ public void windowLostFocus(WindowEvent e) {
+ end = System.currentTimeMillis();
+ long elapsed = end - start;
+
+ if (elapsed < 100)
+ frame.toFront();
+
+ frame.removeWindowFocusListener(this);
+ }
+ };
+
+ /*
+ * This is a small hack to avoid Windows GUI bug, that prevent a new
+ * window from stealing focus (without this windowFocusListener, most of
+ * the time the new frame would just blink from foreground to
+ * background). A windowFocusListener is added to the frame, and if the
+ * time between the frame beeing in foreground and the frame beeing in
+ * background is less that 100ms, it just brings the windows to the
+ * front once again. Then it removes the windowFocusListener. Note that
+ * this hack would not be required on Linux or UNIX based systems.
+ */
+
+ frame.addWindowFocusListener(windowFocusListener);
+
+ // frame.show();
+ frame.setVisible(true);
+ frame.toFront();
+
+ }
+
+ /**
+ * Adds a <code>CloseListener</code> to the tabbedPane.
+ *
+ * @param l the <code>CloseListener</code> to add
+ * @see #fireCloseTabEvent
+ * @see #removeCloseListener
+ */
+ public synchronized void addCloseListener(CloseListener l)
+ {
+ listenerList.add(CloseListener.class, l);
+ }
+
+ /**
+ * Adds a <code>MaxListener</code> to the tabbedPane.
+ *
+ * @param l the <code>MaxListener</code> to add
+ * @see #fireMaxTabEvent
+ * @see #removeMaxListener
+ */
+ public synchronized void addMaxListener(MaxListener l)
+ {
+ listenerList.add(MaxListener.class, l);
+ }
+
+ /**
+ * Adds a <code>DoubleClickListener</code> to the tabbedPane.
+ *
+ * @param l the <code>DoubleClickListener</code> to add
+ * @see #fireDoubleClickTabEvent
+ * @see #removeDoubleClickListener
+ */
+ public synchronized void addDoubleClickListener(DoubleClickListener l)
+ {
+ listenerList.add(DoubleClickListener.class, l);
+ }
+
+ /**
+ * Adds a <code>PopupOutsideListener</code> to the tabbedPane.
+ *
+ * @param l the <code>PopupOutsideListener</code> to add
+ * @see #firePopupOutsideTabEvent
+ * @see #removePopupOutsideListener
+ */
+ public synchronized void addPopupOutsideListener(PopupOutsideListener l)
+ {
+ listenerList.add(PopupOutsideListener.class, l);
+ }
+
+ /**
+ * Removes a <code>CloseListener</code> from this tabbedPane.
+ *
+ * @param l the <code>CloseListener</code> to remove
+ * @see #fireCloseTabEvent
+ * @see #addCloseListener
+ */
+ public synchronized void removeCloseListener(CloseListener l)
+ {
+ listenerList.remove(CloseListener.class, l);
+ }
+
+ /**
+ * Removes a <code>MaxListener</code> from this tabbedPane.
+ *
+ * @param l the <code>MaxListener</code> to remove
+ * @see #fireMaxTabEvent
+ * @see #addMaxListener
+ */
+ public synchronized void removeMaxListener(MaxListener l)
+ {
+ listenerList.remove(MaxListener.class, l);
+ }
+
+ /**
+ * Removes a <code>DoubleClickListener</code> from this tabbedPane.
+ *
+ * @param l
+ * the <code>DoubleClickListener</code> to remove
+ * @see #fireDoubleClickTabEvent
+ * @see #addDoubleClickListener
+ */
+ public synchronized void removeDoubleClickListener(DoubleClickListener l)
+ {
+ listenerList.remove(DoubleClickListener.class, l);
+ }
+
+ /**
+ * Removes a <code>PopupOutsideListener</code> from this tabbedPane.
+ *
+ * @param l
+ * the <code>PopupOutsideListener</code> to remove
+ * @see #firePopupOutsideTabEvent
+ * @see #addPopupOutsideListener
+ */
+ public synchronized void removePopupOutsideListener(
+ PopupOutsideListener l)
+ {
+ listenerList.remove(PopupOutsideListener.class, l);
+ }
+
+ /**
+ * Sends a <code>MouseEvent</code>, whose source is this tabbedpane, to
+ * every <code>CloseListener</code>. The method also updates the
+ * <code>overTabIndex</code> of the tabbedPane with a value coming from
+ * the UI. This method method is called each time a <code>MouseEvent</code>
+ * is received from the UI when the user clicks on the close icon of the tab
+ * which index is <code>overTabIndex</code>.
+ *
+ * @param e
+ * the <code>MouseEvent</code> to be sent
+ * @param overTabIndex
+ * the index of a tab, usually the tab over which the mouse is
+ *
+ * @see #addCloseListener
+ */
+ public void fireCloseTabEvent(MouseEvent e, int overTabIndex)
+ {
+ this.overTabIndex = overTabIndex;
+
+ EventListener[] closeListeners = getListeners(CloseListener.class);
+ for (int i = 0; i < closeListeners.length; i++)
+ {
+ ((CloseListener) closeListeners[i]).closeOperation(e);
+ }
+ }
+
+ /**
+ * Sends a <code>MouseEvent</code>, whose source is this tabbedpane, to
+ * every <code>MaxListener</code>. The method also updates the
+ * <code>overTabIndex</code> of the tabbedPane with a value coming from
+ * the UI. This method method is called each time a <code>MouseEvent</code>
+ * is received from the UI when the user clicks on the max icon of the tab
+ * which index is <code>overTabIndex</code>.
+ *
+ * @param e
+ * the <code>MouseEvent</code> to be sent
+ * @param overTabIndex
+ * the index of a tab, usually the tab over which the mouse is
+ *
+ * @see #addMaxListener
+ */
+ public void fireMaxTabEvent(MouseEvent e, int overTabIndex)
+ {
+ this.overTabIndex = overTabIndex;
+
+ EventListener[] maxListeners = getListeners(MaxListener.class);
+ for (int i = 0; i < maxListeners.length; i++)
+ {
+ ((MaxListener) maxListeners[i]).maxOperation(e);
+ }
+ }
+
+ /**
+ * Sends a <code>MouseEvent</code>, whose source is this tabbedpane, to
+ * every <code>DoubleClickListener</code>. The method also updates the
+ * <code>overTabIndex</code> of the tabbedPane with a value coming from
+ * the UI. This method method is called each time a <code>MouseEvent</code>
+ * is received from the UI when the user double-clicks on the tab which
+ * index is <code>overTabIndex</code>.
+ *
+ * @param e
+ * the <code>MouseEvent</code> to be sent
+ * @param overTabIndex
+ * the index of a tab, usually the tab over which the mouse is
+ *
+ * @see #addDoubleClickListener
+ */
+ public void fireDoubleClickTabEvent(MouseEvent e, int overTabIndex)
+ {
+ this.overTabIndex = overTabIndex;
+
+ EventListener[] dClickListeners
+ = getListeners(DoubleClickListener.class);
+ for (int i = 0; i < dClickListeners.length; i++)
+ {
+ ((DoubleClickListener) dClickListeners[i]).doubleClickOperation(e);
+ }
+ }
+
+ /**
+ * Sends a <code>MouseEvent</code>, whose source is this tabbedpane, to
+ * every <code>PopupOutsideListener</code>. The method also sets the
+ * <code>overTabIndex</code> to -1. This method method is called each time
+ * a <code>MouseEvent</code> is received from the UI when the user
+ * right-clicks on the inactive part of a tabbedPane.
+ *
+ * @param e
+ * the <code>MouseEvent</code> to be sent
+ *
+ * @see #addPopupOutsideListener
+ */
+ public void firePopupOutsideTabEvent(MouseEvent e)
+ {
+ this.overTabIndex = -1;
+
+ EventListener[] popupListeners
+ = getListeners(PopupOutsideListener.class);
+ for (int i = 0; i < popupListeners.length; i++)
+ {
+ ((PopupOutsideListener) popupListeners[i]).popupOutsideOperation(e);
+ }
+ }
+
+ /**
+ * Overrides setSelectedIndex in JTabbedPane in order to remove the
+ * hightlight if the tab which is selected.
+ * @param tabIndex The index of the tab to be selected.
+ */
+ public void setSelectedIndex(int tabIndex)
+ {
+ SIPCommTabbedPaneUI ui = (SIPCommTabbedPaneUI) this.getUI();
+ if (ui.isTabHighlighted(tabIndex))
+ {
+ ui.tabRemoveHighlight(tabIndex);
+ }
+ super.setSelectedIndex(tabIndex);
+ }
+
+ /**
+ * Highlights the tab with the given index.
+ *
+ * @param tabIndex The tab index.
+ */
+ public void highlightTab(int tabIndex)
+ {
+ SIPCommTabbedPaneUI ui = (SIPCommTabbedPaneUI) this.getUI();
+
+ if (!ui.isTabHighlighted(tabIndex)
+ && this.getSelectedIndex() != tabIndex)
+ ui.tabAddHightlight(tabIndex);
+
+ this.repaint();
+ }
+
+ public void removeTabAt(int index)
+ {
+ if (index < lastSelectedIndex)
+ {
+ this.setSelectedIndex(lastSelectedIndex - 1);
+ }
+ else if (index > lastSelectedIndex)
+ {
+ this.setSelectedIndex(lastSelectedIndex);
+ }
+
+ super.removeTabAt(index);
+ }
+
+ public void stateChanged(ChangeEvent e)
+ {
+ lastSelectedIndex = this.getSelectedIndex();
+ }
+}