Author: jfuerth
Date: Tue Aug 26 15:56:41 2008
New Revision: 2617
Modified:
trunk/regress/ca/sqlpower/architect/swingui/TestAutoLayoutAction.java
trunk/src/ca/sqlpower/architect/swingui/ArchitectFrame.java
trunk/src/ca/sqlpower/architect/swingui/ContainerPane.java
trunk/src/ca/sqlpower/architect/swingui/RelationalPlayPenFactory.java
trunk/src/ca/sqlpower/architect/swingui/TablePane.java
trunk/src/ca/sqlpower/architect/swingui/action/AutoLayoutAction.java
trunk/src/ca/sqlpower/architect/swingui/olap/CubePane.java
trunk/src/ca/sqlpower/architect/swingui/olap/OLAPEditSession.java
trunk/src/ca/sqlpower/architect/swingui/olap/OLAPPane.java
trunk/src/ca/sqlpower/architect/swingui/olap/UsageComponent.java
trunk/src/ca/sqlpower/architect/swingui/olap/VirtualCubePane.java
Log:
Implemented auto layout for OLAP playpens. This required changing the
AutoLayoutAction's constructor so you pass in the specific play pen it's
supposed to lay out.
Modified:
trunk/regress/ca/sqlpower/architect/swingui/TestAutoLayoutAction.java
==============================================================================
--- trunk/regress/ca/sqlpower/architect/swingui/TestAutoLayoutAction.java
(original)
+++ trunk/regress/ca/sqlpower/architect/swingui/TestAutoLayoutAction.java
Tue Aug 26 15:56:41 2008
@@ -45,7 +45,7 @@
TestingArchitectSwingSessionContext context = new
TestingArchitectSwingSessionContext();
ArchitectSwingSession session = context.createSession();
PlayPen pp = session.getPlayPen();
- layoutAction = new AutoLayoutAction(session, "Tree Layout", "Basic tree
layout", "auto_layout");
+ layoutAction = new AutoLayoutAction(session, session.getPlayPen(), "Tree
Layout", "Basic tree layout", "auto_layout");
layout = new BasicTreeAutoLayout();
pp.repaint();
//action = af.getAutoLayoutAction();
Modified: trunk/src/ca/sqlpower/architect/swingui/ArchitectFrame.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/ArchitectFrame.java (original)
+++ trunk/src/ca/sqlpower/architect/swingui/ArchitectFrame.java Tue Aug 26
15:56:41 2008
@@ -374,7 +374,7 @@
undoAction = new UndoAction(session, session.getUndoManager());
redoAction = new RedoAction(session, session.getUndoManager());
- autoLayoutAction = new AutoLayoutAction(session,
Messages.getString("ArchitectFrame.autoLayoutActionName"),
Messages.getString("ArchitectFrame.autoLayoutActionDescription"), "auto_layout");
//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ autoLayoutAction = new AutoLayoutAction(session,
session.getPlayPen(),
Messages.getString("ArchitectFrame.autoLayoutActionName"),
Messages.getString("ArchitectFrame.autoLayoutActionDescription"), "auto_layout");
//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
autoLayout = new FruchtermanReingoldForceLayout();
autoLayoutAction.setLayout(autoLayout);
exportDDLAction = new ExportDDLAction(session);
Modified: trunk/src/ca/sqlpower/architect/swingui/ContainerPane.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/ContainerPane.java (original)
+++ trunk/src/ca/sqlpower/architect/swingui/ContainerPane.java Tue Aug 26
15:56:41 2008
@@ -46,6 +46,7 @@
import org.apache.log4j.Logger;
+import ca.sqlpower.architect.layout.LayoutNode;
import ca.sqlpower.architect.swingui.PlayPen.FloatingContainerPaneListener;
import ca.sqlpower.architect.swingui.PlayPen.MouseModeType;
import ca.sqlpower.architect.swingui.event.ItemSelectionEvent;
@@ -60,7 +61,7 @@
*/
public abstract class ContainerPane<T extends Object, C extends Object>
extends PlayPenComponent
-implements DragSourceListener {
+implements DragSourceListener, LayoutNode {
/**
* A special item index that represents the titlebar area.
@@ -564,4 +565,12 @@
* If there is nothing transferable selected, returns null.
*/
public abstract Transferable createTransferableForSelection();
+
+
+ /**
+ * Simple implementation for LayoutNode interface. Simply calls
getName().
+ */
+ public String getNodeName() {
+ return getName();
+ }
}
Modified:
trunk/src/ca/sqlpower/architect/swingui/RelationalPlayPenFactory.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/RelationalPlayPenFactory.java
(original)
+++ trunk/src/ca/sqlpower/architect/swingui/RelationalPlayPenFactory.java
Tue Aug 26 15:56:41 2008
@@ -102,6 +102,7 @@
AutoLayoutAction layoutAction =
new AutoLayoutAction(
session,
+ session.getPlayPen(),
Messages.getString("PlayPen.straightenLinesActionName"), //$NON-NLS-1$
Messages.getString("PlayPen.straightenLinesActionDescription"),
//$NON-NLS-1$
icon);
Modified: trunk/src/ca/sqlpower/architect/swingui/TablePane.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/TablePane.java (original)
+++ trunk/src/ca/sqlpower/architect/swingui/TablePane.java Tue Aug 26
15:56:41 2008
@@ -64,12 +64,11 @@
import ca.sqlpower.architect.SQLRelationship;
import ca.sqlpower.architect.SQLTable;
import ca.sqlpower.architect.layout.LayoutEdge;
-import ca.sqlpower.architect.layout.LayoutNode;
import ca.sqlpower.architect.swingui.action.EditSpecificIndexAction;
import ca.sqlpower.swingui.ColorIcon;
import ca.sqlpower.swingui.SPSUtils;
-public class TablePane extends ContainerPane<SQLTable, SQLColumn>
implements LayoutNode {
+public class TablePane extends ContainerPane<SQLTable, SQLColumn> {
private static final Logger logger = Logger.getLogger(TablePane.class);
@@ -827,13 +826,6 @@
*/
public boolean canImport(JComponent c, DataFlavor[] flavors) {
return bestImportFlavor(c, flavors) != null;
- }
-
-
- // ------- LayoutNode methods that we didn't already happen to
implement --------
-
- public String getNodeName() {
- return getName();
}
public List<LayoutEdge> getInboundEdges() {
Modified:
trunk/src/ca/sqlpower/architect/swingui/action/AutoLayoutAction.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/action/AutoLayoutAction.java
(original)
+++ trunk/src/ca/sqlpower/architect/swingui/action/AutoLayoutAction.java
Tue Aug 26 15:56:41 2008
@@ -35,7 +35,7 @@
import ca.sqlpower.architect.swingui.ContainerPane;
import ca.sqlpower.architect.swingui.LayoutAnimator;
import ca.sqlpower.architect.swingui.PlayPen;
-import ca.sqlpower.architect.swingui.TablePane;
+import ca.sqlpower.architect.swingui.PlayPenComponent;
public class AutoLayoutAction extends AbstractArchitectAction {
private static final Logger logger =
Logger.getLogger(AutoLayoutAction.class);
@@ -46,16 +46,18 @@
private int framesPerSecond = 25;
- public AutoLayoutAction(ArchitectSwingSession session, String name,
String description, String iconResourceName) {
- super(session, name, description, iconResourceName);
+ public AutoLayoutAction(ArchitectSwingSession session, PlayPen
playPen, String name, String description, String iconResourceName) {
+ super(session, playPen, name, description, iconResourceName);
}
- public AutoLayoutAction(ArchitectSwingSession session, String name,
String description, Icon icon) {
- super(session, name, description, icon);
+ public AutoLayoutAction(ArchitectSwingSession session, PlayPen
playPen, String name, String description, Icon icon) {
+ super(session, playPen, name, description, icon);
}
public void actionPerformed(ActionEvent evt) {
+ logger.debug("Auto layout action starting...");
+
// This funny construction creates a new instance of the current
// type of layout. It would be better to ask client code for a
// layout factory, then use the factory to make new instances for
@@ -67,43 +69,64 @@
throw new RuntimeException(e);
}
- // ok, if it's broken, let's just fail silently and pretend the
user missed the button. (that was sarcasm)
- if (layout != null) {
- List<? extends LayoutNode> tablePanes = new
ArrayList<TablePane>();
- for (ContainerPane<?, ?> cp :
getPlayPen().getSelectedContainers()) {
- if (cp instanceof TablePane) {
- ((List<TablePane>) tablePanes).add((TablePane) cp);
- }
- }
- List<LayoutNode> notLaidOut = new
ArrayList<LayoutNode>(playpen.getTablePanes());
- notLaidOut.removeAll(tablePanes);
- Point layoutAreaOffset = new Point();
- if (tablePanes.size() == 0 || tablePanes.size() == 1) {
- tablePanes = playpen.getTablePanes();
- } else if (tablePanes.size() !=
playpen.getTablePanes().size()){
- int maxWidth =0;
- for (LayoutNode tp : notLaidOut){
- int width = tp.getWidth()+tp.getX();
- if (width > maxWidth) {
- maxWidth = width;
- }
- }
- layoutAreaOffset = new Point(maxWidth,0);
- }
-
- List<? extends LayoutEdge> relationships =
playpen.getRelationships();
- logger.debug("About to do layout. tablePanes="+tablePanes);
//$NON-NLS-1$
- logger.debug("About to do layout. relationships="+relationships);
//$NON-NLS-1$
-
-
- Rectangle layoutArea = new Rectangle(layoutAreaOffset,
layout.getNewArea(tablePanes));
- layout.setup(tablePanes, relationships, layoutArea);
- LayoutAnimator anim = new LayoutAnimator(playpen, layout);
- anim.setAnimationEnabled(animationEnabled);
- anim.setFramesPerSecond(framesPerSecond);
- anim.startAnimation();
- }
+ logger.debug("Created new Layout instance: " + layout);
+
+ List<LayoutNode> nodes = new ArrayList<LayoutNode>();
+ for (ContainerPane<?, ?> cp :
getPlayPen().getSelectedContainers()) {
+ if (cp instanceof LayoutNode) {
+ nodes.add((LayoutNode) cp);
+ }
+ }
+
+ // XXX the following block of code is a bit disturbing. Needs
refactoring after we figure out what it's supposed to do.
+ List<LayoutNode> notLaidOut = extractLayoutNodes(playpen);
+ notLaidOut.removeAll(nodes);
+ Point layoutAreaOffset = new Point();
+ if (nodes.size() == 0 || nodes.size() == 1) {
+ nodes = extractLayoutNodes(playpen);
+ } else if (nodes.size() != extractLayoutNodes(playpen).size()){
+ int maxWidth = 0;
+ for (LayoutNode tp : notLaidOut) {
+ int width = tp.getWidth() + tp.getX();
+ if (width > maxWidth) {
+ maxWidth = width;
+ }
+ }
+ layoutAreaOffset = new Point(maxWidth,0);
+ }
+
+ List<LayoutEdge> edges = extractLayoutEdges(playpen);
+ logger.debug("About to do layout. nodes=" + nodes); //$NON-NLS-1$
+ logger.debug("About to do layout. edges=" + edges); //$NON-NLS-1$
+
+
+ Rectangle layoutArea = new Rectangle(layoutAreaOffset,
layout.getNewArea(nodes));
+ layout.setup(nodes, edges, layoutArea);
+ LayoutAnimator anim = new LayoutAnimator(playpen, layout);
+ anim.setAnimationEnabled(animationEnabled);
+ anim.setFramesPerSecond(framesPerSecond);
+ anim.startAnimation();
}
+
+ private static List<LayoutNode> extractLayoutNodes(PlayPen pp) {
+ List<LayoutNode> nodes = new ArrayList<LayoutNode>();
+ for (PlayPenComponent ppc : pp.getPlayPenComponents()) {
+ if (ppc instanceof LayoutNode) {
+ nodes.add((LayoutNode) ppc);
+ }
+ }
+ return nodes;
+ }
+
+ private static List<LayoutEdge> extractLayoutEdges(PlayPen pp) {
+ List<LayoutEdge> edges = new ArrayList<LayoutEdge>();
+ for (PlayPenComponent ppc : pp.getPlayPenComponents()) {
+ if (ppc instanceof LayoutEdge) {
+ edges.add((LayoutEdge) ppc);
+ }
+ }
+ return edges;
+ }
public boolean isAnimationEnabled() {
return animationEnabled;
Modified: trunk/src/ca/sqlpower/architect/swingui/olap/CubePane.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/olap/CubePane.java (original)
+++ trunk/src/ca/sqlpower/architect/swingui/olap/CubePane.java Tue Aug 26
15:56:41 2008
@@ -38,6 +38,7 @@
public class CubePane extends OLAPPane<Cube, OLAPObject> {
+ @SuppressWarnings("unused")
private static final Logger logger = Logger.getLogger(CubePane.class);
public CubePane(Cube model, PlayPenContentPane parent) {
Modified: trunk/src/ca/sqlpower/architect/swingui/olap/OLAPEditSession.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/olap/OLAPEditSession.java
(original)
+++ trunk/src/ca/sqlpower/architect/swingui/olap/OLAPEditSession.java Tue
Aug 26 15:56:41 2008
@@ -30,6 +30,7 @@
import javax.swing.JSplitPane;
import javax.swing.JToolBar;
+import ca.sqlpower.architect.layout.FruchtermanReingoldForceLayout;
import ca.sqlpower.architect.olap.OLAPChildEvent;
import ca.sqlpower.architect.olap.OLAPChildListener;
import ca.sqlpower.architect.olap.OLAPSession;
@@ -37,6 +38,7 @@
import ca.sqlpower.architect.swingui.ArchitectSwingSession;
import ca.sqlpower.architect.swingui.Messages;
import ca.sqlpower.architect.swingui.PlayPen;
+import ca.sqlpower.architect.swingui.action.AutoLayoutAction;
import ca.sqlpower.architect.swingui.action.ZoomAction;
import ca.sqlpower.architect.swingui.action.ZoomResetAction;
import ca.sqlpower.architect.swingui.action.ZoomToFitAction;
@@ -91,9 +93,11 @@
private CreateCubeUsageAction createCubeUsageAction;
private ExportSchemaAction exportSchemaAction;
private OLAPDeleteSelectedAction olapDeleteSelectedAction;
+ private AutoLayoutAction autoLayoutAction;
private final ArchitectSwingSession swingSession;
+
/**
* Creates a new editor for the given OLAP schema. The schema's
OLAPObjects should
@@ -116,6 +120,8 @@
tree = new OLAPTree(swingSession, this, olapSession.getSchema());
tree.setCellRenderer(new OLAPTreeCellRenderer());
pp = OLAPPlayPenFactory.createPlayPen(swingSession, this);
+
+ // Don't create actions here. PlayPen is currently null.
}
/**
@@ -150,7 +156,9 @@
createCubeUsageAction = new CreateCubeUsageAction(swingSession,
pp);
exportSchemaAction = new ExportSchemaAction(swingSession, schema);
olapDeleteSelectedAction = new
OLAPDeleteSelectedAction(swingSession, this);
-
+ autoLayoutAction = new AutoLayoutAction(swingSession,
pp, "Automatic Layout", "Automatic Layout", "auto_layout"); //$NON-NLS-1$
//$NON-NLS-2$ //$NON-NLS-3$
+ autoLayoutAction.setLayout(new FruchtermanReingoldForceLayout());
+
JToolBar toolbar = new JToolBar(JToolBar.VERTICAL);
toolbar.add(zoomInAction);
toolbar.add(zoomOutAction);
@@ -158,7 +166,11 @@
toolbar.add(zoomToFitAction);
toolbar.addSeparator();
-
+
+ toolbar.add(autoLayoutAction);
+
+ toolbar.addSeparator();
+
toolbar.add(createDimensionAction);
toolbar.add(createCubeAction);
toolbar.add(createVirtualCubeAction);
@@ -261,6 +273,10 @@
public OLAPDeleteSelectedAction getOLAPDeleteSelectedAction() {
return olapDeleteSelectedAction;
+ }
+
+ public AutoLayoutAction getAutoLayoutAction() {
+ return autoLayoutAction;
}
// ------ OLAPChildListener methods ------ //
Modified: trunk/src/ca/sqlpower/architect/swingui/olap/OLAPPane.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/olap/OLAPPane.java (original)
+++ trunk/src/ca/sqlpower/architect/swingui/olap/OLAPPane.java Tue Aug 26
15:56:41 2008
@@ -45,12 +45,14 @@
import org.apache.log4j.Logger;
import ca.sqlpower.architect.ArchitectException;
+import ca.sqlpower.architect.layout.LayoutEdge;
import ca.sqlpower.architect.olap.OLAPObject;
import ca.sqlpower.architect.olap.OLAPUtil;
import ca.sqlpower.architect.olap.MondrianModel.Schema;
import ca.sqlpower.architect.swingui.ASUtils;
import ca.sqlpower.architect.swingui.ContainerPane;
import ca.sqlpower.architect.swingui.PlayPen;
+import ca.sqlpower.architect.swingui.PlayPenComponent;
import ca.sqlpower.architect.swingui.PlayPenContentPane;
import ca.sqlpower.architect.swingui.PlayPenCoordinate;
import ca.sqlpower.architect.swingui.PlayPen.FloatingContainerPaneListener;
@@ -599,4 +601,42 @@
return insertionPoint;
}
+ /**
+ * Returns all the UsageComponents in the play pen that this pane
+ * is the "pane2" for. This is part of the LayoutNode interface.
+ */
+ public final List<LayoutEdge> getInboundEdges() {
+ List<LayoutEdge> edges = new ArrayList<LayoutEdge>();
+
+ for (PlayPenComponent ppc : getPlayPen().getPlayPenComponents()) {
+ if (ppc instanceof UsageComponent) {
+ UsageComponent uc = (UsageComponent) ppc;
+ if (uc.getPane2() == this) {
+ edges.add(uc);
+ }
+ }
+ }
+
+ return edges;
+ }
+
+ /**
+ * Returns all the UsageComponents in the play pen that this pane
+ * is the "pane1" for. This is part of the LayoutNode interface.
+ */
+ public final List<LayoutEdge> getOutboundEdges() {
+ List<LayoutEdge> edges = new ArrayList<LayoutEdge>();
+
+ for (PlayPenComponent ppc : getPlayPen().getPlayPenComponents()) {
+ if (ppc instanceof UsageComponent) {
+ UsageComponent uc = (UsageComponent) ppc;
+ if (uc.getPane1() == this) {
+ edges.add(uc);
+ }
+ }
+ }
+
+ return edges;
+ }
+
}
Modified: trunk/src/ca/sqlpower/architect/swingui/olap/UsageComponent.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/olap/UsageComponent.java
(original)
+++ trunk/src/ca/sqlpower/architect/swingui/olap/UsageComponent.java Tue
Aug 26 15:56:41 2008
@@ -22,6 +22,8 @@
import java.awt.Color;
import java.awt.event.MouseEvent;
+import ca.sqlpower.architect.layout.LayoutEdge;
+import ca.sqlpower.architect.layout.LayoutNode;
import ca.sqlpower.architect.olap.OLAPObject;
import ca.sqlpower.architect.swingui.PlayPen;
import ca.sqlpower.architect.swingui.PlayPenComponent;
@@ -34,7 +36,7 @@
* A component that visually indicates a usage of one olap pane by
another. For example,
* a dimension usage or a cube usage.
*/
-public class UsageComponent extends PlayPenComponent {
+public class UsageComponent extends PlayPenComponent implements LayoutEdge
{
private final OLAPObject model;
private final OLAPPane<?, ?> pane1;
@@ -125,5 +127,13 @@
getPlayPen().getContentPane().remove(UsageComponent.this);
}
}
+ }
+
+ public LayoutNode getHeadNode() {
+ return pane2;
+ }
+
+ public LayoutNode getTailNode() {
+ return pane1;
}
}
Modified: trunk/src/ca/sqlpower/architect/swingui/olap/VirtualCubePane.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/olap/VirtualCubePane.java
(original)
+++ trunk/src/ca/sqlpower/architect/swingui/olap/VirtualCubePane.java Tue
Aug 26 15:56:41 2008
@@ -133,4 +133,5 @@
}
return filtered;
}
+
}