Author: truesweetman
Date: Tue Aug 26 15:43:14 2008
New Revision: 2614
Modified:
trunk/src/ca/sqlpower/architect/swingui/PlayPen.java
trunk/src/ca/sqlpower/architect/swingui/olap/DimensionPane.java
trunk/src/ca/sqlpower/architect/swingui/olap/OLAPPane.java
trunk/src/ca/sqlpower/architect/swingui/olap/OLAPPlayPenFactory.java
trunk/src/ca/sqlpower/architect/swingui/olap/OLAPTree.java
Log:
Implemented synchronization for the OLAPPlayPen. It uses a similair method
that the RelationalPlayPen uses. Currently, cubeUsages are not
synchronized because they are not shown in the OLAPTree!
Modified: trunk/src/ca/sqlpower/architect/swingui/PlayPen.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/PlayPen.java (original)
+++ trunk/src/ca/sqlpower/architect/swingui/PlayPen.java Tue Aug 26
15:43:14 2008
@@ -103,11 +103,30 @@
import ca.sqlpower.architect.SQLRelationship;
import ca.sqlpower.architect.SQLSchema;
import ca.sqlpower.architect.SQLTable;
+import ca.sqlpower.architect.olap.MondrianModel;
+import ca.sqlpower.architect.olap.OLAPObject;
+import ca.sqlpower.architect.olap.MondrianModel.Cube;
+import ca.sqlpower.architect.olap.MondrianModel.DimensionUsage;
+import ca.sqlpower.architect.olap.MondrianModel.Hierarchy;
+import ca.sqlpower.architect.olap.MondrianModel.Level;
+import ca.sqlpower.architect.olap.MondrianModel.Measure;
+import ca.sqlpower.architect.olap.MondrianModel.Schema;
+import ca.sqlpower.architect.olap.MondrianModel.VirtualCube;
+import ca.sqlpower.architect.olap.MondrianModel.VirtualCubeDimension;
+import ca.sqlpower.architect.olap.MondrianModel.VirtualCubeMeasure;
import ca.sqlpower.architect.swingui.action.CancelAction;
import ca.sqlpower.architect.swingui.event.PlayPenLifecycleEvent;
import ca.sqlpower.architect.swingui.event.PlayPenLifecycleListener;
import ca.sqlpower.architect.swingui.event.SelectionEvent;
import ca.sqlpower.architect.swingui.event.SelectionListener;
+import ca.sqlpower.architect.swingui.olap.CubePane;
+import ca.sqlpower.architect.swingui.olap.DimensionPane;
+import ca.sqlpower.architect.swingui.olap.OLAPPane;
+import ca.sqlpower.architect.swingui.olap.OLAPTree;
+import ca.sqlpower.architect.swingui.olap.PaneSection;
+import ca.sqlpower.architect.swingui.olap.UsageComponent;
+import ca.sqlpower.architect.swingui.olap.VirtualCubePane;
+import ca.sqlpower.architect.swingui.olap.DimensionPane.HierarchySection;
import ca.sqlpower.architect.undo.UndoCompoundEvent;
import ca.sqlpower.architect.undo.UndoCompoundEventListener;
import ca.sqlpower.architect.undo.UndoCompoundEvent.EventTypes;
@@ -636,7 +655,6 @@
*/
public Action getMouseZoomInAction(){
if (zoomInAction == null) {
- System.out.println("Don't you DARE Zoom In!");
return session.getArchitectFrame().getZoomInAction();
}
return zoomInAction;
@@ -2693,6 +2711,353 @@
}
ignoreTreeSelection = false;
}
+
+ /**
+ * Selects the playpen component that represents the given OLAPObjects.
+ * If the given OLAPObjects aren't in the playpen, this method has no
effect.
+ *
+ * @param selection A list of OLAPObjects.
+ * @throws ArchitectException
+ */
+ public void selectObjects(List<OLAPObject> selections, OLAPTree tree)
throws ArchitectException {
+ if (ignoreTreeSelection) return;
+ ignoreTreeSelection = true;
+ logger.debug("selecting: " + selections); //$NON-NLS-1$
+
+ // Parent objects to select because a child object was selected.
+ List<OLAPObject> extraSelections = new ArrayList<OLAPObject>();
+
+ // Objects that were already selected, only used for debugging.
+ List<OLAPObject> ignoredObjs = new ArrayList<OLAPObject>();
+
+ for (OLAPObject obj : selections) {
+ if (obj instanceof Cube) {
+ selectCube((Cube) obj, ignoredObjs);
+ } else if (obj instanceof VirtualCube) {
+ selectVirtualCube((VirtualCube) obj, ignoredObjs);
+ } else if (obj instanceof MondrianModel.Dimension || obj
instanceof DimensionUsage) {
+ selectDimension(obj, ignoredObjs, extraSelections, tree);
+ } else if (obj instanceof Measure) {
+ selectMeasure((Measure) obj, ignoredObjs, extraSelections,
tree);
+ } else if (obj instanceof VirtualCubeDimension || obj
instanceof VirtualCubeMeasure) {
+ selectItemFromVirtualCube(obj, ignoredObjs,
extraSelections, tree);
+ } else if (obj instanceof Hierarchy) {
+ selectHierarchy((Hierarchy) obj, ignoredObjs,
extraSelections, tree);
+ } else if (obj instanceof Level) {
+ selectLevel((Level) obj, ignoredObjs, extraSelections,
tree);
+ }
+
+ logger.debug("selectObjects ignoring: " + ignoredObjs);
//$NON-NLS-1$
+ logger.debug("selectObjects adding tables selections: " +
extraSelections); //$NON-NLS-1$
+
+ // Deselects all other playpen components.
+ for (PlayPenComponent comp : getSelectedItems()) {
+ if (comp instanceof CubePane) {
+ CubePane cp = (CubePane) comp;
+ if (!selections.contains(cp.getModel())
&& !extraSelections.contains(cp.getModel())) {
+ cp.setSelected(false,
SelectionEvent.SINGLE_SELECT);
+ }
+
+ // Cannot deselect Objects while going through the
selected items.
+ List<OLAPObject> oos = new ArrayList<OLAPObject>();
+
+ for (OLAPObject oo : cp.getSelectedItems()) {
+ if (!selections.contains(oo)
&& !extraSelections.contains(oo)) {
+ oos.add(oo);
+ }
+ }
+ for (OLAPObject oo : oos) {
+ cp.deselectItem(oo);
+ }
+ } else if (comp instanceof VirtualCubePane) {
+ VirtualCubePane vcp = (VirtualCubePane) comp;
+ if (!selections.contains(vcp.getModel())
&& !extraSelections.contains(vcp.getModel())) {
+ vcp.setSelected(false,
SelectionEvent.SINGLE_SELECT);
+ }
+
+ // Cannot deselect Objects while going through the
selected items.
+ List<OLAPObject> oos = new ArrayList<OLAPObject>();
+
+ for (OLAPObject oo : vcp.getSelectedItems()) {
+ if (!selections.contains(oo)
&& !extraSelections.contains(oo)) {
+ oos.add(oo);
+ }
+ }
+ for (OLAPObject oo : oos) {
+ vcp.deselectItem(oo);
+ }
+ } else if (comp instanceof DimensionPane) {
+ DimensionPane dp = (DimensionPane) comp;
+ if (!selections.contains(dp.getModel())
&& !extraSelections.contains(dp.getModel())) {
+ dp.setSelected(false,
SelectionEvent.SINGLE_SELECT);
+ }
+
+ // Cannot deselect Objects while going through the
selected items.
+ List<OLAPObject> oos = new ArrayList<OLAPObject>();
+
+ for (OLAPObject oo : dp.getSelectedItems()) {
+ if (!selections.contains(oo)
&& !extraSelections.contains(oo)) {
+ oos.add(oo);
+ }
+ }
+
+ // Get the hierarchies from the sections and add them.
+ for (PaneSection<? extends Level> hs :
dp.getSelectedSections()) {
+ if (hs instanceof HierarchySection) {
+ if (!selections.contains(((HierarchySection)
hs).getHierarchy())
+
&& !extraSelections.contains(((HierarchySection) hs).getHierarchy())) {
+ oos.add(((HierarchySection)
hs).getHierarchy());
+ }
+ }
+ }
+ for (OLAPObject oo : oos) {
+ if (oo instanceof Level) {
+ dp.deselectItem((Level) oo);
+ } else if (oo instanceof Hierarchy) {
+ dp.deselectSection(dp.findSection((Hierarchy)
oo));
+ }
+ }
+ } else if (comp instanceof UsageComponent) {
+ UsageComponent uc = (UsageComponent) comp;
+ if (!selections.contains(uc.getModel())
&& !extraSelections.contains(uc.getModel())) {
+ uc.setSelected(false,
SelectionEvent.SINGLE_SELECT);
+ }
+ } else {
+ throw new IllegalArgumentException("Unknown
PlayPenComponent type " + comp.getClass() + "!");
+ }
+
+ }
+ }
+ ignoreTreeSelection = false;
+ }
+
+ /**
+ * Uses the given cube to select the matching CubePane on the PlayPen.
+ *
+ * @param cube The Cube whose pane is to be selected.
+ * @param ignoredObjs A list of ingored objects used for debugging.
+ * @return The CubePane that was selected or null if none was selected.
+ */
+ private CubePane selectCube(Cube cube, List<OLAPObject> ignoredObjs) {
+ CubePane cp = (CubePane)findPPComponent(cube);
+ if (cp != null && !cp.isSelected()) {
+ cp.setSelected(true, SelectionEvent.SINGLE_SELECT);
+ } else {
+ ignoredObjs.add(cube);
+ }
+ return cp;
+ }
+
+ /**
+ * Uses the given virtualCube to select the matching VirtualCubePane
on the PlayPen.
+ *
+ * @param vCube The VirtualCube whose pane is to be selected.
+ * @param ignoredObjs A list of ingored objects used for debugging.
+ * @return The VirtualCubePane that was selected or null if none was
selected.
+ */
+ private VirtualCubePane selectVirtualCube(VirtualCube vCube,
List<OLAPObject> ignoredObjs) {
+ VirtualCubePane vcp = (VirtualCubePane)findPPComponent(vCube);
+ if (vcp != null && !vcp.isSelected()) {
+ vcp.setSelected(true, SelectionEvent.SINGLE_SELECT);
+ } else {
+ ignoredObjs.add(vCube);
+ }
+ return vcp;
+ }
+
+ /**
+ * Uses the given OLAPObject (which has to be Dimension or
DimnesionUsage) to
+ * select the matching CubePane or DimensionPane on the PlayPen. Also
+ * ensures the OLAPTree also selects the dimension and it's parent if
the
+ * dimension's parent is a cube and not the schema.
+ *
+ * @param obj
+ * The Dimension or DimensionUsage whose pane is to be
selected.
+ * @param ignoredObjs
+ * A list of ingored objects used for debugging.
+ * @param extraSelections
+ * A list of items that are selected, but not directly from
the
+ * user.
+ * @param tree
+ * The OLAPTree assoicated with this PlayPen.
+ * @return The OLAPPane that was selected or null if none was selected.
+ */
+ private OLAPPane<?, ?> selectDimension(OLAPObject obj,
List<OLAPObject> ignoredObjs, List<OLAPObject> extraSelections, OLAPTree
tree) {
+ if (obj.getParent() instanceof Cube) {
+ CubePane cp = selectCube((Cube) obj.getParent(), ignoredObjs);
+ if (cp != null) {
+ selectParents(obj, cp.getModel(), tree, extraSelections);
+ cp.selectItem(obj);
+ }
+ return cp;
+ } else if (obj.getParent() instanceof Schema) {
+ DimensionPane dp = (DimensionPane)findPPComponent(obj);
+ if (dp != null && !dp.isSelected()) {
+ dp.setSelected(true, SelectionEvent.SINGLE_SELECT);
+ } else {
+ ignoredObjs.add(obj);
+ }
+ return dp;
+ } else {
+ throw new IllegalArgumentException("Parent type " +
obj.getParent().getClass()
+ + " is not a valid parent for type " + obj.getClass()
+ "!");
+ }
+ }
+
+ /**
+ * Uses the given Measure to select the matching Measure and CubePane
on the
+ * PlayPen. Also ensures the OLAPTree also selects the measure and the
cube.
+ *
+ * @param measure
+ * The measure to be selected in the playPen.
+ * @param ignoredObjs
+ * A list of ingored objects used for debugging.
+ * @param extraSelections
+ * A list of items that are selected, but not directly from
the
+ * user.
+ * @param tree
+ * The OLAPTree assoicated with this PlayPen.
+ * @return The CubePane that was selected or null if none was selected.
+ */
+ private CubePane selectMeasure(Measure measure, List<OLAPObject>
ignoredObjs, List<OLAPObject> extraSelections, OLAPTree tree) {
+ if (measure.getParent() instanceof Cube) {
+ CubePane cp = selectCube((Cube) measure.getParent(),
ignoredObjs);
+ if (cp != null) {
+ selectParents(measure, cp.getModel(), tree,
extraSelections);
+ cp.selectItem(measure);
+ }
+ return cp;
+ } else {
+ throw new IllegalArgumentException("Parent type " +
measure.getParent().getClass()
+ + " is not a valid parent for type " +
measure.getClass() + "!");
+ }
+ }
+
+ /**
+ * Uses the given VirtualCubeMeasure or VirtualCubeDimension to select
the
+ * matching Object and VirtualCubePane on the PlayPen. Also ensures the
+ * OLAPTree also selects the object and the virtualCube.
+ *
+ * @param obj
+ * The VirtualCubeMeasure or VirtualCubeDimensionto be
select in
+ * the playPen.
+ * @param ignoredObjs
+ * A list of ingored objects used for debugging.
+ * @param extraSelections
+ * A list of items that are selected, but not directly from
the
+ * user.
+ * @param tree
+ * The OLAPTree assoicated with this PlayPen.
+ * @return The VirtualCubePane that was selected or null if none was
+ * selected.
+ */
+ private VirtualCubePane selectItemFromVirtualCube(OLAPObject obj,
List<OLAPObject> ignoredObjs, List<OLAPObject> extraSelections, OLAPTree
tree) {
+ if (obj.getParent() instanceof VirtualCube) {
+ VirtualCubePane vcp = selectVirtualCube((VirtualCube)
obj.getParent(), ignoredObjs);
+ if (vcp != null) {
+ selectParents(obj, vcp.getModel(), tree, extraSelections);
+ vcp.selectItem(obj);
+ }
+ return vcp;
+ } else {
+ throw new IllegalArgumentException("Parent type " +
obj.getParent().getClass()
+ + " is not a valid parent for type " + obj.getClass()
+ "!");
+ }
+ }
+
+ /**
+ * Uses the given Hierarchy to select the matching Hierarchy and it's
+ * DimensionPane on the PlayPen. Also ensures the OLAPTree also
selects the
+ * hierarchy and the dimension.
+ *
+ * @param hierarchy
+ * The hierarchy to be selected in the playPen.
+ * @param ignoredObjs
+ * A list of ingored objects used for debugging.
+ * @param extraSelections
+ * A list of items that are selected, but not directly from
the
+ * user.
+ * @param tree
+ * The OLAPTree assoicated with this PlayPen.
+ * @return The DimensionPane that was selected or null if none was
selected.
+ */
+ private DimensionPane selectHierarchy(Hierarchy hierarchy,
List<OLAPObject> ignoredObjs, List<OLAPObject> extraSelections, OLAPTree
tree) {
+ if (hierarchy.getParent() instanceof MondrianModel.Dimension) {
+ DimensionPane dp =
(DimensionPane)selectDimension(hierarchy.getParent(), ignoredObjs,
extraSelections, tree);
+ if (dp != null) {
+ selectParents(hierarchy, dp.getModel(), tree,
extraSelections);
+ dp.selectSection(dp.findSection((Hierarchy) hierarchy));
+ } else {
+ throw new NullPointerException("OLAPPane that contains " +
hierarchy.getClass() + " not found.");
+ }
+ return dp;
+ } else {
+ throw new IllegalArgumentException("Parent type " +
hierarchy.getParent().getClass()
+ + " is not a valid parent for type " +
hierarchy.getClass() + "!");
+ }
+ }
+
+ /**
+ * Uses the given Level to select the matching Level and DimensionPane
on
+ * the PlayPen. Also ensures the OLAPTree also selects the level and
the
+ * dimension.
+ *
+ * @param level
+ * The level to be selected in the playPen.
+ * @param ignoredObjs
+ * A list of ingored objects used for debugging.
+ * @param extraSelections
+ * A list of items that are selected, but not directly from
the
+ * user.
+ * @param tree
+ * The OLAPTree assoicated with this PlayPen.
+ * @return The DimensionPane that was selected or null if none was
selected.
+ */
+ private DimensionPane selectLevel(Level level, List<OLAPObject>
ignoredObjs, List<OLAPObject> extraSelections, OLAPTree tree) {
+ if (level.getParent() instanceof Hierarchy) {
+ DimensionPane dp =
(DimensionPane)selectDimension(level.getParent().getParent(), ignoredObjs,
extraSelections, tree);
+ if (dp != null) {
+ selectParents(level, dp.getModel(), tree, extraSelections);
+ dp.selectItem((Level) level);
+ } else {
+ throw new NullPointerException("OLAPPane that contains " +
level.getClass() + " not found.");
+ }
+ return dp;
+ } else {
+ throw new IllegalArgumentException("Parent type " +
level.getParent().getClass()
+ + " is not a valid parent for type " +
level.getClass() + "!");
+ }
+ }
+
+ /**
+ * Uses the given OLAPObjects and selects them on the given OLAPTree.
+ *
+ * @param obj
+ * The object to be selected on the Tree.
+ * @param parent
+ * The object's parent to be selected on the Tree.
+ * @param tree
+ * The OLAPTree assoicated with this PlayPen.
+ * @param extraSelections
+ * A list of items that are selected, but not directly from
the
+ * user.
+ */
+ private void selectParents(OLAPObject obj, OLAPObject parent, OLAPTree
tree, List<OLAPObject> extraSelections) {
+ // ensures the table is selected on the dbTree
+ TreePath tp = tree.getTreePathForNode(parent);
+ if (!tree.isPathSelected(tp)) {
+ tree.addSelectionPath(tp);
+ tree.clearNonPlayPenSelections();
+
+ // ensures column tree path is selected after the table
+ TreePath childPath = tree.getTreePathForNode(obj);
+ tree.removeSelectionPath(childPath);
+ tree.addSelectionPath(childPath);
+ }
+ extraSelections.add(parent);
+ }
+
+
public PlayPenContentPane getPlayPenContentPane() {
return contentPane;
Modified: trunk/src/ca/sqlpower/architect/swingui/olap/DimensionPane.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/olap/DimensionPane.java
(original)
+++ trunk/src/ca/sqlpower/architect/swingui/olap/DimensionPane.java Tue Aug
26 15:43:14 2008
@@ -57,7 +57,7 @@
}
- private class HierarchySection implements PaneSection<Level> {
+ public class HierarchySection implements PaneSection<Level> {
private final Hierarchy hierarchy;
@@ -162,5 +162,20 @@
}
}
return filtered;
+ }
+
+ /**
+ * Returns the HierarchySection that contains the given hierarchy.
+ * Returns null if it was not found.
+ */
+ public HierarchySection findSection(Hierarchy hierarchy) {
+ for (PaneSection<? extends Level> hs : sections) {
+ if (hs instanceof HierarchySection) {
+ if (((HierarchySection) hs).getHierarchy() == hierarchy){
+ return ((HierarchySection) hs);
+ }
+ }
+ }
+ return null;
}
}
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:43:14 2008
@@ -20,6 +20,7 @@
package ca.sqlpower.architect.swingui.olap;
import java.awt.Point;
+import java.awt.Rectangle;
import java.awt.Window;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
@@ -30,6 +31,7 @@
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -259,7 +261,7 @@
}
} else if (evt.getID() == MouseEvent.MOUSE_MOVED || evt.getID() ==
MouseEvent.MOUSE_DRAGGED) {
logger.debug("Mouse moved/dragged to " + evt.getPoint());
-// setSelected(pp.getRubberBand().intersects(getBounds(new
Rectangle())),SelectionEvent.SINGLE_SELECT);
+ setSelected(pp.getRubberBand().intersects(getBounds(new
Rectangle())),SelectionEvent.SINGLE_SELECT);
}
}
@@ -270,8 +272,10 @@
*
* @param sect the section to deselect.
*/
- public void deselectSection(PaneSection<C> sect) {
+ public void deselectSection(PaneSection<? extends C> sect) {
selectedSections.remove(sect);
+ // TODO make a firePlayPenCoordinateEvent and change this event to
that
+ fireItemsDeselected(Collections.singleton((C) null));
repaint();
}
@@ -281,6 +285,8 @@
*/
public void selectSection(PaneSection<? extends C> sect) {
selectedSections.add(sect);
+ // TODO make a firePlayPenCoordinateEvent and change this event to
that
+ fireItemsSelected(Collections.singleton((C) null));
repaint();
}
@@ -592,4 +598,5 @@
public PlayPenCoordinate<T, C> getInsertionPoint() {
return insertionPoint;
}
+
}
Modified:
trunk/src/ca/sqlpower/architect/swingui/olap/OLAPPlayPenFactory.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/olap/OLAPPlayPenFactory.java
(original)
+++ trunk/src/ca/sqlpower/architect/swingui/olap/OLAPPlayPenFactory.java
Tue Aug 26 15:43:14 2008
@@ -20,24 +20,46 @@
package ca.sqlpower.architect.swingui.olap;
import java.awt.event.KeyEvent;
+import java.util.ArrayList;
+import java.util.List;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
+import javax.swing.JTree;
import javax.swing.KeyStroke;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.tree.TreePath;
import org.apache.log4j.Logger;
+import ca.sqlpower.architect.ArchitectException;
+import ca.sqlpower.architect.ArchitectRuntimeException;
import ca.sqlpower.architect.olap.OLAPChildEvent;
import ca.sqlpower.architect.olap.OLAPChildListener;
+import ca.sqlpower.architect.olap.OLAPObject;
import ca.sqlpower.architect.olap.OLAPUtil;
+import ca.sqlpower.architect.olap.MondrianModel.Cube;
+import ca.sqlpower.architect.olap.MondrianModel.CubeDimension;
+import ca.sqlpower.architect.olap.MondrianModel.Hierarchy;
+import ca.sqlpower.architect.olap.MondrianModel.Level;
+import ca.sqlpower.architect.olap.MondrianModel.Measure;
+import ca.sqlpower.architect.olap.MondrianModel.VirtualCube;
+import ca.sqlpower.architect.olap.MondrianModel.VirtualCubeMeasure;
import ca.sqlpower.architect.swingui.ArchitectSwingSession;
import ca.sqlpower.architect.swingui.PlayPen;
import ca.sqlpower.architect.swingui.PlayPenComponent;
+import ca.sqlpower.architect.swingui.event.ItemSelectionEvent;
+import ca.sqlpower.architect.swingui.event.ItemSelectionListener;
+import ca.sqlpower.architect.swingui.event.PlayPenContentEvent;
+import ca.sqlpower.architect.swingui.event.PlayPenContentListener;
import ca.sqlpower.architect.swingui.event.PlayPenLifecycleEvent;
import ca.sqlpower.architect.swingui.event.PlayPenLifecycleListener;
import ca.sqlpower.architect.swingui.event.SelectionEvent;
+import ca.sqlpower.architect.swingui.event.SelectionListener;
+import ca.sqlpower.architect.swingui.olap.DimensionPane.HierarchySection;
public class OLAPPlayPenFactory {
@@ -58,6 +80,10 @@
pp.setPopupFactory(new ContextMenuFactory(session, oSession));
OLAPUtil.listenToHierarchy(oSession.getOlapSession().getSchema(),
ppcl, null);
+ SelectionSynchronizer synchronizer = new
SelectionSynchronizer(oSession.getOlapTree(), pp);
+ pp.addSelectionListener(synchronizer);
+ oSession.getOlapTree().addTreeSelectionListener(synchronizer);
+ pp.getContentPane().addPlayPenContentListener(synchronizer);
return pp;
}
@@ -181,6 +207,190 @@
*/
public void PlayPenLifeEnding(PlayPenLifecycleEvent e) {
OLAPUtil.unlistenToHierarchy(session.getOlapSession().getSchema(), this,
null);
+ }
+ }
+
+ static class SelectionSynchronizer
+ implements SelectionListener,
+ ItemSelectionListener<Cube, OLAPObject>,
+ TreeSelectionListener, PlayPenContentListener {
+
+ private int eventDepth = 0;
+ private final OLAPTree tree;
+ private final PlayPen pp;
+
+ public SelectionSynchronizer(OLAPTree tree, PlayPen pp) {
+ this.tree = tree;
+ this.pp = pp;
+ }
+
+ /**
+ * Synchronizes the olapTree selection with the playpen selections
+ * @throws ArchitectException
+ *
+ */
+ public void updateOLAPTree() {
+ if (eventDepth != 1) return;
+ tree.clearSelection();
+ List<TreePath> selectionPaths = new ArrayList<TreePath>();
+ boolean addedPaths = false;
+ // Keep track of the last tree path
+ TreePath lastPath = null;
+ // finds all the TreePaths to select
+ for (PlayPenComponent comp : pp.getSelectedItems()) {
+ TreePath tp = tree.getTreePathForNode((OLAPObject)
comp.getModel());
+ if (!selectionPaths.contains(tp)) {
+ selectionPaths.add(tp);
+ addedPaths = true;
+ lastPath = tp;
+ }
+
+ if (comp instanceof VirtualCubePane) {
+ for (OLAPObject oo :((VirtualCubePane)
comp).getSelectedItems()) {
+ tp = tree.getTreePathForNode(oo);
+ if (!selectionPaths.contains(tp)) {
+ selectionPaths.add(tp);
+ addedPaths = true;
+ lastPath = tp;
+ }
+ }
+ } else if (comp instanceof CubePane) {
+ for (OLAPObject oo :((CubePane)
comp).getSelectedItems()) {
+ tp = tree.getTreePathForNode(oo);
+ if (!selectionPaths.contains(tp)) {
+ selectionPaths.add(tp);
+ addedPaths = true;
+ lastPath = tp;
+ }
+ }
+ } else if (comp instanceof DimensionPane) {
+ for (OLAPObject oo :((DimensionPane)
comp).getSelectedItems()) {
+ tp = tree.getTreePathForNode(oo);
+ if (!selectionPaths.contains(tp)) {
+ selectionPaths.add(tp);
+ addedPaths = true;
+ lastPath = tp;
+ }
+ }
+ for (PaneSection<? extends Level>
sect :((DimensionPane) comp).getSelectedSections()) {
+ Hierarchy hierarchy;
+ if (sect instanceof HierarchySection) {
+ hierarchy = ((HierarchySection)
sect).getHierarchy();
+ } else {
+ throw new IllegalArgumentException("Unknown
section type " + sect.getClass() + " in a DimensionPane!");
+ }
+ tp = tree.getTreePathForNode(hierarchy);
+ if (!selectionPaths.contains(tp)) {
+ selectionPaths.add(tp);
+ addedPaths = true;
+ lastPath = tp;
+ }
+ }
+ } else if (comp instanceof UsageComponent) {
+ tp = tree.getTreePathForNode(((UsageComponent)
comp).getModel());
+ if (!selectionPaths.contains(tp)) {
+ selectionPaths.add(tp);
+ addedPaths = true;
+ lastPath = tp;
+ }
+ }
+ }
+
+ // Scroll to last tree path.
+ if (lastPath != null) {
+ tree.scrollPathToVisible(lastPath);
+ }
+
+ tree.setSelectionPaths(selectionPaths.toArray(new
TreePath[selectionPaths.size()]));
+ if (addedPaths) {
+ tree.clearNonPlayPenSelections();
+ }
+ }
+
+ /**
+ * Selects the corresponding objects from the give TreePaths on
the PlayPen.
+ *
+ * @param treePaths TreePaths containing the objects to select.
+ */
+ private void selectInPlayPen(TreePath[] treePaths) {
+ if (eventDepth != 1) return;
+ if (treePaths == null) {
+ pp.selectNone();
+ } else {
+ List<OLAPObject> objects = new ArrayList<OLAPObject>();
+ for (TreePath tp : treePaths) {
+ OLAPObject obj = (OLAPObject)
tp.getLastPathComponent();
+ // only select playpen represented objects.
+ if ((obj instanceof Cube || obj instanceof VirtualCube
|| obj instanceof Measure
+ || obj instanceof CubeDimension || obj
instanceof VirtualCubeMeasure
+ || obj instanceof Level || obj instanceof
Hierarchy) &&
+ !objects.contains(obj)) {
+ objects.add(obj);
+ }
+ }
+ try {
+ pp.selectObjects(objects, tree);
+ } catch (ArchitectException e) {
+ throw new ArchitectRuntimeException(e);
+ }
+ }
+ }
+
+ public void itemDeselected(SelectionEvent e) {
+ try {
+ eventDepth++;
+ updateOLAPTree();
+ } finally {
+ eventDepth--;
+ }
+ }
+
+ public void itemSelected(SelectionEvent e) {
+ try {
+ eventDepth++;
+ updateOLAPTree();
+ } finally {
+ eventDepth--;
+ }
+ }
+
+ public void valueChanged(TreeSelectionEvent e) {
+ try {
+ eventDepth++;
+ selectInPlayPen(((JTree)
e.getSource()).getSelectionPaths());
+ } finally {
+ eventDepth--;
+ }
+ }
+
+ public void PlayPenComponentAdded(PlayPenContentEvent e) {
+ if (e.getPlayPenComponent() instanceof CubePane) {
+ ((CubePane)
e.getPlayPenComponent()).addItemSelectionListener(this);
+ }
+ }
+
+ public void PlayPenComponentRemoved(PlayPenContentEvent e) {
+ if (e.getPlayPenComponent() instanceof CubePane) {
+ ((CubePane)
e.getPlayPenComponent()).removeItemSelectionListener(this);
+ }
+ }
+
+ public void itemsDeselected(ItemSelectionEvent<Cube, OLAPObject>
e) {
+ try {
+ eventDepth++;
+ updateOLAPTree();
+ } finally {
+ eventDepth--;
+ }
+ }
+
+ public void itemsSelected(ItemSelectionEvent<Cube, OLAPObject> e) {
+ try {
+ eventDepth++;
+ updateOLAPTree();
+ } finally {
+ eventDepth--;
+ }
}
}
}
Modified: trunk/src/ca/sqlpower/architect/swingui/olap/OLAPTree.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/olap/OLAPTree.java (original)
+++ trunk/src/ca/sqlpower/architect/swingui/olap/OLAPTree.java Tue Aug 26
15:43:14 2008
@@ -21,6 +21,8 @@
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+import java.util.List;
import javax.swing.JPopupMenu;
import javax.swing.JTree;
@@ -29,7 +31,14 @@
import org.apache.log4j.Logger;
import ca.sqlpower.architect.olap.OLAPObject;
+import ca.sqlpower.architect.olap.MondrianModel.Cube;
+import ca.sqlpower.architect.olap.MondrianModel.CubeDimension;
+import ca.sqlpower.architect.olap.MondrianModel.Hierarchy;
+import ca.sqlpower.architect.olap.MondrianModel.Level;
+import ca.sqlpower.architect.olap.MondrianModel.Measure;
import ca.sqlpower.architect.olap.MondrianModel.Schema;
+import ca.sqlpower.architect.olap.MondrianModel.VirtualCube;
+import ca.sqlpower.architect.olap.MondrianModel.VirtualCubeMeasure;
import ca.sqlpower.architect.swingui.ArchitectSwingSession;
import ca.sqlpower.swingui.JTreeCollapseAllAction;
import ca.sqlpower.swingui.JTreeExpandAllAction;
@@ -43,7 +52,10 @@
private final JTreeCollapseAllAction collapseAllAction;
private final JTreeExpandAllAction expandAllAction;
+ private Schema schema;
+
public OLAPTree(ArchitectSwingSession session, OLAPEditSession
oSession, Schema schema) {
+ this.schema = schema;
setModel(new OLAPTreeModel(schema));
addMouseListener(new PopupListener());
collapseAllAction = new JTreeCollapseAllAction(this, "Collapse
All");
@@ -102,4 +114,50 @@
}
}
}
+
+ /**
+ * Returns the TreePath built from the getParent() of the given
OLAPObject.
+ *
+ * @param obj OLAPObject to build TreePath upon.
+ * @return TreePath for given object.
+ */
+ public TreePath getTreePathForNode(OLAPObject o) {
+ List<OLAPObject> path = new ArrayList<OLAPObject>();
+ while (o != null) {
+ path.add(0, o);
+ if (o == schema) break;
+ o = o.getParent();
+ }
+ return new TreePath(path.toArray());
+ }
+
+ /**
+ * Removes all selections of objects that are not represented on the
playpen.
+ *
+ */
+ public void clearNonPlayPenSelections() {
+ if (getSelectionPaths() == null) return;
+ for (TreePath tp : getSelectionPaths()) {
+ OLAPObject obj = (OLAPObject) tp.getLastPathComponent();
+ if (!(obj instanceof Cube || obj instanceof VirtualCube || obj
instanceof Measure
+ || obj instanceof CubeDimension || obj instanceof
VirtualCubeMeasure
+ || obj instanceof Level || obj instanceof Hierarchy)) {
+ removeSelectionPath(tp);
+ }
+ }
+ }
+
+ /**
+ * Checks to see if the Schema reference from the the OLAPTree is the
+ * same as the one held by the PlayPen. If it is, we are looking at
the
+ * Schema.
+ */
+ protected boolean isSchemaNode(TreePath tp) {
+ if (tp == null) {
+ return false;
+ } else {
+ return schema == tp.getLastPathComponent();
+ }
+ }
+
}