Author: kevin1219
Date: Thu Aug 28 14:03:28 2008
New Revision: 2653
Modified:
trunk/src/ca/sqlpower/architect/swingui/olap/LevelEditPanel.java
trunk/src/ca/sqlpower/architect/swingui/olap/MeasureEditPanel.java
Log:
Added ui components for editing a level's Properties. It's just a simple
table that with two columns for name and column. The column for column uses
a cool and awesome JCOMBOBOX!
Modified: trunk/src/ca/sqlpower/architect/swingui/olap/LevelEditPanel.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/olap/LevelEditPanel.java
(original)
+++ trunk/src/ca/sqlpower/architect/swingui/olap/LevelEditPanel.java Thu
Aug 28 14:03:28 2008
@@ -19,23 +19,50 @@
package ca.sqlpower.architect.swingui.olap;
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.DefaultCellEditor;
+import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
import javax.swing.JTextField;
+import javax.swing.ListSelectionModel;
+import javax.swing.border.EmptyBorder;
+import javax.swing.event.TableModelEvent;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.TableCellEditor;
+import javax.swing.table.TableModel;
import ca.sqlpower.architect.ArchitectException;
import ca.sqlpower.architect.SQLColumn;
import ca.sqlpower.architect.SQLTable;
+import ca.sqlpower.architect.olap.OLAPChildEvent;
+import ca.sqlpower.architect.olap.OLAPChildListener;
import ca.sqlpower.architect.olap.OLAPUtil;
import ca.sqlpower.architect.olap.MondrianModel.Hierarchy;
import ca.sqlpower.architect.olap.MondrianModel.Level;
+import ca.sqlpower.architect.olap.MondrianModel.Property;
+import ca.sqlpower.swingui.table.EditableJTable;
+import ca.sqlpower.validation.Status;
+import ca.sqlpower.validation.ValidateResult;
import ca.sqlpower.validation.Validator;
import ca.sqlpower.validation.swingui.FormValidationHandler;
import ca.sqlpower.validation.swingui.StatusComponent;
import ca.sqlpower.validation.swingui.ValidatableDataEntryPanel;
import ca.sqlpower.validation.swingui.ValidationHandler;
+import com.jgoodies.forms.builder.ButtonStackBuilder;
import com.jgoodies.forms.builder.DefaultFormBuilder;
import com.jgoodies.forms.layout.FormLayout;
@@ -46,6 +73,8 @@
private JTextField name;
private JTextField captionField;
private JComboBox columnChooser;
+
+ private PropertiesEditPanel propertiesPanel;
/**
* Validation handler for errors in the dialog
@@ -72,23 +101,30 @@
builder.append("Name", name = new JTextField(level.getName()));
builder.append("Caption", captionField = new
JTextField(level.getCaption()));
builder.append("Column", columnChooser = new JComboBox());
+
SQLTable dimensionTable = OLAPUtil.tableForHierarchy((Hierarchy)
level.getParent());
- if (dimensionTable != null) {
+ if (dimensionTable == null) {
+ columnChooser.addItem("Parent hierarchy has no table");
+ columnChooser.setEnabled(false);
+ } else if (dimensionTable.getColumns().isEmpty()) {
+ columnChooser.addItem("Parent hierarchy table has no columns");
+ columnChooser.setEnabled(false);
+ } else {
for (SQLColumn col : dimensionTable.getColumns()) {
columnChooser.addItem(col);
if (col.getName().equalsIgnoreCase(level.getColumn())) {
columnChooser.setSelectedItem(col);
}
}
- } else {
- columnChooser.addItem("Parent dimension has no table");
- columnChooser.setEnabled(false);
}
handler = new FormValidationHandler(status);
Validator validator = new
OLAPObjectNameValidator(level.getParent(), level, false);
handler.addValidateObject(name, validator);
+ builder.appendSeparator("Properties");
+ propertiesPanel = new PropertiesEditPanel(dimensionTable, handler);
+ builder.append(propertiesPanel, 3);
panel = builder.getPanel();
}
@@ -124,6 +160,246 @@
public ValidationHandler getValidationHandler() {
return handler;
}
+
+ /**
+ * Checks through the table model for duplicate property names.
+ *
+ */
+ private class PropertiesTableNameValidator implements Validator {
+ public ValidateResult validate(Object contents) {
+ TableModel model = (TableModel) contents;
+ List<String> propNames = new ArrayList<String>();
+ for ( int i = 0; i < model.getRowCount(); i++) {
+ String propName = (String) model.getValueAt(i, 0);
+ if (propNames.contains(propName)) {
+ return
ValidateResult.createValidateResult(Status.FAIL, "Duplicate Property
names.");
+ } else {
+ propNames.add(propName);
+ }
+ }
+ return ValidateResult.createValidateResult(Status.OK, "");
+ }
+ }
+ private class PropertiesEditPanel extends JPanel {
+
+ private final JTable propertiesTab;
+
+ /**
+ * Default name for a new Property.
+ */
+ private final String defaultPropName = "New Property";
+
+ private final Action newPropertyAction = new
AbstractAction("New...") {
+ public void actionPerformed(ActionEvent e) {
+ Property prop = new Property();
+ prop.setName(defaultPropName);
+ level.addProperty(prop);
+ }
+ };
+
+ private final Action removePropertyAction = new
AbstractAction("Remove...") {
+ public void actionPerformed(ActionEvent e) {
+ int selectedRow = propertiesTab.getSelectedRow();
+ if (selectedRow > -1) {
+ level.removeProperty(selectedRow);
+ setEnabled(false);
+ }
+ }
+ };
+
+ /**
+ * Creates a panel for editing a level's Properties with a JTable.
+ *
+ * @param table
+ * Should contain the columns that a Property could
use, can
+ * be null.
+ * @param handler
+ * Used for adding the [EMAIL PROTECTED]
PropertiesTableNameValidator}
+ * on the JTable.
+ * @throws ArchitectException
+ * If retrieving the columns from the table fails.
+ */
+ public PropertiesEditPanel(SQLTable table, ValidationHandler
handler) throws ArchitectException {
+ setBorder(new EmptyBorder(10, 10, 10, 10));
+ setLayout(new BorderLayout(10, 10));
+
+ propertiesTab = new PropertiesTable(table);
+ handler.addValidateObject(propertiesTab, new
PropertiesTableNameValidator());
+
+ JScrollPane sp = new JScrollPane(propertiesTab);
+ sp.setPreferredSize(new Dimension(200, 200));
+ add(sp, BorderLayout.CENTER);
+
+ ButtonStackBuilder bsb = new ButtonStackBuilder();
+ bsb.addGridded(new JButton(newPropertyAction));
+ bsb.addRelatedGap();
+ bsb.addGridded(new JButton(removePropertyAction));
+ bsb.addRelatedGap();
+
+ removePropertyAction.setEnabled(false);
+
+ add(bsb.getPanel(), BorderLayout.EAST);
+ }
+
+ private class PropertiesTable extends EditableJTable {
+
+ /**
+ * List of the SQLColumns available for Properties to use.
+ */
+ private final List<SQLColumn> columns;
+
+ /**
+ * Creates an EditableJTable for modifying Properties of the
level.
+ * @param table
+ * Should contain the columns that a Property could
use,
+ * can be null.
+ * @throws ArchitectException
+ * If retrieving the columns from the table fails.
+ */
+ public PropertiesTable(SQLTable table) throws
ArchitectException {
+ super();
+ this.columns = table == null ? null : table.getColumns();
+
+ boolean disableColumns = columns == null ||
columns.isEmpty();
+ setModel(new PropertiesTableModel(disableColumns));
+ setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ addMouseListener(new MouseAdapter() {
+ public void mouseClicked(MouseEvent evt) {
+ boolean enableAction =
propertiesTab.getSelectedRow() > -1;
+ removePropertyAction.setEnabled(enableAction);
+ }
+ });
+ }
+
+ @Override
+ public TableCellEditor getCellEditor(int row, int column) {
+ if (column == 1) {
+ // columns could be null, but then it would not be
editable, so we're save.
+ return new DefaultCellEditor(new
JComboBox(columns.toArray()));
+ } else {
+ return super.getCellEditor(row, column);
+ }
+ }
+
+ }
+
+ private class PropertiesTableModel extends AbstractTableModel
implements OLAPChildListener {
+
+ /**
+ * Determines whether the column attributes can be modified.
+ */
+ private final boolean disableColumns;
+
+ public PropertiesTableModel(boolean disableColumns) {
+ this.disableColumns = disableColumns;
+ level.addChildListener(this);
+ }
+
+ public int getRowCount() {
+ return level.getProperties().size();
+ }
+
+ public int getColumnCount() {
+ return 2;
+ }
+
+ @Override
+ public String getColumnName(int columnIndex) {
+ if (columnIndex == 0) {
+ return "Name";
+ } else if (columnIndex == 1) {
+ return "Column";
+ } else {
+ throw new IllegalArgumentException("getColumnName:
Unknow column index: " + columnIndex);
+ }
+ }
+ @Override
+ public Class<?> getColumnClass(int columnIndex) {
+ if (columnIndex == 0 || columnIndex == 1) {
+ return String.class;
+ } else {
+ throw new IllegalArgumentException("getColumnClass:
Unknow column index: " + columnIndex);
+ }
+ }
+
+ @Override
+ public boolean isCellEditable(int rowIndex, int columnIndex) {
+ if (columnIndex == 0) {
+ return true;
+ } else if (columnIndex == 1) {
+ return !disableColumns;
+ } else {
+ throw new IllegalArgumentException("isCellEditable:
Unknow column index: " + columnIndex);
+ }
+ }
+
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ if (columnIndex == 0) {
+ return level.getProperties().get(rowIndex).getName();
+ } else if (columnIndex == 1) {
+ if (disableColumns) {
+ return "Not Applicable";
+ } else {
+ return
level.getProperties().get(rowIndex).getColumn();
+ }
+ } else {
+ throw new IllegalArgumentException("getValueAt:
Unexcepted column index: " + columnIndex);
+ }
+ }
+
+ public void setValueAt(Object aValue, int rowIndex, int
columnIndex) {
+ Property prop = level.getProperties().get(rowIndex);
+ if (columnIndex == 0) {
+ prop.setName((String) aValue);
+ } else if (columnIndex == 1) {
+ if (aValue == null) {
+ prop.setColumn(null);
+ } else {
+ String colName = ((SQLColumn) aValue).getName();
+ // if the Property has not been named, name it
similar to its chosen column.
+ if (defaultPropName.equals(prop.getName())) {
+ prop.setName(underscoreToCamelCaps(colName));
+ }
+ prop.setColumn(colName);
+ }
+ } else {
+ throw new IllegalArgumentException("setValueAt:
Unexcepted column index:"+columnIndex);
+ }
+ fireTableChanged(new TableModelEvent(this, rowIndex));
+ }
+
+ /**
+ * Converts underscores in given text to spaces and return in
camel caps.
+ *
+ */
+ private String underscoreToCamelCaps(String text) {
+ StringBuffer result = new StringBuffer(text.length() * 2);
+ char[] chars = text.toLowerCase().toCharArray();
+ for (int i = 0; i < text.length(); i++) {
+ if ('_' == chars[i]) {
+ result.append(" ");
+ i++;
+ if (i >= chars.length) break;
+ result.append(Character.toUpperCase(chars[i]));
+ } else {
+ result.append(chars[i]);
+ }
+ }
+ if (chars.length > 0) {
+ result.setCharAt(0, Character.toUpperCase(chars[0]));
+ }
+ return result.toString();
+ }
+
+ public void olapChildAdded(OLAPChildEvent e) {
+ fireTableDataChanged();
+ }
+
+ public void olapChildRemoved(OLAPChildEvent e) {
+ fireTableDataChanged();
+ }
+ }
+ }
}
Modified: trunk/src/ca/sqlpower/architect/swingui/olap/MeasureEditPanel.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/olap/MeasureEditPanel.java
(original)
+++ trunk/src/ca/sqlpower/architect/swingui/olap/MeasureEditPanel.java Thu
Aug 28 14:03:28 2008
@@ -120,7 +120,7 @@
boolean enableColumns = false;
if (cubeTable == null) {
columnChooser.addItem("Parent Cube has no table");
- } else if (cubeTable.getColumns().size() == 0) {
+ } else if (cubeTable.getColumns().isEmpty()) {
columnChooser.addItem("Parent Cube table has no columns");
} else {
for (SQLColumn col : cubeTable.getColumns()) {