diff --git a/lib/idcanet-x4o-bin.jar b/lib/idcanet-x4o-bin.jar index 5fd5748..a3f6509 100644 Binary files a/lib/idcanet-x4o-bin.jar and b/lib/idcanet-x4o-bin.jar differ diff --git a/src/com/idcanet/vasc/annotations/VascAnnotationParser.java b/src/com/idcanet/vasc/annotations/VascAnnotationParser.java index b97b563..7f2749d 100644 --- a/src/com/idcanet/vasc/annotations/VascAnnotationParser.java +++ b/src/com/idcanet/vasc/annotations/VascAnnotationParser.java @@ -62,11 +62,11 @@ public class VascAnnotationParser { * @param property The property for the ToolTip * @return The i18n key for an ToolTip */ - public String getVascToolTipKey(Class beanClass,String property) { + public String getVascToolTipKey(Class beanClass,String property) { return (String)getValue(beanClass,VascToolTip.class,property); } - public String getVascToolTipKey(Class beanClass) { + public String getVascToolTipKey(Class beanClass) { return (String)getValue(beanClass,VascToolTip.class,null); } @@ -76,44 +76,44 @@ public class VascAnnotationParser { * @param property The property for the Labe * @return The i18n key for an Label */ - public String getVascNameKey(Class beanClass,String property) { + public String getVascNameKey(Class beanClass,String property) { return (String)getValue(beanClass,VascName.class,property); } - public String getVascNameKey(Class beanClass) { + public String getVascNameKey(Class beanClass) { return (String)getValue(beanClass,VascName.class,null); } - public Object getVascColumnWidth(Class beanClass,String property) { + public Object getVascColumnWidth(Class beanClass,String property) { return getValue(beanClass,VascColumnWidth.class,property); } - public Object getVascColumnWidth(Class beanClass) { + public Object getVascColumnWidth(Class beanClass) { return getValue(beanClass,VascColumnWidth.class,null); } - public String getVascHelpId(Class beanClass,String property) { + public String getVascHelpId(Class beanClass,String property) { return (String)getValue(beanClass,VascHelpId.class,property); } - public String getVascHelpId(Class beanClass) { + public String getVascHelpId(Class beanClass) { return (String)getValue(beanClass,VascHelpId.class,null); } - public Object getVascDefaultValue(Class beanClass,String property) { + public Object getVascDefaultValue(Class beanClass,String property) { return getValue(beanClass,VascDefaultValue.class,property); } - public Object getVascDefaultValue(Class beanClass) { + public Object getVascDefaultValue(Class beanClass) { return getValue(beanClass,VascDefaultValue.class,null); } - public String getVascImage(Class beanClass,String property) { + public String getVascImage(Class beanClass,String property) { return (String)getValue(beanClass,VascImage.class,property); } - public String getVascImage(Class beanClass) { + public String getVascImage(Class beanClass) { return (String)getValue(beanClass,VascImage.class,null); } @@ -127,7 +127,8 @@ public class VascAnnotationParser { * @param annotationType * @return */ - private Object getValue(Class beanClass,Class annotationType,String property) { + @SuppressWarnings("unchecked") + private Object getValue(Class beanClass,Class annotationType,String property) { if(beanClass==null) { throw new NullPointerException("beanClass may not be null"); } if(annotationType==null){ throw new NullPointerException("annotationType may not be null"); } @@ -202,7 +203,7 @@ public class VascAnnotationParser { return null; } - Class a = b.annotationType(); + Class a = b.annotationType(); if (a.equals(VascName.class)) { VascName l = (VascName)b; if("".equals(l.key()) | "null".equals(l.key())) { diff --git a/src/com/idcanet/vasc/annotations/VascDefaultValue.java b/src/com/idcanet/vasc/annotations/VascDefaultValue.java index ab49bea..bccde37 100644 --- a/src/com/idcanet/vasc/annotations/VascDefaultValue.java +++ b/src/com/idcanet/vasc/annotations/VascDefaultValue.java @@ -45,7 +45,7 @@ public @interface VascDefaultValue { /** * The defaultValue of the method */ - Class defaultValueClass() default Object.class; + Class defaultValueClass() default Object.class; String defaultValue() default "null"; } \ No newline at end of file diff --git a/src/com/idcanet/vasc/annotations/VascModelReference.java b/src/com/idcanet/vasc/annotations/VascModelReference.java index c707ba1..fe7cbc9 100644 --- a/src/com/idcanet/vasc/annotations/VascModelReference.java +++ b/src/com/idcanet/vasc/annotations/VascModelReference.java @@ -42,5 +42,5 @@ import java.lang.annotation.Target; @Target(ElementType.METHOD) public @interface VascModelReference { - Class type() default Object.class; + Class type() default Object.class; } \ No newline at end of file diff --git a/src/com/idcanet/vasc/core/VascEventListener.java b/src/com/idcanet/vasc/core/VascEventListener.java index da24029..db8c40c 100644 --- a/src/com/idcanet/vasc/core/VascEventListener.java +++ b/src/com/idcanet/vasc/core/VascEventListener.java @@ -34,7 +34,7 @@ package com.idcanet.vasc.core; */ public interface VascEventListener { - public enum VascEventType { DATA_UPDATE,OPTION_UPDATE,CLOSE_WINDOW } + public enum VascEventType { DATA_UPDATE,OPTION_UPDATE,CLOSE_WINDOW,BEAN_MERGE,BEAN_INIT } public void vascEvent(VascEventType e,Object o); diff --git a/src/com/idcanet/vasc/core/VascRecordCreator.java b/src/com/idcanet/vasc/core/VascRecordCreator.java index 62c2f44..afb8083 100644 --- a/src/com/idcanet/vasc/core/VascRecordCreator.java +++ b/src/com/idcanet/vasc/core/VascRecordCreator.java @@ -36,5 +36,5 @@ public interface VascRecordCreator { public Object newRecord(VascTable table) throws Exception; - public Class getObjectClass(); + public Class getObjectClass(); } \ No newline at end of file diff --git a/src/com/idcanet/vasc/core/VascTableController.java b/src/com/idcanet/vasc/core/VascTableController.java index 8c5b228..0e5c576 100644 --- a/src/com/idcanet/vasc/core/VascTableController.java +++ b/src/com/idcanet/vasc/core/VascTableController.java @@ -60,4 +60,6 @@ public interface VascTableController { public void addExceptionListener(VascExceptionListener listener); public void removeExceptionListener(VascExceptionListener listener); + + public Object mergeObject(VascTable table,Object object); } \ No newline at end of file diff --git a/src/com/idcanet/vasc/core/ui/VascColorChooser.java b/src/com/idcanet/vasc/core/ui/VascColorChooser.java new file mode 100644 index 0000000..9952245 --- /dev/null +++ b/src/com/idcanet/vasc/core/ui/VascColorChooser.java @@ -0,0 +1,61 @@ +/* + * Copyright 2004-2007 IDCA. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and + * the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions + * and the following disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY IDCA AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL IDCA OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the authors and + * should not be interpreted as representing official policies, either expressed or implied, of IDCA. + */ + +package com.idcanet.vasc.core.ui; + +import com.idcanet.vasc.core.VascTable; + + +/** + * + * @author Willem Cazander + * @version 1.0 Nov 25, 2007 + */ +public class VascColorChooser extends VascUIComponentImplLoader { + + // TODO: remove this hack with converters + boolean hexSwingEncoding = false; + + public Object createComponent(VascTable table,VascValueModel model,Object gui) throws Exception { + return loadAndCreateComponent(this, table, model, gui); + } + + /** + * @return the hexSwingEncoding + */ + public boolean getHexSwingEncoding() { + return hexSwingEncoding; + } + + /** + * @param hexSwingEncoding the hexSwingEncoding to set + */ + public void setHexSwingEncoding(boolean hexSwingEncoding) { + this.hexSwingEncoding = hexSwingEncoding; + } + + +} \ No newline at end of file diff --git a/src/com/idcanet/vasc/impl/BeanVascRecordCreator.java b/src/com/idcanet/vasc/impl/BeanVascRecordCreator.java index dafcd8b..2a23dde 100644 --- a/src/com/idcanet/vasc/impl/BeanVascRecordCreator.java +++ b/src/com/idcanet/vasc/impl/BeanVascRecordCreator.java @@ -36,13 +36,12 @@ import com.idcanet.vasc.core.VascTable; */ public class BeanVascRecordCreator implements VascRecordCreator { - private Class objectClass = null; - + private Class objectClass = null; public BeanVascRecordCreator() { - } - public BeanVascRecordCreator(Class objectClass) { + + public BeanVascRecordCreator(Class objectClass) { setObjectClass(objectClass); } @@ -50,10 +49,10 @@ public class BeanVascRecordCreator implements VascRecordCreator { return objectClass.newInstance(); } - public Class getObjectClass() { + public Class getObjectClass() { return objectClass; } - public void setObjectClass(Class objectClass) { + public void setObjectClass(Class objectClass) { this.objectClass=objectClass; } } \ No newline at end of file diff --git a/src/com/idcanet/vasc/impl/DefaultVascTableController.java b/src/com/idcanet/vasc/impl/DefaultVascTableController.java index 006a7b3..f72ed71 100644 --- a/src/com/idcanet/vasc/impl/DefaultVascTableController.java +++ b/src/com/idcanet/vasc/impl/DefaultVascTableController.java @@ -147,6 +147,7 @@ public class DefaultVascTableController implements VascTableController { return object; } object = table.getVascRecordCreator().newRecord(table); + fireVascEvent(VascEventListener.VascEventType.BEAN_INIT, object); return object; } @@ -245,4 +246,21 @@ public class DefaultVascTableController implements VascTableController { public void removeExceptionListener(VascExceptionListener listener) { exceptionListeners.remove(listener); } + + public Object mergeObject(VascTable table,Object object) { + Object result = null; + try { + object = table.getVascDataSource().merge(object); + fireVascEvent(VascEventListener.VascEventType.BEAN_MERGE,object); + // todo: make faster + // add to table at position old old object + // then remove old object + // send refresh + + table.getVascTableController().refreshData(table); + } catch (Exception e) { + handleException(e, table); + } + return result; + } } \ No newline at end of file diff --git a/src/com/idcanet/vasc/impl/actions/AddRowAction.java b/src/com/idcanet/vasc/impl/actions/AddRowAction.java index 4b9b4be..5db3ed7 100644 --- a/src/com/idcanet/vasc/impl/actions/AddRowAction.java +++ b/src/com/idcanet/vasc/impl/actions/AddRowAction.java @@ -44,6 +44,6 @@ public class AddRowAction extends AbstractVascAction implements RowVascAction { } public void doRowAction(VascTable table,Object rowObject) throws Exception { - table.getVascViewRenderer().renderEdit(table.getVascRecordCreator().newRecord(table)); + table.getVascViewRenderer().renderEdit(null); } } \ No newline at end of file diff --git a/src/com/idcanet/vasc/impl/serv5/Serv5HibernateVascDataSource.java b/src/com/idcanet/vasc/impl/serv5/Serv5HibernateVascDataSource.java index 142bb42..9b40b3f 100644 --- a/src/com/idcanet/vasc/impl/serv5/Serv5HibernateVascDataSource.java +++ b/src/com/idcanet/vasc/impl/serv5/Serv5HibernateVascDataSource.java @@ -27,13 +27,11 @@ package com.idcanet.vasc.impl.serv5; import java.util.List; -import java.util.logging.Level; import org.hibernate.Query; import com.idcanet.serv5.services.hibernate3.Hibernate3Factory; import com.idcanet.vasc.core.AbstractVascDataSource; -import com.idcanet.vasc.core.VascDataSource; import com.idcanet.xtes.xpql.query.QueryParameterValue; /** @@ -55,6 +53,7 @@ public class Serv5HibernateVascDataSource extends AbstractVascDataSource { setQuery(query); } + @SuppressWarnings("unchecked") public List execute() throws Exception { try { Query q = Hibernate3Factory.getSession(getSession()).createQuery(query.toPreparedSQL(query)); @@ -66,7 +65,7 @@ public class Serv5HibernateVascDataSource extends AbstractVascDataSource { q.setParameter(i,value.getValue()); i++; } - List data = q.list(); + List data = q.list(); //logger.fine("Query returned: "+data.size()+" of: "+crudTable.getQueryName()); return data; } finally { diff --git a/src/com/idcanet/vasc/impl/swing/SwingVascViewRenderer.java b/src/com/idcanet/vasc/impl/swing/SwingVascViewRenderer.java index 68ee086..5aa51b2 100644 --- a/src/com/idcanet/vasc/impl/swing/SwingVascViewRenderer.java +++ b/src/com/idcanet/vasc/impl/swing/SwingVascViewRenderer.java @@ -35,6 +35,8 @@ import java.awt.Image; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; import java.io.FileOutputStream; import java.io.OutputStream; import java.util.ArrayList; @@ -73,6 +75,7 @@ import com.idcanet.vasc.core.VascViewRenderer; import com.idcanet.vasc.core.actions.GlobalVascAction; import com.idcanet.vasc.core.actions.RowVascAction; import com.idcanet.vasc.core.column.VascTableColumn; +import com.idcanet.vasc.core.ui.VascColorChooser; import com.idcanet.vasc.core.ui.VascColumnValueModelListener; import com.idcanet.vasc.core.ui.VascDate; import com.idcanet.vasc.core.ui.VascList; @@ -80,6 +83,7 @@ import com.idcanet.vasc.core.ui.VascTextField; import com.idcanet.vasc.core.ui.VascToggle; import com.idcanet.vasc.core.ui.VascUIComponent; import com.idcanet.vasc.core.ui.VascValueModel; +import com.idcanet.vasc.impl.swing.ui.SwingColorChooser; import com.idcanet.vasc.impl.swing.ui.SwingDate; import com.idcanet.vasc.impl.swing.ui.SwingList; import com.idcanet.vasc.impl.swing.ui.SwingTextField; @@ -117,6 +121,7 @@ public class SwingVascViewRenderer implements VascViewRenderer { table.putUIComponent(VascList.class, SwingList.class); table.putUIComponent(VascToggle.class, SwingToggle.class); table.putUIComponent(VascDate.class, SwingDate.class); + table.putUIComponent(VascColorChooser.class, SwingColorChooser.class); this.table=table; } @@ -141,7 +146,7 @@ public class SwingVascViewRenderer implements VascViewRenderer { */ public void renderEdit(Object rowBean) throws Exception { logger.fine("Rending Edit View"); - table.getVascTableController().initEditObject(table, rowBean); + rowBean = table.getVascTableController().initEditObject(table, rowBean); String beanValue = rowBean.toString(); if (table.getUIIdentifierVascTableColomn()!=null) { Object vv = table.getUIIdentifierVascTableColomn().getVascColumnValue().getValue(table.getUIIdentifierVascTableColomn(), rowBean); @@ -160,16 +165,7 @@ public class SwingVascViewRenderer implements VascViewRenderer { if(result==null) { return; } - try { - result = table.getVascDataSource().merge(rowBean); - } finally { - // todo: make faster - // add to table at position old old object - // then remove old object - // send refresh - - table.getVascTableController().refreshData(table); - } + table.getVascTableController().mergeObject(table, result); } public void renderDelete(Object rowBean) throws Exception { @@ -455,8 +451,17 @@ public class SwingVascViewRenderer implements VascViewRenderer { VascColumnModel model = new VascColumnModel(); table.getVascTableController().addEventListener(model); - JTable jTable = new JTable(model); - + JTable jTable = new JTable(); + //TODO: remove this extra model for sorting, AND fixup a real sorting stuff + TableSorter tableSorter = new TableSorter(); + // this regs the listeners for the sorting + tableSorter.setTableHeader(jTable.getTableHeader()); + tableSorter.setTableModel(model); + + + jTable.setModel(tableSorter); + jTable.getTableHeader().setReorderingAllowed(false); + // remove auto columns :( int cols = jTable.getColumnModel().getColumnCount(); for (int i=0;i list = new ArrayList(); for(VascTableColumn c:table.getTableColumns()) { if (c.isListDisplay()==false) { diff --git a/src/com/idcanet/vasc/impl/swing/TableSorter.java b/src/com/idcanet/vasc/impl/swing/TableSorter.java new file mode 100644 index 0000000..c671c96 --- /dev/null +++ b/src/com/idcanet/vasc/impl/swing/TableSorter.java @@ -0,0 +1,492 @@ +/* + * + * + * THIS FILE IS FROM: + * http://java.sun.com/docs/books/tutorial/uiswing/components/table.html#sorting + */ + +package com.idcanet.vasc.impl.swing; + +import java.awt.*; +import java.awt.event.*; +import java.util.*; +import java.util.List; + +import javax.swing.*; +import javax.swing.event.TableModelEvent; +import javax.swing.event.TableModelListener; +import javax.swing.table.*; + +/** + * TableSorter is a decorator for TableModels; adding sorting + * functionality to a supplied TableModel. TableSorter does + * not store or copy the data in its TableModel; instead it maintains + * a map from the row indexes of the view to the row indexes of the + * model. As requests are made of the sorter (like getValueAt(row, col)) + * they are passed to the underlying model after the row numbers + * have been translated via the internal mapping array. This way, + * the TableSorter appears to hold another copy of the table + * with the rows in a different order. + *

+ * TableSorter registers itself as a listener to the underlying model, + * just as the JTable itself would. Events recieved from the model + * are examined, sometimes manipulated (typically widened), and then + * passed on to the TableSorter's listeners (typically the JTable). + * If a change to the model has invalidated the order of TableSorter's + * rows, a note of this is made and the sorter will resort the + * rows the next time a value is requested. + *

+ * When the tableHeader property is set, either by using the + * setTableHeader() method or the two argument constructor, the + * table header may be used as a complete UI for TableSorter. + * The default renderer of the tableHeader is decorated with a renderer + * that indicates the sorting status of each column. In addition, + * a mouse listener is installed with the following behavior: + *

    + *
  • + * Mouse-click: Clears the sorting status of all other columns + * and advances the sorting status of that column through three + * values: {NOT_SORTED, ASCENDING, DESCENDING} (then back to + * NOT_SORTED again). + *
  • + * SHIFT-mouse-click: Clears the sorting status of all other columns + * and cycles the sorting status of the column through the same + * three values, in the opposite order: {NOT_SORTED, DESCENDING, ASCENDING}. + *
  • + * CONTROL-mouse-click and CONTROL-SHIFT-mouse-click: as above except + * that the changes to the column do not cancel the statuses of columns + * that are already sorting - giving a way to initiate a compound + * sort. + *
+ *

+ * This is a long overdue rewrite of a class of the same name that + * first appeared in the swing table demos in 1997. + * + * @author Philip Milne + * @author Brendon McLean + * @author Dan van Enckevort + * @author Parwinder Sekhon + * @version 2.0 02/27/04 + */ +@SuppressWarnings("unchecked") +public class TableSorter extends AbstractTableModel { + + private static final long serialVersionUID = 10L; + protected TableModel tableModel; + + public static final int DESCENDING = -1; + public static final int NOT_SORTED = 0; + public static final int ASCENDING = 1; + + private static Directive EMPTY_DIRECTIVE = new Directive(-1, NOT_SORTED); + + public static final Comparator COMPARABLE_COMAPRATOR = new Comparator() { + public int compare(Object o1, Object o2) { + return ((Comparable) o1).compareTo(o2); + } + }; + public static final Comparator LEXICAL_COMPARATOR = new Comparator() { + public int compare(Object o1, Object o2) { + return o1.toString().compareTo(o2.toString()); + } + }; + + private Row[] viewToModel; + private int[] modelToView; + + private JTableHeader tableHeader; + private MouseListener mouseListener; + private TableModelListener tableModelListener; + private Map columnComparators = new HashMap(); + private List sortingColumns = new ArrayList(); + + public TableSorter() { + this.mouseListener = new MouseHandler(); + this.tableModelListener = new TableModelHandler(); + } + + public TableSorter(TableModel tableModel) { + this(); + setTableModel(tableModel); + } + + public TableSorter(TableModel tableModel, JTableHeader tableHeader) { + this(); + setTableHeader(tableHeader); + setTableModel(tableModel); + } + + private void clearSortingState() { + viewToModel = null; + modelToView = null; + } + + public TableModel getTableModel() { + return tableModel; + } + + public void setTableModel(TableModel tableModel) { + if (this.tableModel != null) { + this.tableModel.removeTableModelListener(tableModelListener); + } + + this.tableModel = tableModel; + if (this.tableModel != null) { + this.tableModel.addTableModelListener(tableModelListener); + } + + clearSortingState(); + fireTableStructureChanged(); + } + + public JTableHeader getTableHeader() { + return tableHeader; + } + + public void setTableHeader(JTableHeader tableHeader) { + if (this.tableHeader != null) { + this.tableHeader.removeMouseListener(mouseListener); + TableCellRenderer defaultRenderer = this.tableHeader.getDefaultRenderer(); + if (defaultRenderer instanceof SortableHeaderRenderer) { + this.tableHeader.setDefaultRenderer(((SortableHeaderRenderer) defaultRenderer).tableCellRenderer); + } + } + this.tableHeader = tableHeader; + if (this.tableHeader != null) { + this.tableHeader.addMouseListener(mouseListener); + this.tableHeader.setDefaultRenderer( + new SortableHeaderRenderer(this.tableHeader.getDefaultRenderer())); + } + } + + public boolean isSorting() { + return sortingColumns.size() != 0; + } + + private Directive getDirective(int column) { + for (int i = 0; i < sortingColumns.size(); i++) { + Directive directive = (Directive)sortingColumns.get(i); + if (directive.column == column) { + return directive; + } + } + return EMPTY_DIRECTIVE; + } + + public int getSortingStatus(int column) { + return getDirective(column).direction; + } + + private void sortingStatusChanged() { + clearSortingState(); + fireTableDataChanged(); + if (tableHeader != null) { + tableHeader.repaint(); + } + } + + public void setSortingStatus(int column, int status) { + Directive directive = getDirective(column); + if (directive != EMPTY_DIRECTIVE) { + sortingColumns.remove(directive); + } + if (status != NOT_SORTED) { + sortingColumns.add(new Directive(column, status)); + } + sortingStatusChanged(); + } + + protected Icon getHeaderRendererIcon(int column, int size) { + Directive directive = getDirective(column); + if (directive == EMPTY_DIRECTIVE) { + return null; + } + return new Arrow(directive.direction == DESCENDING, size, sortingColumns.indexOf(directive)); + } + + private void cancelSorting() { + sortingColumns.clear(); + sortingStatusChanged(); + } + + public void setColumnComparator(Class type, Comparator comparator) { + if (comparator == null) { + columnComparators.remove(type); + } else { + columnComparators.put(type, comparator); + } + } + + protected Comparator getComparator(int column) { + Class columnType = tableModel.getColumnClass(column); + Comparator comparator = (Comparator) columnComparators.get(columnType); + if (comparator != null) { + return comparator; + } + if (Comparable.class.isAssignableFrom(columnType)) { + return COMPARABLE_COMAPRATOR; + } + return LEXICAL_COMPARATOR; + } + + private Row[] getViewToModel() { + if (viewToModel == null) { + int tableModelRowCount = tableModel.getRowCount(); + viewToModel = new Row[tableModelRowCount]; + for (int row = 0; row < tableModelRowCount; row++) { + viewToModel[row] = new Row(row); + } + + if (isSorting()) { + Arrays.sort(viewToModel); + } + } + return viewToModel; + } + + public int modelIndex(int viewIndex) { + return getViewToModel()[viewIndex].modelIndex; + } + + private int[] getModelToView() { + if (modelToView == null) { + int n = getViewToModel().length; + modelToView = new int[n]; + for (int i = 0; i < n; i++) { + modelToView[modelIndex(i)] = i; + } + } + return modelToView; + } + + // TableModel interface methods + + public int getRowCount() { + return (tableModel == null) ? 0 : tableModel.getRowCount(); + } + + public int getColumnCount() { + return (tableModel == null) ? 0 : tableModel.getColumnCount(); + } + + public String getColumnName(int column) { + return tableModel.getColumnName(column); + } + + public Class getColumnClass(int column) { + return tableModel.getColumnClass(column); + } + + public boolean isCellEditable(int row, int column) { + return tableModel.isCellEditable(modelIndex(row), column); + } + + public Object getValueAt(int row, int column) { + return tableModel.getValueAt(modelIndex(row), column); + } + + public void setValueAt(Object aValue, int row, int column) { + tableModel.setValueAt(aValue, modelIndex(row), column); + } + + // Helper classes + + private class Row implements Comparable { + private int modelIndex; + + public Row(int index) { + this.modelIndex = index; + } + + public int compareTo(Object o) { + int row1 = modelIndex; + int row2 = ((Row) o).modelIndex; + + for (Iterator it = sortingColumns.iterator(); it.hasNext();) { + Directive directive = (Directive) it.next(); + int column = directive.column; + Object o1 = tableModel.getValueAt(row1, column); + Object o2 = tableModel.getValueAt(row2, column); + + int comparison = 0; + // Define null less than everything, except null. + if (o1 == null && o2 == null) { + comparison = 0; + } else if (o1 == null) { + comparison = -1; + } else if (o2 == null) { + comparison = 1; + } else { + comparison = getComparator(column).compare(o1, o2); + } + if (comparison != 0) { + return directive.direction == DESCENDING ? -comparison : comparison; + } + } + return 0; + } + } + + private class TableModelHandler implements TableModelListener { + public void tableChanged(TableModelEvent e) { + // If we're not sorting by anything, just pass the event along. + if (!isSorting()) { + clearSortingState(); + fireTableChanged(e); + return; + } + + // If the table structure has changed, cancel the sorting; the + // sorting columns may have been either moved or deleted from + // the model. + if (e.getFirstRow() == TableModelEvent.HEADER_ROW) { + cancelSorting(); + fireTableChanged(e); + return; + } + + // We can map a cell event through to the view without widening + // when the following conditions apply: + // + // a) all the changes are on one row (e.getFirstRow() == e.getLastRow()) and, + // b) all the changes are in one column (column != TableModelEvent.ALL_COLUMNS) and, + // c) we are not sorting on that column (getSortingStatus(column) == NOT_SORTED) and, + // d) a reverse lookup will not trigger a sort (modelToView != null) + // + // Note: INSERT and DELETE events fail this test as they have column == ALL_COLUMNS. + // + // The last check, for (modelToView != null) is to see if modelToView + // is already allocated. If we don't do this check; sorting can become + // a performance bottleneck for applications where cells + // change rapidly in different parts of the table. If cells + // change alternately in the sorting column and then outside of + // it this class can end up re-sorting on alternate cell updates - + // which can be a performance problem for large tables. The last + // clause avoids this problem. + int column = e.getColumn(); + if (e.getFirstRow() == e.getLastRow() + && column != TableModelEvent.ALL_COLUMNS + && getSortingStatus(column) == NOT_SORTED + && modelToView != null) { + int viewIndex = getModelToView()[e.getFirstRow()]; + fireTableChanged(new TableModelEvent(TableSorter.this, + viewIndex, viewIndex, + column, e.getType())); + return; + } + + // Something has happened to the data that may have invalidated the row order. + clearSortingState(); + fireTableDataChanged(); + return; + } + } + + private class MouseHandler extends MouseAdapter { + public void mouseClicked(MouseEvent e) { + JTableHeader h = (JTableHeader) e.getSource(); + TableColumnModel columnModel = h.getColumnModel(); + int viewColumn = columnModel.getColumnIndexAtX(e.getX()); + int column = columnModel.getColumn(viewColumn).getModelIndex(); + if (column != -1) { + int status = getSortingStatus(column); + if (!e.isControlDown()) { + cancelSorting(); + } + // Cycle the sorting states through {NOT_SORTED, ASCENDING, DESCENDING} or + // {NOT_SORTED, DESCENDING, ASCENDING} depending on whether shift is pressed. + status = status + (e.isShiftDown() ? -1 : 1); + status = (status + 4) % 3 - 1; // signed mod, returning {-1, 0, 1} + setSortingStatus(column, status); + } + } + } + + private static class Arrow implements Icon { + private boolean descending; + private int size; + private int priority; + + public Arrow(boolean descending, int size, int priority) { + this.descending = descending; + this.size = size; + this.priority = priority; + } + + public void paintIcon(Component c, Graphics g, int x, int y) { + Color color = c == null ? Color.GRAY : c.getBackground(); + // In a compound sort, make each succesive triangle 20% + // smaller than the previous one. + int dx = (int)(size/2*Math.pow(0.8, priority)); + int dy = descending ? dx : -dx; + // Align icon (roughly) with font baseline. + y = y + 5*size/6 + (descending ? -dy : 0); + int shift = descending ? 1 : -1; + g.translate(x, y); + + // Right diagonal. + g.setColor(color.darker()); + g.drawLine(dx / 2, dy, 0, 0); + g.drawLine(dx / 2, dy + shift, 0, shift); + + // Left diagonal. + g.setColor(color.brighter()); + g.drawLine(dx / 2, dy, dx, 0); + g.drawLine(dx / 2, dy + shift, dx, shift); + + // Horizontal line. + if (descending) { + g.setColor(color.darker().darker()); + } else { + g.setColor(color.brighter().brighter()); + } + g.drawLine(dx, 0, 0, 0); + + g.setColor(color); + g.translate(-x, -y); + } + + public int getIconWidth() { + return size; + } + + public int getIconHeight() { + return size; + } + } + + private class SortableHeaderRenderer implements TableCellRenderer { + private TableCellRenderer tableCellRenderer; + + public SortableHeaderRenderer(TableCellRenderer tableCellRenderer) { + this.tableCellRenderer = tableCellRenderer; + } + + public Component getTableCellRendererComponent(JTable table, + Object value, + boolean isSelected, + boolean hasFocus, + int row, + int column) { + Component c = tableCellRenderer.getTableCellRendererComponent(table, + value, isSelected, hasFocus, row, column); + if (c instanceof JLabel) { + JLabel l = (JLabel) c; + l.setHorizontalTextPosition(JLabel.LEFT); + int modelColumn = table.convertColumnIndexToModel(column); + l.setIcon(getHeaderRendererIcon(modelColumn, l.getFont().getSize())); + } + return c; + } + } + + private static class Directive { + private int column; + private int direction; + + public Directive(int column, int direction) { + this.column = column; + this.direction = direction; + } + } +} diff --git a/src/com/idcanet/vasc/impl/swing/ui/SwingColorChooser.java b/src/com/idcanet/vasc/impl/swing/ui/SwingColorChooser.java new file mode 100644 index 0000000..39722b9 --- /dev/null +++ b/src/com/idcanet/vasc/impl/swing/ui/SwingColorChooser.java @@ -0,0 +1,125 @@ +/* + * Copyright 2004-2007 IDCA. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and + * the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions + * and the following disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY IDCA AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL IDCA OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the authors and + * should not be interpreted as representing official policies, either expressed or implied, of IDCA. + */ + +package com.idcanet.vasc.impl.swing.ui; + +import java.awt.Color; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JButton; +import javax.swing.JColorChooser; +import javax.swing.JComponent; + +import com.idcanet.vasc.core.VascTable; +import com.idcanet.vasc.core.ui.AbstractVascUIComponent; +import com.idcanet.vasc.core.ui.VascColorChooser; +import com.idcanet.vasc.core.ui.VascValueModel; + +/** + * + * + * @author Willem Cazander + * @version 1.0 Nov 25, 2007 + */ +public class SwingColorChooser extends AbstractVascUIComponent { + + private JButton colorButton = null; + private Color orgBackgroundColor = null; + + public Object createComponent(VascTable table,VascValueModel model,Object gui) throws Exception { + + + VascColorChooser org = (VascColorChooser)getWrapper(); + + JButton colorButton = new JButton("Color"); + orgBackgroundColor = colorButton.getBackground(); + ((JComponent)gui).add(colorButton); + colorButton.addActionListener(new SelectActionListener3(model,org.getHexSwingEncoding())); + return colorButton; + } + + /** + * @see com.idcanet.vasc.core.ui.VascUIComponent#getErrorText() + */ + public String getErrorText() { + if (colorButton==null) { + return null; + } + return colorButton.getToolTipText(); + } + + /** + * @see com.idcanet.vasc.core.ui.VascUIComponent#setErrorText(java.lang.String) + */ + public void setErrorText(String text) { + if (colorButton==null) { + return; + } + colorButton.setToolTipText(text); + if (text==null) { + colorButton.setBackground(orgBackgroundColor); + } else { + colorButton.setBackground(Color.RED); + } + } +} +class SelectActionListener3 implements ActionListener { + + private VascValueModel model; + private boolean hexEncoding = false; + public SelectActionListener3(VascValueModel model,boolean hexEncoding) { + this.model=model; + this.hexEncoding=hexEncoding; + } + + /** + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + */ + public void actionPerformed(ActionEvent e) { + if (hexEncoding==false) { + Color cur = (Color)model.getValue(); + if (cur==null) { + cur = Color.YELLOW; + } + Color newColor = JColorChooser.showDialog(null,"Choose a color...",cur); + model.setValue(newColor); + } else { + String cur = (String)model.getValue(); + Color c = Color.YELLOW; + try { + if (cur!=null) { + c = Color.decode(cur); + } + Color newColor = JColorChooser.showDialog(null,"Choose a color...",c); + String newColorString = "#"+Integer.toHexString( newColor.getRGB() & 0x00ffffff ); + model.setValue(newColorString); + } catch (Exception ee) { + + } + } + } +} \ No newline at end of file diff --git a/src/com/idcanet/vasc/impl/swt/SwtVascViewRenderer.java b/src/com/idcanet/vasc/impl/swt/SwtVascViewRenderer.java index 66f2b98..a9fd355 100644 --- a/src/com/idcanet/vasc/impl/swt/SwtVascViewRenderer.java +++ b/src/com/idcanet/vasc/impl/swt/SwtVascViewRenderer.java @@ -66,7 +66,6 @@ import org.eclipse.swt.widgets.ToolItem; import com.idcanet.fff.SwingImageHelper; import com.idcanet.vasc.core.VascDataExporter; import com.idcanet.vasc.core.VascTable; -import com.idcanet.vasc.core.VascUserOption; import com.idcanet.vasc.core.VascViewRenderer; import com.idcanet.vasc.core.actions.GlobalVascAction; import com.idcanet.vasc.core.actions.RowVascAction; @@ -189,14 +188,14 @@ public class SwtVascViewRenderer implements VascViewRenderer { public class SwtVascEditDialog extends Dialog { private Shell shell = null; - private String headerText = null; + //private String headerText = null; private String title = null; private Object result = null; private Object bean = null; public SwtVascEditDialog (Shell parent,VascTable table,Object bean,String title,String headerText) { super (parent, 0); - this.headerText = headerText; + ///this.headerText = headerText; this.title = title; this.bean = bean; } @@ -445,7 +444,7 @@ public class SwtVascViewRenderer implements VascViewRenderer { } // create options - for(VascUserOption option:table.getUserOptions()) { + //for(VascUserOption option:table.getUserOptions()) { /* if(option.getLabelText()!=null) { @@ -461,7 +460,7 @@ public class SwtVascViewRenderer implements VascViewRenderer { cpo.getValueHolder().addPropertyChangeListener(this); */ - } + //} } class GlobalActionListener extends SelectionAdapter { diff --git a/tests/META-INF/vasc-lang.eld b/tests/META-INF/vasc-lang.eld new file mode 100644 index 0000000..c19c954 --- /dev/null +++ b/tests/META-INF/vasc-lang.eld @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/META-INF/vasc-namespaces.xml b/tests/META-INF/vasc-namespaces.xml new file mode 100644 index 0000000..01ac3aa --- /dev/null +++ b/tests/META-INF/vasc-namespaces.xml @@ -0,0 +1,8 @@ + + + + + Vasc namespace for x4o vasc state/table/column language + + META-INF/vasc-lang.eld + \ No newline at end of file diff --git a/tests/com/idcanet/vasc/TestTable.java b/tests/com/idcanet/vasc/TestTable.java index 30b3012..e6f0971 100644 --- a/tests/com/idcanet/vasc/TestTable.java +++ b/tests/com/idcanet/vasc/TestTable.java @@ -31,11 +31,11 @@ import java.util.Date; import com.idcanet.vasc.core.VascTable; import com.idcanet.vasc.core.column.VascAnnotationTableColumn; import com.idcanet.vasc.core.column.VascTableColumn; +import com.idcanet.vasc.core.ui.VascColorChooser; import com.idcanet.vasc.core.ui.VascList; import com.idcanet.vasc.core.ui.VascTextField; import com.idcanet.vasc.impl.BeanVascRecordCreator; import com.idcanet.vasc.impl.DefaultVascTableController; -import com.idcanet.vasc.impl.DefaultVascTextValue; import com.idcanet.vasc.impl.actions.AddRowAction; import com.idcanet.vasc.impl.actions.CSVExportGlobalAction; import com.idcanet.vasc.impl.actions.DeleteRowAction; @@ -44,9 +44,6 @@ import com.idcanet.vasc.impl.actions.RefreshDataGlobalAction; import com.idcanet.vasc.impl.actions.XMLExportGlobalAction; import com.idcanet.vasc.impl.column.BeanPropertyVascColumnValue; import com.idcanet.vasc.models.TestModel; -import com.idcanet.xtes.core.TemplateStore; -import com.idcanet.xtes.core.XTESParser; -import com.idcanet.xtes.xpql.query.Query; /** @@ -122,9 +119,16 @@ public class TestTable { VascList list = new VascList(); list.setVascSelectItemModel(data); column.setVascUIComponent(list); - - table.addTableColumns(column); + + + column = new VascAnnotationTableColumn("hexColor"); + column.setDefaultValue("#FF3355"); + VascColorChooser ui = new VascColorChooser(); + ui.setHexSwingEncoding(true); + column.setVascUIComponent(ui); + table.addTableColumns(column); + return table; } diff --git a/tests/com/idcanet/vasc/models/TestModel.java b/tests/com/idcanet/vasc/models/TestModel.java index 2a4341a..8640982 100644 --- a/tests/com/idcanet/vasc/models/TestModel.java +++ b/tests/com/idcanet/vasc/models/TestModel.java @@ -56,6 +56,7 @@ public class TestModel { private Boolean active = null; private Date date = null; private TestModel testModel = null; + private String hexColor = null; /** * @return the date @@ -146,7 +147,18 @@ public class TestModel { public void setActive(Boolean active) { this.active = active; } - - - + + /** + * @return the hexColor + */ + public String getHexColor() { + return hexColor; + } + + /** + * @param hexColor the hexColor to set + */ + public void setHexColor(String hexColor) { + this.hexColor = hexColor; + } } \ No newline at end of file