Revision: 6656
http://squirrel-sql.svn.sourceforge.net/squirrel-sql/?rev=6656&view=rev
Author: gerdwagner
Date: 2012-08-28 17:56:43 +0000 (Tue, 28 Aug 2012)
Log Message:
-----------
Positions of SQL result tabs and of Session tabs can now be changed using drag and drop.
Modified Paths:
--------------
trunk/sql12/app/src/main/java/net/sourceforge/squirrel_sql/client/gui/builders/SquirrelTabbedPane.java
trunk/sql12/app/src/main/java/net/sourceforge/squirrel_sql/client/gui/builders/UIFactory.java
trunk/sql12/app/src/main/java/net/sourceforge/squirrel_sql/client/gui/desktopcontainer/docktabdesktop/DesktopTabbedPane.java
trunk/sql12/app/src/main/java/net/sourceforge/squirrel_sql/client/session/mainpanel/SQLResultExecuterPanel.java
trunk/sql12/doc/src/main/resources/changes.txt
Added Paths:
-----------
trunk/sql12/app/src/main/java/net/sourceforge/squirrel_sql/client/gui/builders/DnDSquirrelTabbedPane.java
trunk/sql12/app/src/main/java/net/sourceforge/squirrel_sql/client/gui/builders/DnDTabbedPane.java
trunk/sql12/app/src/main/java/net/sourceforge/squirrel_sql/client/gui/builders/SquirrelTabbedPaneDelegate.java
Copied: trunk/sql12/app/src/main/java/net/sourceforge/squirrel_sql/client/gui/builders/DnDSquirrelTabbedPane.java (from rev 6654, trunk/sql12/app/src/main/java/net/sourceforge/squirrel_sql/client/gui/builders/SquirrelTabbedPane.java)
===================================================================
--- trunk/sql12/app/src/main/java/net/sourceforge/squirrel_sql/client/gui/builders/DnDSquirrelTabbedPane.java (rev 0)
+++ trunk/sql12/app/src/main/java/net/sourceforge/squirrel_sql/client/gui/builders/DnDSquirrelTabbedPane.java 2012-08-28 17:56:43 UTC (rev 6656)
@@ -0,0 +1,36 @@
+package net.sourceforge.squirrel_sql.client.gui.builders;
+
+/*
+ * Copyright (C) 2001-2003 Colin Bell
+ * co...@us...
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+import net.sourceforge.squirrel_sql.client.IApplication;
+import net.sourceforge.squirrel_sql.client.preferences.SquirrelPreferences;
+
+import javax.swing.*;
+
+class DnDSquirrelTabbedPane extends DnDTabbedPane
+{
+ DnDSquirrelTabbedPane(SquirrelPreferences prefs, IApplication app)
+ {
+ new SquirrelTabbedPaneDelegate(prefs, app, this);
+ setPaintScrollArea(false);
+ setPaintGhost(true);
+ }
+
+}
Added: trunk/sql12/app/src/main/java/net/sourceforge/squirrel_sql/client/gui/builders/DnDTabbedPane.java
===================================================================
--- trunk/sql12/app/src/main/java/net/sourceforge/squirrel_sql/client/gui/builders/DnDTabbedPane.java (rev 0)
+++ trunk/sql12/app/src/main/java/net/sourceforge/squirrel_sql/client/gui/builders/DnDTabbedPane.java 2012-08-28 17:56:43 UTC (rev 6656)
@@ -0,0 +1,459 @@
+package net.sourceforge.squirrel_sql.client.gui.builders;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.dnd.*;
+import java.awt.event.ActionEvent;
+import java.awt.image.BufferedImage;
+
+public class DnDTabbedPane extends JTabbedPane
+{
+ private static final int LINEWIDTH = 3;
+ private static final String NAME = "test";
+ private final GhostGlassPane glassPane = new GhostGlassPane();
+ private final Rectangle lineRect = new Rectangle();
+ private final Color lineColor = new Color(0, 100, 255);
+ private int dragTabIndex = -1;
+
+ private void clickArrowButton(String actionKey)
+ {
+ ActionMap map = getActionMap();
+ if (map != null)
+ {
+ Action action = map.get(actionKey);
+ if (action != null && action.isEnabled())
+ {
+ action.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, null, 0, 0));
+ }
+ }
+ }
+
+ private static Rectangle rBackward = new Rectangle();
+ private static Rectangle rForward = new Rectangle();
+ private static int rwh = 20;
+ private static int buttonsize = 30; //xxx magic number of scroll button size
+
+ private void autoScrollTest(Point glassPt)
+ {
+ Rectangle r = getTabAreaBounds();
+ int tabPlacement = getTabPlacement();
+ if (tabPlacement == TOP || tabPlacement == BOTTOM)
+ {
+ rBackward.setBounds(r.x, r.y, rwh, r.height);
+ rForward.setBounds(r.x + r.width - rwh - buttonsize, r.y, rwh + buttonsize, r.height);
+ }
+ else if (tabPlacement == LEFT || tabPlacement == RIGHT)
+ {
+ rBackward.setBounds(r.x, r.y, r.width, rwh);
+ rForward.setBounds(r.x, r.y + r.height - rwh - buttonsize, r.width, rwh + buttonsize);
+ }
+ rBackward = SwingUtilities.convertRectangle(getParent(), rBackward, glassPane);
+ rForward = SwingUtilities.convertRectangle(getParent(), rForward, glassPane);
+ if (rBackward.contains(glassPt))
+ {
+ //System.out.println(new java.util.Date() + "Backward");
+ clickArrowButton("scrollTabsBackwardAction");
+ }
+ else if (rForward.contains(glassPt))
+ {
+ //System.out.println(new java.util.Date() + "Forward");
+ clickArrowButton("scrollTabsForwardAction");
+ }
+ }
+
+ public DnDTabbedPane()
+ {
+ super();
+ final DragSourceListener dsl = new DragSourceListener()
+ {
+ @Override
+ public void dragEnter(DragSourceDragEvent e)
+ {
+ e.getDragSourceContext().setCursor(DragSource.DefaultMoveDrop);
+ }
+
+ @Override
+ public void dragExit(DragSourceEvent e)
+ {
+ e.getDragSourceContext().setCursor(DragSource.DefaultMoveNoDrop);
+ lineRect.setRect(0, 0, 0, 0);
+ glassPane.setPoint(new Point(-1000, -1000));
+ glassPane.repaint();
+ }
+
+ @Override
+ public void dragOver(DragSourceDragEvent e)
+ {
+ Point glassPt = e.getLocation();
+ SwingUtilities.convertPointFromScreen(glassPt, glassPane);
+ int targetIdx = getTargetTabIndex(glassPt);
+ //if(getTabAreaBounds().contains(tabPt) && targetIdx>=0 &&
+ if (getTabAreaBounds().contains(glassPt) && targetIdx >= 0 &&
+ targetIdx != dragTabIndex && targetIdx != dragTabIndex + 1)
+ {
+ e.getDragSourceContext().setCursor(DragSource.DefaultMoveDrop);
+ glassPane.setCursor(DragSource.DefaultMoveDrop);
+ }
+ else
+ {
+ e.getDragSourceContext().setCursor(DragSource.DefaultMoveNoDrop);
+ glassPane.setCursor(DragSource.DefaultMoveNoDrop);
+ }
+ }
+
+ @Override
+ public void dragDropEnd(DragSourceDropEvent e)
+ {
+ lineRect.setRect(0, 0, 0, 0);
+ dragTabIndex = -1;
+ glassPane.setVisible(false);
+ if (hasGhost())
+ {
+ glassPane.setVisible(false);
+ glassPane.setImage(null);
+ }
+ }
+
+ @Override
+ public void dropActionChanged(DragSourceDragEvent e)
+ {
+ }
+ };
+ final Transferable t = new Transferable()
+ {
+ private final DataFlavor FLAVOR = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType, NAME);
+
+ @Override
+ public Object getTransferData(DataFlavor flavor)
+ {
+ return DnDTabbedPane.this;
+ }
+
+ @Override
+ public DataFlavor[] getTransferDataFlavors()
+ {
+ DataFlavor[] f = new DataFlavor[1];
+ f[0] = this.FLAVOR;
+ return f;
+ }
+
+ @Override
+ public boolean isDataFlavorSupported(DataFlavor flavor)
+ {
+ return flavor.getHumanPresentableName().equals(NAME);
+ }
+ };
+ final DragGestureListener dgl = new DragGestureListener()
+ {
+ @Override
+ public void dragGestureRecognized(DragGestureEvent e)
+ {
+ if (getTabCount() <= 1) return;
+ Point tabPt = e.getDragOrigin();
+ dragTabIndex = indexAtLocation(tabPt.x, tabPt.y);
+ //"disabled tab problem".
+ if (dragTabIndex < 0 || !isEnabledAt(dragTabIndex)) return;
+ initGlassPane(e.getComponent(), e.getDragOrigin());
+ try
+ {
+ e.startDrag(DragSource.DefaultMoveDrop, t, dsl);
+ }
+ catch (InvalidDnDOperationException idoe)
+ {
+ idoe.printStackTrace();
+ }
+ }
+ };
+ new DropTarget(glassPane, DnDConstants.ACTION_COPY_OR_MOVE, new CDropTargetListener(), true);
+ new DragSource().createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY_OR_MOVE, dgl);
+ }
+
+ class CDropTargetListener implements DropTargetListener
+ {
+ @Override
+ public void dragEnter(DropTargetDragEvent e)
+ {
+ if (isDragAcceptable(e)) e.acceptDrag(e.getDropAction());
+ else e.rejectDrag();
+ }
+
+ @Override
+ public void dragExit(DropTargetEvent e)
+ {
+ }
+
+ @Override
+ public void dropActionChanged(DropTargetDragEvent e)
+ {
+ }
+
+ private Point _glassPt = new Point();
+
+ @Override
+ public void dragOver(final DropTargetDragEvent e)
+ {
+ Point glassPt = e.getLocation();
+ if (getTabPlacement() == JTabbedPane.TOP || getTabPlacement() == JTabbedPane.BOTTOM)
+ {
+ initTargetLeftRightLine(getTargetTabIndex(glassPt));
+ }
+ else
+ {
+ initTargetTopBottomLine(getTargetTabIndex(glassPt));
+ }
+ if (hasGhost())
+ {
+ glassPane.setPoint(glassPt);
+ }
+ if (!_glassPt.equals(glassPt)) glassPane.repaint();
+ _glassPt = glassPt;
+ autoScrollTest(glassPt);
+ }
+
+ @Override
+ public void drop(DropTargetDropEvent e)
+ {
+ if (isDropAcceptable(e))
+ {
+ convertTab(dragTabIndex, getTargetTabIndex(e.getLocation()));
+ e.dropComplete(true);
+ }
+ else
+ {
+ e.dropComplete(false);
+ }
+ repaint();
+ }
+
+ private boolean isDragAcceptable(DropTargetDragEvent e)
+ {
+ Transferable t = e.getTransferable();
+ if (t == null) return false;
+ DataFlavor[] f = e.getCurrentDataFlavors();
+ if (t.isDataFlavorSupported(f[0]) && dragTabIndex >= 0)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isDropAcceptable(DropTargetDropEvent e)
+ {
+ Transferable t = e.getTransferable();
+ if (t == null) return false;
+ DataFlavor[] f = t.getTransferDataFlavors();
+ if (t.isDataFlavorSupported(f[0]) && dragTabIndex >= 0)
+ {
+ return true;
+ }
+ return false;
+ }
+ }
+
+ private boolean hasGhost = true;
+
+ public void setPaintGhost(boolean flag)
+ {
+ hasGhost = flag;
+ }
+
+ public boolean hasGhost()
+ {
+ return hasGhost;
+ }
+
+ private boolean isPaintScrollArea = true;
+
+ public void setPaintScrollArea(boolean flag)
+ {
+ isPaintScrollArea = flag;
+ }
+
+ public boolean isPaintScrollArea()
+ {
+ return isPaintScrollArea;
+ }
+
+ private int getTargetTabIndex(Point glassPt)
+ {
+ Point tabPt = SwingUtilities.convertPoint(glassPane, glassPt, DnDTabbedPane.this);
+ boolean isTB = getTabPlacement() == JTabbedPane.TOP || getTabPlacement() == JTabbedPane.BOTTOM;
+ for (int i = 0; i < getTabCount(); i++)
+ {
+ Rectangle r = getBoundsAt(i);
+ if (isTB) r.setRect(r.x - r.width / 2, r.y, r.width, r.height);
+ else r.setRect(r.x, r.y - r.height / 2, r.width, r.height);
+ if (r.contains(tabPt)) return i;
+ }
+ Rectangle r = getBoundsAt(getTabCount() - 1);
+ if (isTB) r.setRect(r.x + r.width / 2, r.y, r.width, r.height);
+ else r.setRect(r.x, r.y + r.height / 2, r.width, r.height);
+ return r.contains(tabPt) ? getTabCount() : -1;
+ }
+
+ private void convertTab(int prev, int next)
+ {
+ if (next < 0 || prev == next)
+ {
+ return;
+ }
+ Component cmp = getComponentAt(prev);
+ Component tab = getTabComponentAt(prev);
+ String str = getTitleAt(prev);
+ Icon icon = getIconAt(prev);
+ String tip = getToolTipTextAt(prev);
+ boolean flg = isEnabledAt(prev);
+ int tgtindex = prev > next ? next : next - 1;
+ remove(prev);
+ insertTab(str, icon, cmp, tip, tgtindex);
+ setEnabledAt(tgtindex, flg);
+ //When you drag'n'drop a disabled tab, it finishes enabled and selected.
+ //pointed out by dlorde
+ if (flg) setSelectedIndex(tgtindex);
+
+ //I have a component in all tabs (jlabel with an X to close the tab) and when i move a tab the component disappear.
+ //pointed out by Daniel Dario Morales Salas
+ setTabComponentAt(tgtindex, tab);
+ }
+
+ private void initTargetLeftRightLine(int next)
+ {
+ if (next < 0 || dragTabIndex == next || next - dragTabIndex == 1)
+ {
+ lineRect.setRect(0, 0, 0, 0);
+ }
+ else if (next == 0)
+ {
+ Rectangle r = SwingUtilities.convertRectangle(this, getBoundsAt(0), glassPane);
+ lineRect.setRect(r.x - LINEWIDTH / 2, r.y, LINEWIDTH, r.height);
+ }
+ else
+ {
+ Rectangle r = SwingUtilities.convertRectangle(this, getBoundsAt(next - 1), glassPane);
+ lineRect.setRect(r.x + r.width - LINEWIDTH / 2, r.y, LINEWIDTH, r.height);
+ }
+ }
+
+ private void initTargetTopBottomLine(int next)
+ {
+ if (next < 0 || dragTabIndex == next || next - dragTabIndex == 1)
+ {
+ lineRect.setRect(0, 0, 0, 0);
+ }
+ else if (next == 0)
+ {
+ Rectangle r = SwingUtilities.convertRectangle(this, getBoundsAt(0), glassPane);
+ lineRect.setRect(r.x, r.y - LINEWIDTH / 2, r.width, LINEWIDTH);
+ }
+ else
+ {
+ Rectangle r = SwingUtilities.convertRectangle(this, getBoundsAt(next - 1), glassPane);
+ lineRect.setRect(r.x, r.y + r.height - LINEWIDTH / 2, r.width, LINEWIDTH);
+ }
+ }
+
+ private void initGlassPane(Component c, Point tabPt)
+ {
+ getRootPane().setGlassPane(glassPane);
+ if (hasGhost())
+ {
+ Rectangle rect = getBoundsAt(dragTabIndex);
+ BufferedImage image = new BufferedImage(c.getWidth(), c.getHeight(), BufferedImage.TYPE_INT_ARGB);
+ Graphics g = image.getGraphics();
+ c.paint(g);
+ rect.x = rect.x < 0 ? 0 : rect.x;
+ rect.y = rect.y < 0 ? 0 : rect.y;
+ image = image.getSubimage(rect.x, rect.y, rect.width, rect.height);
+ glassPane.setImage(image);
+ }
+ Point glassPt = SwingUtilities.convertPoint(c, tabPt, glassPane);
+ glassPane.setPoint(glassPt);
+ glassPane.setVisible(true);
+ }
+
+ private Rectangle getTabAreaBounds()
+ {
+ Rectangle tabbedRect = getBounds();
+ //pointed out by daryl. NullPointerException: i.e. addTab("Tab",null)
+ //Rectangle compRect = getSelectedComponent().getBounds();
+ Component comp = getSelectedComponent();
+ int idx = 0;
+ while (comp == null && idx < getTabCount())
+ {
+ comp = getComponentAt(idx++);
+ }
+ Rectangle compRect = (comp == null) ? new Rectangle() : comp.getBounds();
+ int tabPlacement = getTabPlacement();
+ if (tabPlacement == TOP)
+ {
+ tabbedRect.height = tabbedRect.height - compRect.height;
+ }
+ else if (tabPlacement == BOTTOM)
+ {
+ tabbedRect.y = tabbedRect.y + compRect.y + compRect.height;
+ tabbedRect.height = tabbedRect.height - compRect.height;
+ }
+ else if (tabPlacement == LEFT)
+ {
+ tabbedRect.width = tabbedRect.width - compRect.width;
+ }
+ else if (tabPlacement == RIGHT)
+ {
+ tabbedRect.x = tabbedRect.x + compRect.x + compRect.width;
+ tabbedRect.width = tabbedRect.width - compRect.width;
+ }
+ tabbedRect.grow(2, 2);
+ return tabbedRect;
+ }
+
+ class GhostGlassPane extends JPanel
+ {
+ private final AlphaComposite composite;
+ private Point location = new Point(0, 0);
+ private BufferedImage draggingGhost = null;
+
+ public GhostGlassPane()
+ {
+ setOpaque(false);
+ composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f);
+ //http://bugs.sun.com/view_bug.do?bug_id=6700748
+ //setCursor(null);
+ }
+
+ public void setImage(BufferedImage draggingGhost)
+ {
+ this.draggingGhost = draggingGhost;
+ }
+
+ public void setPoint(Point location)
+ {
+ this.location = location;
+ }
+
+ @Override
+ public void paintComponent(Graphics g)
+ {
+ Graphics2D g2 = (Graphics2D) g;
+ g2.setComposite(composite);
+ if (isPaintScrollArea() && getTabLayoutPolicy() == SCROLL_TAB_LAYOUT)
+ {
+ g2.setPaint(Color.RED);
+ g2.fill(rBackward);
+ g2.fill(rForward);
+ }
+ if (draggingGhost != null)
+ {
+ double xx = location.getX() - (draggingGhost.getWidth(this) / 2d);
+ double yy = location.getY() - (draggingGhost.getHeight(this) / 2d);
+ g2.drawImage(draggingGhost, (int) xx, (int) yy, null);
+ }
+ if (dragTabIndex >= 0)
+ {
+ g2.setPaint(lineColor);
+ g2.fill(lineRect);
+ }
+ }
+ }
+}
Modified: trunk/sql12/app/src/main/java/net/sourceforge/squirrel_sql/client/gui/builders/SquirrelTabbedPane.java
===================================================================
--- trunk/sql12/app/src/main/java/net/sourceforge/squirrel_sql/client/gui/builders/SquirrelTabbedPane.java 2012-08-21 20:17:46 UTC (rev 6655)
+++ trunk/sql12/app/src/main/java/net/sourceforge/squirrel_sql/client/gui/builders/SquirrelTabbedPane.java 2012-08-28 17:56:43 UTC (rev 6656)
@@ -18,115 +18,17 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-import java.lang.ref.WeakReference;
-import javax.swing.*;
-
-import net.sourceforge.squirrel_sql.client.preferences.SquirrelPreferences;
import net.sourceforge.squirrel_sql.client.IApplication;
+import net.sourceforge.squirrel_sql.client.preferences.SquirrelPreferences;
+import javax.swing.*;
+
class SquirrelTabbedPane extends JTabbedPane
{
- private static final long serialVersionUID = 3663370280049413647L;
-
- private SquirrelPreferences _prefs;
-
- private PropsListener _prefsListener;
-
- /** Convenient way to refer to Application Preferences property names. */
- private interface IAppPrefPropertynames extends SquirrelPreferences.IPropertyNames
- {
- // Empty block.
- }
-
SquirrelTabbedPane(SquirrelPreferences prefs, IApplication app)
{
- super();
-
- if (prefs == null) { throw new IllegalArgumentException("SquirrelPreferences == null"); }
- _prefs = prefs;
-
- int tabLayoutPolicy =
- _prefs.getUseScrollableTabbedPanes() ? JTabbedPane.SCROLL_TAB_LAYOUT : JTabbedPane.WRAP_TAB_LAYOUT;
- setTabLayoutPolicy(tabLayoutPolicy);
+ new SquirrelTabbedPaneDelegate(prefs, app, this);
}
- /**
- * Component is being added to its parent so add a property change listener to application perferences.
- */
- public void addNotify()
- {
- super.addNotify();
- _prefsListener = new PropsListener(_prefs, this);
- _prefs.addPropertyChangeListener(_prefsListener);
- _prefsListener.propertiesHaveChanged(null);
- }
-
- /**
- * Component is being removed from its parent so remove the property change listener from the application
- * preferences.
- */
- public void removeNotify()
- {
- super.removeNotify();
- if (_prefsListener != null)
- {
- _prefs.removePropertyChangeListener(_prefsListener);
- _prefsListener = null;
- }
- }
-
-
- /**
- * Avoids memory leaks.
- *
- * Removing the global listener in removeNotify() did not prove really save.
- * We introduced this listener class to hold a weak reference to the tabbed pane
- * to make sure Sessions get garbage collected:
- *
- * If removeNotify() does not work this listener will remain in the list of the global prefs
- * listener. It will then be the only global reference to the tabbed pane.
- * The tabbed pane then can be garbage collected which will result in garbage collecting the
- * complete Session.
- *
- */
- private static final class PropsListener implements PropertyChangeListener
- {
- private SquirrelPreferences _prefs;
-
- private WeakReference<SquirrelTabbedPane> _refSquirrelTabbedPane;
-
- public PropsListener(SquirrelPreferences prefs, SquirrelTabbedPane squirrelTabbedPane)
- {
- _prefs = prefs;
- _refSquirrelTabbedPane = new WeakReference<SquirrelTabbedPane>(squirrelTabbedPane);
- }
-
- public void propertyChange(PropertyChangeEvent evt)
- {
- propertiesHaveChanged(evt.getPropertyName());
- }
-
- void propertiesHaveChanged(String propName)
- {
- SquirrelTabbedPane squirrelTabbedPane = _refSquirrelTabbedPane.get();
-
- if(null == squirrelTabbedPane)
- {
- return;
- }
-
-
- if (propName == null || propName.equals(IAppPrefPropertynames.SCROLLABLE_TABBED_PANES))
- {
- int tabLayoutPolicy =
- _prefs.getUseScrollableTabbedPanes() ? JTabbedPane.SCROLL_TAB_LAYOUT
- : JTabbedPane.WRAP_TAB_LAYOUT;
- squirrelTabbedPane.setTabLayoutPolicy(tabLayoutPolicy);
- }
- }
-
- }
}
Added: trunk/sql12/app/src/main/java/net/sourceforge/squirrel_sql/client/gui/builders/SquirrelTabbedPaneDelegate.java
===================================================================
--- trunk/sql12/app/src/main/java/net/sourceforge/squirrel_sql/client/gui/builders/SquirrelTabbedPaneDelegate.java (rev 0)
+++ trunk/sql12/app/src/main/java/net/sourceforge/squirrel_sql/client/gui/builders/SquirrelTabbedPaneDelegate.java 2012-08-28 17:56:43 UTC (rev 6656)
@@ -0,0 +1,111 @@
+package net.sourceforge.squirrel_sql.client.gui.builders;
+
+import net.sourceforge.squirrel_sql.client.IApplication;
+import net.sourceforge.squirrel_sql.client.preferences.SquirrelPreferences;
+
+import javax.swing.*;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.lang.ref.WeakReference;
+
+public class SquirrelTabbedPaneDelegate
+{
+ private SquirrelPreferences _prefs;
+
+ private PropsListener _prefsListener;
+ private JTabbedPane _tabbedPane;
+
+ /** Convenient way to refer to Application Preferences property names. */
+ private interface IAppPrefPropertynames extends SquirrelPreferences.IPropertyNames
+ {
+ // Empty block.
+ }
+
+ SquirrelTabbedPaneDelegate(SquirrelPreferences prefs, IApplication app, JTabbedPane tabbedPane)
+ {
+ _tabbedPane = tabbedPane;
+ if (prefs == null) { throw new IllegalArgumentException("SquirrelPreferences == null"); }
+ _prefs = prefs;
+
+ int tabLayoutPolicy =
+ _prefs.getUseScrollableTabbedPanes() ? JTabbedPane.SCROLL_TAB_LAYOUT : JTabbedPane.WRAP_TAB_LAYOUT;
+ _tabbedPane.setTabLayoutPolicy(tabLayoutPolicy);
+ }
+
+ /**
+ * Component is being added to its parent so add a property change listener to application perferences.
+ */
+ public void addNotify()
+ {
+ _prefsListener = new PropsListener(_prefs, _tabbedPane);
+ _prefs.addPropertyChangeListener(_prefsListener);
+ _prefsListener.propertiesHaveChanged(null);
+ }
+
+ /**
+ * Component is being removed from its parent so remove the property change listener from the application
+ * preferences.
+ */
+ public void removeNotify()
+ {
+ _tabbedPane.removeNotify();
+ if (_prefsListener != null)
+ {
+ _prefs.removePropertyChangeListener(_prefsListener);
+ _prefsListener = null;
+ }
+ }
+
+
+ /**
+ * Avoids memory leaks.
+ *
+ * Removing the global listener in removeNotify() did not prove really save.
+ * We introduced this listener class to hold a weak reference to the tabbed pane
+ * to make sure Sessions get garbage collected:
+ *
+ * If removeNotify() does not work this listener will remain in the list of the global prefs
+ * listener. It will then be the only global reference to the tabbed pane.
+ * The tabbed pane then can be garbage collected which will result in garbage collecting the
+ * complete Session.
+ *
+ */
+ private static final class PropsListener implements PropertyChangeListener
+ {
+ private SquirrelPreferences _prefs;
+
+ private WeakReference<JTabbedPane> _refSquirrelTabbedPane;
+
+ public PropsListener(SquirrelPreferences prefs, JTabbedPane squirrelTabbedPane)
+ {
+ _prefs = prefs;
+ _refSquirrelTabbedPane = new WeakReference<JTabbedPane>(squirrelTabbedPane);
+ }
+
+ public void propertyChange(PropertyChangeEvent evt)
+ {
+ propertiesHaveChanged(evt.getPropertyName());
+ }
+
+ void propertiesHaveChanged(String propName)
+ {
+ JTabbedPane squirrelTabbedPane = _refSquirrelTabbedPane.get();
+
+ if(null == squirrelTabbedPane)
+ {
+ return;
+ }
+
+
+ if (propName == null || propName.equals(IAppPrefPropertynames.SCROLLABLE_TABBED_PANES))
+ {
+ int tabLayoutPolicy =
+ _prefs.getUseScrollableTabbedPanes() ? JTabbedPane.SCROLL_TAB_LAYOUT
+ : JTabbedPane.WRAP_TAB_LAYOUT;
+ squirrelTabbedPane.setTabLayoutPolicy(tabLayoutPolicy);
+ }
+ }
+
+ }
+
+}
Modified: trunk/sql12/app/src/main/java/net/sourceforge/squirrel_sql/client/gui/builders/UIFactory.java
===================================================================
--- trunk/sql12/app/src/main/java/net/sourceforge/squirrel_sql/client/gui/builders/UIFactory.java 2012-08-21 20:17:46 UTC (rev 6655)
+++ trunk/sql12/app/src/main/java/net/sourceforge/squirrel_sql/client/gui/builders/UIFactory.java 2012-08-28 17:56:43 UTC (rev 6656)
@@ -111,8 +111,23 @@
*/
public JTabbedPane createTabbedPane(int tabPlacement)
{
- final JTabbedPane pnl = new SquirrelTabbedPane(_prefs, _app);
- pnl.setTabPlacement(tabPlacement);
+ return createTabbedPane(tabPlacement, false);
+ }
+
+ public JTabbedPane createTabbedPane(int tabPlacement, boolean dndTabbedPane)
+ {
+ JTabbedPane pnl;
+
+ if (dndTabbedPane)
+ {
+ pnl = new DnDSquirrelTabbedPane(_prefs, _app);
+ }
+ else
+ {
+ pnl = new SquirrelTabbedPane(_prefs, _app);
+ }
+
+ pnl.setTabPlacement(tabPlacement);
fireTabbedPaneCreated(pnl);
return pnl;
Modified: trunk/sql12/app/src/main/java/net/sourceforge/squirrel_sql/client/gui/desktopcontainer/docktabdesktop/DesktopTabbedPane.java
===================================================================
--- trunk/sql12/app/src/main/java/net/sourceforge/squirrel_sql/client/gui/desktopcontainer/docktabdesktop/DesktopTabbedPane.java 2012-08-21 20:17:46 UTC (rev 6655)
+++ trunk/sql12/app/src/main/java/net/sourceforge/squirrel_sql/client/gui/desktopcontainer/docktabdesktop/DesktopTabbedPane.java 2012-08-28 17:56:43 UTC (rev 6656)
@@ -1,11 +1,19 @@
package net.sourceforge.squirrel_sql.client.gui.desktopcontainer.docktabdesktop;
+import net.sourceforge.squirrel_sql.client.gui.builders.DnDTabbedPane;
+
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
-public class DesktopTabbedPane extends JTabbedPane
+public class DesktopTabbedPane extends DnDTabbedPane
{
+ public DesktopTabbedPane()
+ {
+ setPaintScrollArea(false);
+ setPaintGhost(true);
+ }
+
@Override
public Dimension getMinimumSize()
{
Modified: trunk/sql12/app/src/main/java/net/sourceforge/squirrel_sql/client/session/mainpanel/SQLResultExecuterPanel.java
===================================================================
--- trunk/sql12/app/src/main/java/net/sourceforge/squirrel_sql/client/session/mainpanel/SQLResultExecuterPanel.java 2012-08-21 20:17:46 UTC (rev 6655)
+++ trunk/sql12/app/src/main/java/net/sourceforge/squirrel_sql/client/session/mainpanel/SQLResultExecuterPanel.java 2012-08-28 17:56:43 UTC (rev 6656)
@@ -869,7 +869,7 @@
private void createGUI()
{
final SessionProperties props = _session.getProperties();
- _tabbedExecutionsPanel = UIFactory.getInstance().createTabbedPane(props.getSQLExecutionTabPlacement());
+ _tabbedExecutionsPanel = UIFactory.getInstance().createTabbedPane(props.getSQLExecutionTabPlacement(), true);
createTabPopup();
Modified: trunk/sql12/doc/src/main/resources/changes.txt
===================================================================
--- trunk/sql12/doc/src/main/resources/changes.txt 2012-08-21 20:17:46 UTC (rev 6655)
+++ trunk/sql12/doc/src/main/resources/changes.txt 2012-08-28 17:56:43 UTC (rev 6656)
@@ -6,6 +6,8 @@
Not yet released, available in our Subversion repository and in future snapshots and releases.
===============================================================================================
+Positions of SQL result tabs and of Session tabs can now be changed using drag and drop.
+
Fixed bug in logging: Log level could not be set in log4j.properties file.
2759952 (Update fails unless run as admin on Vista): Fixed mis-spelled variable in squirrel-sql.bat which
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|