Revision: 3538
Author: [email protected]
Date: Fri May 14 11:58:04 2010
Log: The ColumnEditPanel now allows selection of domains, not just data types. Refactored a Popup creator from Wabit into the library. This popup was used in Wabit to choose cubes in an OLAP query. It has been moved into the library to allow the ColumnEditPanel in Architect to use a popup for choosing domains and data types.

A new TreeCellRenderer has been created to render domains and data types in the tree displayed in the Popup, as well as the Domain Editor Panel. Each cell of the tree is rendered to display user friendly text, icons, and tooltips.

If two or more users are modifying the same column type and one user commits the change, the users who have not committed the change will see that their domain/type tree will be highlighted in red or yellow, just like the other components in the panel do.
http://code.google.com/p/power-architect/source/detail?r=3538

Added:
/trunk/src/main/java/ca/sqlpower/architect/swingui/SQLTypeTreeCellRenderer.java
 /trunk/src/main/java/ca/sqlpower/architect/swingui/SQLTypeTreeModel.java
/trunk/src/main/java/ca/sqlpower/architect/swingui/SQLTypeTreePopupAction.java
 /trunk/src/main/resources/ca/sqlpower/architect/swingui/icons
 /trunk/src/main/resources/ca/sqlpower/architect/swingui/icons/category.png
 /trunk/src/main/resources/ca/sqlpower/architect/swingui/icons/domain.png
 /trunk/src/main/resources/ca/sqlpower/architect/swingui/icons/type.png
Modified:
 /trunk/regress/ca/sqlpower/architect/StubArchitectSession.java
 /trunk/regress/ca/sqlpower/architect/TestingArchitectSession.java
 /trunk/regress/ca/sqlpower/architect/swingui/TestColumnEditPanel.java
/trunk/regress/ca/sqlpower/architect/swingui/TestingArchitectSwingSession.java
 /trunk/src/main/java/ca/sqlpower/architect/ArchitectProject.java
 /trunk/src/main/java/ca/sqlpower/architect/ArchitectSession.java
 /trunk/src/main/java/ca/sqlpower/architect/ArchitectSessionImpl.java
/trunk/src/main/java/ca/sqlpower/architect/enterprise/ArchitectClientSideSession.java
 /trunk/src/main/java/ca/sqlpower/architect/enterprise/DomainCategory.java
/trunk/src/main/java/ca/sqlpower/architect/swingui/ArchitectSwingSessionImpl.java
 /trunk/src/main/java/ca/sqlpower/architect/swingui/ColumnEditPanel.java
 /trunk/src/main/resources/ca/sqlpower/architect/swingui/messages.properties

=======================================
--- /dev/null
+++ /trunk/src/main/java/ca/sqlpower/architect/swingui/SQLTypeTreeCellRenderer.java Fri May 14 11:58:04 2010
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2010, SQL Power Group Inc.
+ *
+ * This file is part of Power*Architect.
+ *
+ * Power*Architect is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Power*Architect 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package ca.sqlpower.architect.swingui;
+
+import java.awt.Component;
+
+import javax.swing.ImageIcon;
+import javax.swing.JTree;
+import javax.swing.tree.DefaultTreeCellRenderer;
+import javax.swing.tree.TreeCellRenderer;
+
+import org.apache.log4j.Logger;
+
+import ca.sqlpower.architect.ArchitectProject;
+import ca.sqlpower.architect.enterprise.DomainCategory;
+import ca.sqlpower.sqlobject.UserDefinedSQLType;
+
+/**
+ * This {...@link TreeCellRenderer} is used for rendering {...@link JTree}s that used
+ * the {...@link SQLTypeTreeModel}.
+ */
+public class SQLTypeTreeCellRenderer extends DefaultTreeCellRenderer {
+
+ private static final Logger logger = Logger.getLogger(SQLTypeTreeCellRenderer.class);
+
+ public static final ImageIcon CATEGORY_ICON = new ImageIcon(SQLTypeTreeCellRenderer.class.getResource("icons/category.png")); + public static final ImageIcon DOMAIN_ICON = new ImageIcon(SQLTypeTreeCellRenderer.class.getResource("icons/domain.png")); + public static final ImageIcon TYPE_ICON = new ImageIcon(SQLTypeTreeCellRenderer.class.getResource("icons/type.png"));
+
+    public SQLTypeTreeCellRenderer() {
+        super();
+    }
+
+    @Override
+ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded,
+            boolean leaf, int row, boolean hasFocus) {
+        if (value instanceof ArchitectProject) {
+            setIcon(null);
+
+ if (((ArchitectProject) value).getSession().isEnterpriseSession()) {
+                setText("Domains & Data Types");
+            } else {
+                setText("Data Types");
+            }
+        } else if (value instanceof UserDefinedSQLType) {
+            UserDefinedSQLType type = (UserDefinedSQLType) value;
+
+            if (type.getParent() instanceof DomainCategory) {
+                setIcon(DOMAIN_ICON);
+            } else {
+                setIcon(TYPE_ICON);
+            }
+            setText(type.getName());
+        } else if (value instanceof DomainCategory) {
+            setIcon(CATEGORY_ICON);
+            setText(((DomainCategory) value).getName());
+        }
+        setToolTipText(getText());
+        return this;
+    }
+
+}
=======================================
--- /dev/null
+++ /trunk/src/main/java/ca/sqlpower/architect/swingui/SQLTypeTreeModel.java Fri May 14 11:58:04 2010
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2010, SQL Power Group Inc.
+ *
+ * This file is part of Power*Architect.
+ *
+ * Power*Architect is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Power*Architect 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package ca.sqlpower.architect.swingui;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import javax.swing.event.TreeModelListener;
+import javax.swing.tree.TreeModel;
+import javax.swing.tree.TreePath;
+
+import org.apache.log4j.Logger;
+
+import ca.sqlpower.architect.ArchitectProject;
+import ca.sqlpower.architect.ArchitectSession;
+import ca.sqlpower.architect.enterprise.DomainCategory;
+import ca.sqlpower.object.SPObject;
+import ca.sqlpower.sqlobject.UserDefinedSQLType;
+
+/**
+ * This {...@link TreeModel} defines the hierarchy of {...@link UserDefinedSQLType}s
+ * and {...@link DomainCategory}s under an {...@link ArchitectProject}.
+ *
+ */
+public class SQLTypeTreeModel implements TreeModel {
+
+ private static final Logger logger = Logger.getLogger(SQLTypeTreeModel.class);
+
+    private final ArchitectSession session;
+
+    /**
+     * This {...@link Comparator} can compare {...@link UserDefinedSQLType} and
+ * {...@link DomainCategory} objects. {...@link UserDefinedSQLType}s always come + * after {...@link DomainCategory}s. Comparison between objects with different
+     * parents should never occur.
+     */
+ private final Comparator<SPObject> typeComparator = new Comparator<SPObject>() {
+
+        public int compare(SPObject spo1, SPObject spo2) {
+            if (spo1.getParent() != spo2.getParent()) {
+                throw new ClassCastException("Cannot compare " +
+                               spo1.getClass().getSimpleName() + " and " +
+                               DomainCategory.class.getSimpleName() + " objects 
with " +
+                               "different parents.");
+            }
+
+ if (spo1 instanceof UserDefinedSQLType && spo2 instanceof UserDefinedSQLType) { + return Integer.signum(spo1.getName().compareTo(spo2.getName())); + } else if (spo1 instanceof DomainCategory && spo2 instanceof DomainCategory) { + return Integer.signum(spo1.getName().compareTo(spo2.getName()));
+            } else if (spo1 instanceof DomainCategory) {
+                return -1;
+            } else {
+                return 1;
+            }
+        }
+    };
+
+    public SQLTypeTreeModel(ArchitectSession session) {
+        this.session = session;
+    }
+
+    public SPObject getChild(Object parent, int index) {
+        // If the parent is the delegate ArchitectProject, get the child at
+        // the specified index which should be of type UserDefinedSQLType
+        // or DomainCategory.
+        if (session.getWorkspace() == parent) {
+            return getChildren().get(index);
+
+        // If the parent is DomainCategory, get the child at the specified
+        // index which should be of type UserDefinedSQLType.
+        } else if (parent instanceof DomainCategory &&
+                session.getDomainCategories().contains(parent)) {
+            return getDomainTypes((DomainCategory) parent).get(index);
+        }
+
+        return null;
+    }
+
+    public int getChildCount(Object parent) {
+        if (session.getWorkspace() == parent) {
+            return getChildren().size();
+        } else if (parent instanceof DomainCategory &&
+                session.getDomainCategories().contains(parent)) {
+            return getDomainTypes((DomainCategory) parent).size();
+        }
+        return 0;
+    }
+
+    /**
+     * Returns the sorted {...@link List} of {...@link UserDefinedSQLType}s and
+     * {...@link DomainCategory}s that are children of a given project.
+     */
+    private List<? extends SPObject> getChildren() {
+        List<SPObject> children = new ArrayList<SPObject>();
+        children.addAll(session.getDomainCategories());
+        children.addAll(session.getSQLTypes());
+        Collections.sort(children, typeComparator);
+        return Collections.unmodifiableList(children);
+    }
+
+    /**
+ * Creates the sorted {...@link List} of {...@link UserDefinedSQLType}s under a
+     * given {...@link DomainCategory}.
+     *
+     * @param category
+     *            The {...@link DomainCategory} to get the children from.
+     * @return The {...@link List} of {...@link UserDefinedSQLType}s that are
+     *         contained under the given {...@link DomainCategory}.
+     */
+ private List<UserDefinedSQLType> getDomainTypes(DomainCategory category) { + List<UserDefinedSQLType> children = new ArrayList<UserDefinedSQLType>();
+        children.addAll(category.getChildren(UserDefinedSQLType.class));
+        Collections.sort(children, typeComparator);
+        return children;
+    }
+
+    public int getIndexOfChild(Object parent, Object child) {
+        if (parent == null || child == null) {
+            return -1;
+        } else if (session.getWorkspace() == parent) {
+            return getChildren().indexOf(child);
+        } else if (parent instanceof DomainCategory &&
+                session.getDomainCategories().contains(parent)) {
+            if (child instanceof UserDefinedSQLType) {
+ return getDomainTypes((DomainCategory) parent).indexOf(child);
+            }
+        }
+        return -1;
+    }
+
+    public ArchitectProject getRoot() {
+        return session.getWorkspace();
+    }
+
+    public boolean isLeaf(Object node) {
+        return (node instanceof UserDefinedSQLType);
+    }
+
+    public void addTreeModelListener(TreeModelListener l) {
+        // no-op
+    }
+
+    public void removeTreeModelListener(TreeModelListener l) {
+        // no-op
+    }
+
+    public void valueForPathChanged(TreePath path, Object newValue) {
+        // no-op
+    }
+
+}
+
=======================================
--- /dev/null
+++ /trunk/src/main/java/ca/sqlpower/architect/swingui/SQLTypeTreePopupAction.java Fri May 14 11:58:04 2010
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2010, SQL Power Group Inc.
+ *
+ * This file is part of Power*Architect.
+ *
+ * Power*Architect is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Power*Architect 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package ca.sqlpower.architect.swingui;
+
+import java.awt.Point;
+import java.awt.event.ActionEvent;
+
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.JButton;
+import javax.swing.JPanel;
+import javax.swing.JTree;
+import javax.swing.Popup;
+import javax.swing.SwingUtilities;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.tree.TreePath;
+
+import ca.sqlpower.sqlobject.UserDefinedSQLType;
+import ca.sqlpower.swingui.PopupListenerHandler;
+import ca.sqlpower.swingui.SPSUtils;
+
+/**
+ * This {...@link Action} creates a {...@link Popup} for choosing domains and data
+ * types in the {...@link ColumnEditPanel}.
+ */
+public class SQLTypeTreePopupAction extends AbstractAction {
+
+    private final JPanel panel;
+    private final JTree colType;
+    private final JButton typeChooserButton;
+    private PopupListenerHandler popupListenerHandler;
+
+    /**
+ * Creates a new {...@link SQLTypeTreePopupAction} given the {...@link JPanel} the
+     * created {...@link Popup} should appear on, the {...@link JTree} the
+ * {...@link Popup} should embed, and the {...@link JButton} that performs this
+     * action.
+     *
+     * @param panel
+     *            The {...@link JPanel} this {...@link Popup} should appear on.
+     * @param colType
+     *            The {...@link JTree} the {...@link Popup} should embed.
+     * @param typeChooserButton
+     *            The {...@link JButton} that should perform this action.
+     */
+ public SQLTypeTreePopupAction(JPanel panel, JTree colType, JButton typeChooserButton) {
+        super();
+
+        this.panel = panel;
+        this.colType = colType;
+        this.typeChooserButton = typeChooserButton;
+    }
+
+    /**
+     * Creates a {...@link Popup} if it is not visible, and connects the
+     * appropriate listeners to check for when to hide the {...@link Popup}.
+     * Otherwise, it hides the {...@link Popup} and disconnects the listeners.
+     */
+    public void actionPerformed(ActionEvent e) {
+ if (popupListenerHandler != null && popupListenerHandler.isPopupVisible()) {
+            popupListenerHandler.cleanup();
+        } else {
+            Point windowLocation = new Point(0, 0);
+ SwingUtilities.convertPointToScreen(windowLocation, typeChooserButton);
+            windowLocation.y += typeChooserButton.getHeight();
+
+            // Popup the type choosing tree and attach the
+            // popup listener handler to the tree
+            popupListenerHandler =
+                SPSUtils.popupComponent(panel, colType, windowLocation);
+            popupListenerHandler.connect();
+            colType.addTreeSelectionListener(new TreeSelectionListener() {
+                public void valueChanged(TreeSelectionEvent e) {
+                    TreePath path = e.getNewLeadSelectionPath();
+                    Object node = path.getLastPathComponent();
+                    if (node instanceof UserDefinedSQLType) {
+                        popupListenerHandler.cleanup();
+                    }
+                }
+            });
+        }
+    }
+
+}
=======================================
--- /dev/null   
+++ /trunk/src/main/resources/ca/sqlpower/architect/swingui/icons/category.png Fri May 14 11:58:04 2010
Binary file, no diff available.
=======================================
--- /dev/null   
+++ /trunk/src/main/resources/ca/sqlpower/architect/swingui/icons/domain.png Fri May 14 11:58:04 2010
Binary file, no diff available.
=======================================
--- /dev/null   
+++ /trunk/src/main/resources/ca/sqlpower/architect/swingui/icons/type.png Fri May 14 11:58:04 2010
Binary file, no diff available.
=======================================
--- /trunk/regress/ca/sqlpower/architect/StubArchitectSession.java Mon May 10 11:20:07 2010 +++ /trunk/regress/ca/sqlpower/architect/StubArchitectSession.java Fri May 14 11:58:04 2010
@@ -23,6 +23,7 @@
 import java.util.List;

 import ca.sqlpower.architect.ddl.DDLGenerator;
+import ca.sqlpower.architect.enterprise.DomainCategory;
 import ca.sqlpower.architect.profile.ProfileManager;
 import ca.sqlpower.sql.DataSourceCollection;
 import ca.sqlpower.sql.JDBCDataSource;
@@ -184,4 +185,9 @@
         // TODO Auto-generated method stub
         return null;
     }
-}
+
+    public List<DomainCategory> getDomainCategories() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+}
=======================================
--- /trunk/regress/ca/sqlpower/architect/TestingArchitectSession.java Mon May 10 11:20:07 2010 +++ /trunk/regress/ca/sqlpower/architect/TestingArchitectSession.java Fri May 14 11:58:04 2010
@@ -36,6 +36,7 @@
 import java.util.List;

 import ca.sqlpower.architect.ddl.DDLGenerator;
+import ca.sqlpower.architect.enterprise.DomainCategory;
 import ca.sqlpower.architect.olap.OLAPRootObject;
 import ca.sqlpower.architect.profile.ProfileManager;
 import ca.sqlpower.sql.DataSourceCollection;
@@ -219,4 +220,9 @@
public <T> UserPrompter createListUserPrompter(String question, List<T> responses, T defaultResponse) { return defaultUPF.createListUserPrompter(question, responses, defaultResponse);
     }
-}
+
+    public List<DomainCategory> getDomainCategories() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+}
=======================================
--- /trunk/regress/ca/sqlpower/architect/swingui/TestColumnEditPanel.java Tue May 4 14:48:14 2010 +++ /trunk/regress/ca/sqlpower/architect/swingui/TestColumnEditPanel.java Fri May 14 11:58:04 2010
@@ -86,7 +86,7 @@

assertEquals("Wrong column logical name",col3.getName(),panel.getColLogicalName().getText()); assertEquals("Wrong Precision",col3.getPrecision(),((Integer) panel.getColPrec().getValue()).intValue()); - assertEquals("Wrong type",col3.getType(),((UserDefinedSQLType)panel.getColType().getSelectedItem()).getType().intValue()); + assertEquals("Wrong type",col3.getType(),((UserDefinedSQLType)panel.getColType().getLastSelectedPathComponent()).getType().intValue()); assertEquals("Wrong Scale",col3.getScale(),((Integer) (panel.getColScale().getValue())).intValue()); assertEquals(col3.isAutoIncrement(), ((YesNoEnum) panel.getColAutoInc().getSelectedItem()).getValue()); assertEquals(col3.isPrimaryKey(), panel.getColInPK().getModel().isSelected());
@@ -98,7 +98,7 @@

assertEquals("Wrong column logical name",col2.getName(),panel.getColLogicalName().getText()); assertEquals("Wrong Precision",col2.getPrecision(),((Integer) panel.getColPrec().getValue()).intValue()); - assertEquals("Wrong type",col2.getType(),((UserDefinedSQLType)panel.getColType().getSelectedItem()).getType().intValue()); + assertEquals("Wrong type",col2.getType(),((UserDefinedSQLType)panel.getColType().getLastSelectedPathComponent()).getType().intValue()); assertEquals("Wrong Scale",col2.getScale(),((Integer) (panel.getColScale().getValue())).intValue()); assertEquals(col2.isAutoIncrement(), ((YesNoEnum) panel.getColAutoInc().getSelectedItem()).getValue()); assertEquals(col2.isPrimaryKey(), panel.getColInPK().getModel().isSelected());
@@ -110,7 +110,7 @@

                panel.getColPhysicalName().setText("CHANGED");
                panel.getColLogicalName().setText("Easier Use Column Name");
-               panel.getColType().setSelectedIndex(1);
+               panel.getColType().setSelectionRow(1);
                panel.getColPrec().setValue(new Integer(1234));
                
panel.getTypeOverrideMap().get(panel.getColPrec()).setSelected(true);
                panel.getColScale().setValue(new Integer(5432));
@@ -128,7 +128,7 @@
assertEquals("Wrong column physical name","CHANGED",col2.getPhysicalName()); assertEquals("Wrong column logical name","Easier Use Column Name",col2.getName());
                assertEquals("Wrong Precision",1234,col2.getPrecision());
-               assertEquals("Wrong type",2,col2.getType());
+               assertEquals("Wrong type",1,col2.getType());
                assertEquals("Wrong Scale",5432,col2.getScale());
                assertTrue(col2.isAutoIncrement());
                assertTrue(col2.isPrimaryKey());
@@ -141,6 +141,7 @@

                panel.getColPhysicalName().setText("CHANGED");
                panel.getColLogicalName().setText("Easier Use Column Name");
+               panel.getColType().setSelectionRow(1);
                panel.getColPrec().setValue(new Integer(1234));
                panel.getColScale().setValue(new Integer(5432));
                panel.getColAutoInc().setSelectedItem(YesNoEnum.YES);
@@ -150,6 +151,7 @@

assertEquals("Wrong column physical name","Physical Name 2",col2.getPhysicalName());
                assertEquals("Wrong column logical name","Column 
2",col2.getName());
+               assertEquals("Wrong column data type", 2, col2.getType());
                assertEquals("Wrong Precision",3,col2.getPrecision());
                assertEquals("Wrong Scale",4,col2.getScale());
                assertFalse(col2.isAutoIncrement());
=======================================
--- /trunk/regress/ca/sqlpower/architect/swingui/TestingArchitectSwingSession.java Mon May 10 11:20:07 2010 +++ /trunk/regress/ca/sqlpower/architect/swingui/TestingArchitectSwingSession.java Fri May 14 11:58:04 2010
@@ -41,6 +41,7 @@
 import ca.sqlpower.architect.ddl.DDLGenerator;
 import ca.sqlpower.architect.ddl.GenericDDLGenerator;
 import ca.sqlpower.architect.enterprise.ArchitectClientSideSession;
+import ca.sqlpower.architect.enterprise.DomainCategory;
 import ca.sqlpower.architect.etl.kettle.KettleJob;
 import ca.sqlpower.architect.olap.OLAPRootObject;
 import ca.sqlpower.architect.olap.OLAPSession;
@@ -496,4 +497,8 @@
public <T> UserPrompter createListUserPrompter(String question, List<T> responses, T defaultResponse) { return new DefaultUserPrompterFactory().createListUserPrompter(question, responses, defaultResponse);
     }
-}
+
+    public List<DomainCategory> getDomainCategories() {
+        return Collections.emptyList();
+    }
+}
=======================================
--- /trunk/src/main/java/ca/sqlpower/architect/ArchitectProject.java Mon May 10 12:30:08 2010 +++ /trunk/src/main/java/ca/sqlpower/architect/ArchitectProject.java Fri May 14 11:58:04 2010
@@ -412,8 +412,8 @@
         allChildren.add(kettleSettings);
         allChildren.addAll(users);
         allChildren.addAll(groups);
-        allChildren.addAll(domainCategories);
         allChildren.addAll(sqlTypes);
+        allChildren.addAll(domainCategories);
         return allChildren;
     }

@@ -574,15 +574,6 @@
         return true;
     }

-    /**
-     * Returns the list of all child {...@link UserDefinedSQLType} for this
-     * {...@link ArchitectProject}
-     */
-    @NonProperty
-    public List<UserDefinedSQLType> getSqlTypes() {
-        return sqlTypes;
-    }
-
     @NonBound
     public SPObject getObjectInTree(String uuid) {
         return projectMap.get(uuid);
=======================================
--- /trunk/src/main/java/ca/sqlpower/architect/ArchitectSession.java Mon May 3 16:11:03 2010 +++ /trunk/src/main/java/ca/sqlpower/architect/ArchitectSession.java Fri May 14 11:58:04 2010
@@ -23,6 +23,7 @@
 import java.util.List;

 import ca.sqlpower.architect.ddl.DDLGenerator;
+import ca.sqlpower.architect.enterprise.DomainCategory;
 import ca.sqlpower.architect.profile.ProfileManager;
 import ca.sqlpower.sql.DataSourceCollection;
 import ca.sqlpower.sql.JDBCDataSource;
@@ -140,6 +141,12 @@
* Returns a list of {...@link UserDefinedSQLType} defined in this session.
      */
     public List<UserDefinedSQLType> getSQLTypes();
+
+    /**
+ * Returns a list of {...@link DomainCategory}s defined in this session. Only
+     * enterprise sessions should contain domains.
+     */
+    public List<DomainCategory> getDomainCategories();

     /**
      * Searches the session for a {...@link UserDefinedSQLType} with the given
=======================================
--- /trunk/src/main/java/ca/sqlpower/architect/ArchitectSessionImpl.java Mon May 10 11:20:07 2010 +++ /trunk/src/main/java/ca/sqlpower/architect/ArchitectSessionImpl.java Fri May 14 11:58:04 2010
@@ -23,10 +23,12 @@
 import java.beans.PropertyChangeSupport;
 import java.sql.SQLException;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;

 import ca.sqlpower.architect.ddl.DDLGenerator;
 import ca.sqlpower.architect.ddl.GenericDDLGenerator;
+import ca.sqlpower.architect.enterprise.DomainCategory;
 import ca.sqlpower.architect.profile.ProfileManager;
 import ca.sqlpower.architect.profile.ProfileManagerImpl;
 import ca.sqlpower.sql.DataSourceCollection;
@@ -279,5 +281,9 @@
public <T> UserPrompter createListUserPrompter(String question, List<T> responses, T defaultResponse) { return userPrompterFactory.createListUserPrompter(question, responses, defaultResponse);
     }
+
+    public List<DomainCategory> getDomainCategories() {
+        return Collections.emptyList();
+    }
 }

=======================================
--- /trunk/src/main/java/ca/sqlpower/architect/enterprise/ArchitectClientSideSession.java Mon May 10 22:46:35 2010 +++ /trunk/src/main/java/ca/sqlpower/architect/enterprise/ArchitectClientSideSession.java Fri May 14 11:58:04 2010
@@ -8,6 +8,7 @@
 import java.net.URISyntaxException;
 import java.text.ParseException;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -254,7 +255,12 @@

                                            @Override
                                            public List<UserDefinedSQLType> 
getSQLTypes() {
-                                               return 
ArchitectClientSideSession.this.getSQLTypes();
+ List<UserDefinedSQLType> types = new ArrayList<UserDefinedSQLType>();
+                                               
types.addAll(ArchitectClientSideSession.this.getSQLTypes());
+ for (DomainCategory dc : ArchitectClientSideSession.this.getDomainCategories()) {
+                                                   
types.addAll(dc.getChildren(UserDefinedSQLType.class));
+                                               }
+                                               return types;
                                            }

                                            @Override
@@ -954,7 +960,17 @@
      */
     @Override
     public List<UserDefinedSQLType> getSQLTypes() {
- final List<UserDefinedSQLType> sqlTypes = getSystemWorkspace().getSqlTypes();
-        return sqlTypes;
+        return Collections.unmodifiableList(
+ getSystemWorkspace().getChildren(UserDefinedSQLType.class));
+    }
+
+    /**
+ * Returns the {...@link List} of {...@link DomainCategory}s in this session's
+     * system workspace.
+     */
+    @Override
+    public List<DomainCategory> getDomainCategories() {
+        return Collections.unmodifiableList(
+                getSystemWorkspace().getChildren(DomainCategory.class));
     }
 }
=======================================
--- /trunk/src/main/java/ca/sqlpower/architect/enterprise/DomainCategory.java Mon Apr 19 14:18:19 2010 +++ /trunk/src/main/java/ca/sqlpower/architect/enterprise/DomainCategory.java Fri May 14 11:58:04 2010
@@ -86,6 +86,7 @@
     @Override
     protected void addChildImpl(SPObject child, int index) {
         children.add(index, (UserDefinedSQLType) child);
+        child.setParent(this);
         fireChildAdded(UserDefinedSQLType.class, child, index);
     }

=======================================
--- /trunk/src/main/java/ca/sqlpower/architect/swingui/ArchitectSwingSessionImpl.java Mon May 10 22:46:35 2010 +++ /trunk/src/main/java/ca/sqlpower/architect/swingui/ArchitectSwingSessionImpl.java Fri May 14 11:58:04 2010
@@ -61,6 +61,7 @@
 import ca.sqlpower.architect.ProjectSettings.ColumnVisibility;
 import ca.sqlpower.architect.ddl.DDLGenerator;
 import ca.sqlpower.architect.enterprise.ArchitectClientSideSession;
+import ca.sqlpower.architect.enterprise.DomainCategory;
 import ca.sqlpower.architect.enterprise.NetworkConflictResolver;
 import ca.sqlpower.architect.etl.kettle.KettleJob;
 import ca.sqlpower.architect.olap.OLAPRootObject;
@@ -1229,4 +1230,8 @@
public <T> UserPrompter createListUserPrompter(String question, List<T> responses, T defaultResponse) { return swinguiUserPrompterFactory.createListUserPrompter(question, responses, defaultResponse);
     }
-}
+
+    public List<DomainCategory> getDomainCategories() {
+        return delegateSession.getDomainCategories();
+    }
+}
=======================================
--- /trunk/src/main/java/ca/sqlpower/architect/swingui/ColumnEditPanel.java Mon May 10 19:46:07 2010 +++ /trunk/src/main/java/ca/sqlpower/architect/swingui/ColumnEditPanel.java Fri May 14 11:58:04 2010
@@ -27,20 +27,17 @@
 import java.awt.event.ComponentEvent;
 import java.awt.event.FocusAdapter;
 import java.awt.event.FocusEvent;
-import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
 import java.beans.PropertyChangeEvent;
 import java.sql.DatabaseMetaData;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;

+import javax.swing.JButton;
 import javax.swing.JCheckBox;
 import javax.swing.JComboBox;
 import javax.swing.JComponent;
@@ -51,6 +48,7 @@
 import javax.swing.JSpinner;
 import javax.swing.JTextArea;
 import javax.swing.JTextField;
+import javax.swing.JTree;
 import javax.swing.SpinnerNumberModel;
 import javax.swing.SwingUtilities;
 import javax.swing.UIManager;
@@ -60,7 +58,11 @@
 import javax.swing.event.ChangeListener;
 import javax.swing.event.DocumentEvent;
 import javax.swing.event.DocumentListener;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
 import javax.swing.text.JTextComponent;
+import javax.swing.tree.TreePath;
+import javax.swing.tree.TreeSelectionModel;

 import org.apache.log4j.Logger;

@@ -166,7 +168,9 @@

     private final JTextField colPhysicalName;

-    private final JComboBox colType;
+    private final JButton typeChooserButton;
+
+    private final JTree colType;

     private final JSpinner colScale;

@@ -181,7 +185,7 @@
     private final JCheckBox colInPK;

     private final JComboBox colAutoInc;
-
+
     /**
* Text field for the name of the sequence that will generate this column's
      * default values. In multi-edit mode, this component will be null.
@@ -210,7 +214,7 @@
         this(Collections.singleton(col), session);
     }

- public ColumnEditPanel(Collection<SQLColumn> cols, ArchitectSwingSession session) throws SQLObjectException { + public ColumnEditPanel(Collection<SQLColumn> cols, final ArchitectSwingSession session) throws SQLObjectException {
         logger.debug("ColumnEditPanel called"); //$NON-NLS-1$

         if (session == null) {
@@ -324,19 +328,29 @@
         if (cols.size() > 1) {
             panel.add(cb, cc.xy(1, row));
         }
-        List<UserDefinedSQLType> typeList = session.getSQLTypes();
- UserDefinedSQLType[] types = new UserDefinedSQLType[typeList.size()];
-        types = typeList.toArray(types);
-        Arrays.sort(types, new Comparator<UserDefinedSQLType>() {
- public int compare(UserDefinedSQLType a, UserDefinedSQLType b) {
-                return a.getName().compareTo(b.getName());
-            }
-        });
-        panel.add(colType = new JComboBox(types), cc.xyw(2, row++, width));
-        componentEnabledMap.put(colType, cb);
-        colType.setSelectedItem(null);
-        colType.addActionListener(this);
-
+
+ typeChooserButton = new JButton(Messages.getString("ColumnEditPanel.chooseType"));
+
+        if (session.isEnterpriseSession()) {
+            colType = new JTree(new SQLTypeTreeModel(
+                    session.getEnterpriseSession()));
+        } else {
+            colType = new JTree(new SQLTypeTreeModel(session));
+        }
+
+        colType.setCellRenderer(new SQLTypeTreeCellRenderer());
+        for (int i = 0; i < colType.getRowCount(); i++) {
+            colType.expandRow(i);
+        }
+        colType.setRootVisible(true);
+        colType.getSelectionModel().setSelectionMode(
+                TreeSelectionModel.SINGLE_TREE_SELECTION);
+
+ typeChooserButton.addActionListener(new SQLTypeTreePopupAction(panel, colType, typeChooserButton));
+
+        componentEnabledMap.put(colType, cb);
+        panel.add(typeChooserButton, cc.xyw(2, row++, 2));
+
         layout.appendRow(RowSpec.decode("5dlu"));
         row++;

@@ -357,8 +371,9 @@
                     colPrec.setEnabled(true);
                 } else {
                     colPrec.setEnabled(false);
-                    if (colType.getSelectedItem() != null) {
- colPrec.setValue(((UserDefinedSQLType) colType.getSelectedItem()).getPrecision( + if (colType.getLastSelectedPathComponent() instanceof UserDefinedSQLType) {
+                        colPrec.setValue(
+ ((UserDefinedSQLType) colType.getLastSelectedPathComponent()).getPrecision( SQLTypePhysicalPropertiesProvider.GENERIC_PLATFORM));
                     }
                 }
@@ -378,8 +393,8 @@
                     colScale.setEnabled(true);
                 } else {
                     colScale.setEnabled(false);
-                    if (colType.getSelectedItem() != null) {
- colScale.setValue(((UserDefinedSQLType) colType.getSelectedItem()).getScale( + if (colType.getLastSelectedPathComponent() instanceof UserDefinedSQLType) { + colScale.setValue(((UserDefinedSQLType) colType.getLastSelectedPathComponent()).getScale( SQLTypePhysicalPropertiesProvider.GENERIC_PLATFORM));
                     }
                 }
@@ -406,9 +421,9 @@
                     colNullable.setEnabled(true);
                 } else {
                     colNullable.setEnabled(false);
-                    if (colType.getSelectedItem() != null) {
+ if (colType.getLastSelectedPathComponent() instanceof UserDefinedSQLType) {
                         colNullable.setSelectedItem(YesNoEnum.valueOf(
- ((UserDefinedSQLType) colType.getSelectedItem()).getNullability() == DatabaseMetaData.columnNullable)); + ((UserDefinedSQLType) colType.getLastSelectedPathComponent()).getNullability() == DatabaseMetaData.columnNullable));
                     }
                 }
                 updateComponents();
@@ -435,9 +450,9 @@
                     colAutoInc.setEnabled(true);
                 } else {
                     colAutoInc.setEnabled(false);
-                    if (colType.getSelectedItem() != null) {
+ if (colType.getLastSelectedPathComponent() instanceof UserDefinedSQLType) {
                         colAutoInc.setSelectedItem(YesNoEnum.valueOf(
- ((UserDefinedSQLType) colType.getSelectedItem()).getAutoIncrement())); + ((UserDefinedSQLType) colType.getLastSelectedPathComponent()).getAutoIncrement()));
                     }
                 }
             }
@@ -463,8 +478,8 @@
                     colDefaultValue.setEnabled(true);
                 } else {
                     colDefaultValue.setEnabled(false);
-                    if (colType.getSelectedItem() != null) {
- colDefaultValue.setText(((UserDefinedSQLType) colType.getSelectedItem()).getDefaultValue( + if (colType.getLastSelectedPathComponent() instanceof UserDefinedSQLType) { + colDefaultValue.setText(((UserDefinedSQLType) colType.getLastSelectedPathComponent()).getDefaultValue( SQLTypePhysicalPropertiesProvider.GENERIC_PLATFORM));
                     }
                 }
@@ -586,11 +601,14 @@
SQLPowerUtils.listenToHierarchy(session.getRootObject(), obsolesenceListener);
         SQLPowerUtils.listenToHierarchy(session.getRootObject(), this);
         panel.addAncestorListener(cleanupListener);
-        colType.addItemListener(new ItemListener() {
-            public void itemStateChanged(ItemEvent e) {
- if (e.getItem() instanceof UserDefinedSQLType && e.getStateChange() == ItemEvent.SELECTED) { - UserDefinedSQLType sqlType = (UserDefinedSQLType) e.getItem();
-                    updateSQLTypeComponents(sqlType, false);
+
+        colType.addTreeSelectionListener(new TreeSelectionListener() {
+            public void valueChanged(TreeSelectionEvent e) {
+                TreePath path = e.getNewLeadSelectionPath();
+                Object selection = path.getLastPathComponent();
+                if (selection instanceof UserDefinedSQLType) {
+ typeChooserButton.setText(((UserDefinedSQLType) selection).getName()); + updateSQLTypeComponents((UserDefinedSQLType) selection, false);
                 }
             }
         });
@@ -610,7 +628,7 @@
return createScaleEditor(); // looks better if both spinners are same
                                     // size
     }
-
+
     /**
* Updates all the UI components to reflect the given column's properties.
      * <p>
@@ -667,6 +685,22 @@
         }
     }

+    private void updateComponent(JTree comp, Object expectedValue) {
+        if (componentEnabledMap.get(comp).isSelected() &&
+ (comp.isSelectionEmpty() || comp.getLastSelectedPathComponent() == expectedValue)) {
+            for (int i = 0; i < comp.getRowCount(); i++) {
+ if (comp.getPathForRow(i).getLastPathComponent() == expectedValue) {
+                    comp.setSelectionRow(i);
+                    typeChooserButton.setText(
+ ((UserDefinedSQLType) expectedValue).getName());
+                }
+            }
+        } else {
+            comp.clearSelection();
+            componentEnabledMap.get(comp).setSelected(false);
+        }
+    }
+
     /** Subroutine of {...@link #updateComponents(SQLColumn)}. */
private void updateComponent(JTextComponent comp, String expectedValue) {
         boolean unvisited = comp.getText().equals("");
@@ -678,18 +712,6 @@
         }
     }

-    /** Subroutine of {...@link #updateComponents(SQLColumn)}. */
-    private void updateComponent(JComboBox comp, Object expectedValue) {
-        boolean unvisited = comp.getSelectedItem() == null;
-        if (componentEnabledMap.get(comp).isSelected() &&
- (unvisited || comp.getSelectedItem().equals(expectedValue))) {
-            comp.setSelectedItem(expectedValue);
-        } else {
-            comp.setSelectedItem(null);
-            componentEnabledMap.get(comp).setSelected(false);
-        }
-    }
-
     /** Subroutine of {...@link #updateComponents(SQLColumn)}. */
     private void updateComponent(JCheckBox comp, boolean expectedValue) {
// Checking if a checkbox was visited is not possible just by examining its value,
@@ -809,7 +831,7 @@
                     column.setPhysicalName(colPhysicalName.getText());
                 }
                 if (componentEnabledMap.get(colType).isSelected()) {
- column.getUserDefinedSQLType().setUpstreamType((UserDefinedSQLType) colType.getSelectedItem()); + column.getUserDefinedSQLType().setUpstreamType((UserDefinedSQLType) colType.getLastSelectedPathComponent());
                 }

                 if (componentEnabledMap.get(colType).isSelected()) {
@@ -959,7 +981,7 @@
     }

/** Only for testing. Normal client code should not need to call this. */
-    public JComboBox getColType() {
+    public JTree getColType() {
         return colType;
     }

@@ -1072,8 +1094,8 @@
     }

     public void propertyChanged(PropertyChangeEvent e) {
+        String property = e.getPropertyName();
         if (columns.contains(e.getSource())) {
-            String property = e.getPropertyName();
             if (property.equals("name")) {
                 DataEntryPanelChangeUtil.incomingChange(colLogicalName, e);
             } else if (property.equals("physicalName")) {
@@ -1096,9 +1118,18 @@
                 DataEntryPanelChangeUtil.incomingChange(colRemarks, e);
             } else if (property.equals("defaultValue")) {
DataEntryPanelChangeUtil.incomingChange(colDefaultValue, e);
-            } else return;
+            } else {
+                return;
+            }
             setErrorText(DataEntryPanelChangeUtil.ERROR_MESSAGE);
-        }
+ } else if (e.getSource() instanceof UserDefinedSQLType && columns.contains(((UserDefinedSQLType) e.getSource()).getParent())) {
+            if (property.equals("type")) {
+                DataEntryPanelChangeUtil.incomingChange(colType, e);
+            } else {
+                return;
+            }
+            setErrorText(DataEntryPanelChangeUtil.ERROR_MESSAGE);
+        }
     }

     public void transactionEnded(TransactionEvent e) {
=======================================
--- /trunk/src/main/resources/ca/sqlpower/architect/swingui/messages.properties Thu May 6 09:31:10 2010 +++ /trunk/src/main/resources/ca/sqlpower/architect/swingui/messages.properties Fri May 14 11:58:04 2010
@@ -73,6 +73,7 @@
 ASUtils.targetDatabase=(Target Database)
 ColumnEditPanel.allowsNulls=Allows Nulls
 ColumnEditPanel.autoIncrement=Auto Increment
+ColumnEditPanel.chooseType=Choose Type...
 ColumnEditPanel.columnNameRequired=Column name is required
 ColumnEditPanel.compoundEditName=Modify Column Properties
 ColumnEditPanel.defaultValue=Default Value

Reply via email to