I extended this approach to use annotation which support all
TableView.Column properties.
Since some of the object is not primitive type, the generic class will use
Javascripts(this can be any script though) to instantiate appropriate object
at runtime.

This sample is working. In this way, it would be useful to have these
view(table/form) specific annotations in the bean class.

-----------------------

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface PivotTableViewColumn {
    String name();

    String headerData(); // JavaScripts
    //HeaderDataRenderer headerDataRenderer = DEFAULT_HEADER_DATA_RENDERER;
    String headerDataRenderer() default ""; // JavaScripts
    int width() default 0;
    int minimumWidth() default 0;
    int maximumWidth() default Integer.MAX_VALUE;
    boolean relative() default false;
    //Object filter = null;
    String filter() default ""; // JavaScripts
    //CellRenderer cellRenderer = DEFAULT_CELL_RENDERER;
    String cellRenderer() default ""; // JavaScripts
}

---------------

public class OlympicStanding {
@PivotTableViewColumn(
    name = "flag",
    headerData = "'Flag'",
    width = 25,
    cellRenderer = "new
org.apache.pivot.wtk.content.TableViewImageCellRenderer()"
)
    public Image flag = null;
 @PivotTableViewColumn(
    name = "nation",
    headerData = "'Nation'",
    width = 3,
    relative = true
)
    public String nation = null;
    @PivotTableViewColumn(
    name = "gold",
    headerData = "'Gold'",
    width = 1,
    relative = true
)
    public int gold = 0;
 @PivotTableViewColumn(
    name = "silver",
    headerData = "'Silver'",
    width = 1,
    relative = true
)
public int silver = 0;

@PivotTableViewColumn(
    name = "bronze",
    headerData = "'Bronze'",
    width = 1,
    relative = true
)
    public int bronze = 0;

    public OlympicStanding() {
    }

    public Image getFlag() {
        return flag;
    }

    public void setFlag(Image flag) {
        this.flag = flag;
    }

    public void setFlag(URL flag) {
        try {
            setFlag(Image.load(flag));
        } catch (TaskExecutionException exception) {
            throw new IllegalArgumentException(exception);
        }
    }

    public String getNation() {
        return nation;
    }

    public void setNation(String nation) {
        this.nation = nation;
    }

    public int getGold() {
        return gold;
    }

    public void setGold(int gold) {
        this.gold = gold;
    }

    public int getSilver() {
        return silver;
    }

    public void setSilver(int silver) {
        this.silver = silver;
    }

    public int getBronze() {
        return bronze;
    }

    public void setBronze(int bronze) {
        this.bronze = bronze;
    }

    public int getTotal() {
        return (gold + silver + bronze);
    }
}

-------------------

      public static class GenericTableView<T> extends TableView {
        public static final String DEFAULT_LANGUAGE = "javascript";

     private final Class<T> cls;
     private final ScriptEngineManager scriptEngineManager;

     public GenericTableView(final Class<T> cls, final Map<String, Object>
namespace) throws Exception {
     this.cls = cls;
     this.scriptEngineManager = createScriptEngineManager(namespace);
            final ScriptEngine scriptEngine =
scriptEngineManager.getEngineByName(DEFAULT_LANGUAGE);
            for (final Field field: cls.getFields()) {
             final PivotTableViewColumn column =
getPivotTableViewColumn(field);
             if (column == null) {
             continue;
             }
             getColumns().add(new TableView.Column() {{
             setName(column.name());
                    setWidth(column.width(), column.relative());
                    setMinimumWidth(column.minimumWidth());
                    setMaximumWidth(column.maximumWidth());

                 final String headerData = column.headerData();
                 if (headerData != null && !headerData.equals("")) {
                 setHeaderData(scriptEngine.eval(headerData));
                 }

                 final String headerDataRenderer =
column.headerDataRenderer();
                 if (headerDataRenderer != null &&
!headerDataRenderer.equals("")) {

setHeaderDataRenderer((HeaderDataRenderer)scriptEngine.eval(headerDataRenderer));
                 }
                    final String cellRenderer = column.cellRenderer();
                 if (cellRenderer != null && !cellRenderer.equals("")) {

setCellRenderer((CellRenderer)scriptEngine.eval(cellRenderer));
                 }
                 final String filter = column.filter();
                 if (filter != null && !filter.equals("")) {
                 setFilter(scriptEngine.eval(filter));
                 }
                }});
            }
            getTableViewSortListeners().add(new
TableViewSortListener.Adapter() {
                @Override
                @SuppressWarnings("unchecked")
                public void sortChanged(TableView tableView) {
                 tableView.getTableData().setComparator(new
org.apache.pivot.wtk.content.TableViewRowComparator(tableView));
                }
            });
        }

     public void add(T... ts) {
     for (T t: ts) {
     getTableData().add(t);
     }
     }

     //
     static ScriptEngineManager createScriptEngineManager(final Map<String,
Object> namespace) {
     final ScriptEngineManager scriptEngineManager = new
javax.script.ScriptEngineManager();
            scriptEngineManager.setBindings(new Bindings() {
                @Override
                public Object get(Object key) {
                    return namespace.get(key.toString());
                }

                @Override
                public Object put(String key, Object value) {
                    return namespace.put(key, value);
                }

                @Override
                public void putAll(java.util.Map<? extends String, ? extends
Object> map) {
                    for (String key : map.keySet()) {
                        put(key, map.get(key));
                    }
                }

                @Override
                public Object remove(Object key) {
                    return namespace.remove(key.toString());
                }

                @Override
                public void clear() {
                    namespace.clear();
                }

                @Override
                public boolean containsKey(Object key) {
                    return namespace.containsKey(key.toString());
                }

                @Override
                public boolean containsValue(Object value) {
                    boolean contains = false;
                    for (String key : namespace) {
                        if (namespace.get(key).equals(value)) {
                            contains = true;
                            break;
                        }
                    }

                    return contains;
                }

                @Override
                public boolean isEmpty() {
                    return namespace.isEmpty();
                }

                @Override
                public java.util.Set<String> keySet() {
                    java.util.HashSet<String> keySet = new
java.util.HashSet<String>();
                    for (String key : namespace) {
                        keySet.add(key);
                    }

                    return keySet;
                }

                @Override
                public java.util.Set<Entry<String, Object>> entrySet() {
                    java.util.HashMap<String, Object> hashMap = new
java.util.HashMap<String, Object>();
                    for (String key : namespace) {
                        hashMap.put(key, namespace.get(key));
                    }

                    return hashMap.entrySet();
                }

                @Override
                public int size() {
                    return namespace.getCount();
                }

                @Override
                public Collection<Object> values() {
                    java.util.ArrayList<Object> values = new
java.util.ArrayList<Object>();
                    for (String key : namespace) {
                        values.add(namespace.get(key));
                    }
                    return values;
                }
            });
            return scriptEngineManager;
     }

     static PivotTableViewColumn getPivotTableViewColumn(final Field field)
{
     for(Annotation annotation: field.getDeclaredAnnotations()){
            if (annotation instanceof PivotTableViewColumn){
             return (PivotTableViewColumn) annotation;
            }
         }
     return null;
     }
    }

    static Window create() throws Exception {
        return new Window() {{
            final Map<String, Object> namespace = new HashMap<String,
Object>();
            setTitle("Generic Table Views");
            setMaximized(true);
            setContent(new Border() {{
                setContent(new ScrollPane() {{

 setHorizontalScrollBarPolicy(ScrollPane.ScrollBarPolicy.FILL);
                    setView(new
GenericTableView<OlympicStanding>(OlympicStanding.class, namespace){{
                        namespace.put("tableView", this);

                        for (OlympicStanding os: createOlympicStandings()) {
                     add(os);
                     }
                    }}); // INSTANCE, name: <TableView>
                    // columnHeader(): WRITABLE_PROPERTY
                    setColumnHeader(new TableViewHeader() {{
                        setTableView((TableView)namespace.get("tableView"));
                        setSortMode(TableViewHeader.SortMode.MULTI_COLUMN);
                    }}); // INSTANCE, name: <TableViewHeader>
                }}); // INSTANCE, name: <ScrollPane>
            }}); // INSTANCE, name: <Border>
            CodeEmitterRuntime.initialize(this, namespace);
        }};
    }

    static java.util.List<OlympicStanding> createOlympicStandings() throws
Exception {
        java.util.List<OlympicStanding> ts = new
java.util.ArrayList<OlympicStanding>();

        // tableViewSortListeners(): LISTENER_LIST_PROPERTY
        ts.add(new OlympicStanding() {{
            setNation("China");
            setGold(51);
            setSilver(21);
            setBronze(28);
            setFlag(new
URL("file:/share/workspace/pivot/tutorials/src/org/apache/pivot/tutorials/tableviews/cn.png"));
        }}); // INSTANCE, name: <tableviews:OlympicStanding>
        ts.add(new OlympicStanding() {{
            setNation("United States");
            setGold(36);
            setSilver(38);
            setBronze(36);
            setFlag(new
URL("file:/share/workspace/pivot/tutorials/src/org/apache/pivot/tutorials/tableviews/us.png"));
        }}); // INSTANCE, name: <tableviews:OlympicStanding>
  }
}

On Tue, Jan 4, 2011 at 9:11 AM, calathus <[email protected]> wrote:

>
>
> On Mon, Dec 20, 2010 at 5:54 PM, Greg Brown <[email protected]> wrote:
>
>> > My goal was to create a generic class to support CRUD GUI from a given
>> Java Beans class. Although it is not generic version, Vaadin provides such
>> sample implementation which may be  immediately used for real projects.
>>
>> I'd be interested in learning more about how you envision something like
>> this might work.
>>
>
> Greg,
>
> I created a sample generic  TableView class which can take a parameter bean
> class and using the reflection library, it defines table view's column
> fields. This class is modified from tutorials tableviews sample.
> This is only for demonstration of the generic class approach in Pivot using
> builder class approach.
>
> In general, if we introduce new annotations for entity beans class to
> define more presentation related information (like width of column) , we can
> fine tune the look and feels.
> And the same entity beans can have another JPA annotation from which DB
> scheme can be generated and also some utility (like in netbeans) will allow
> to generate restful API from the entity beans.
>
> So if we define more GUI feature to support CRUD operation as generic class
> library, it become very simple to develop DB based web application.
> There is an  open source project called openxava which has similar
> approach, but its GUI is based on JSP and not so impressive compared to
> other GUI(web) projects.
> The degree of usability of such generic library may not be so general, but
> if there are a lot of entity classes, this type of approach would be quite
> useful.
> Also the pattern of these class may be used as starting point for other
> type of CRUD GUI.
>
> Following is the sample code:
>
>     public static class GenericTableView<T> extends TableView {
>
>      private final Class<T> cls;
>
>      public GenericTableView(final Class<T> cls, final Map<String, Object>
> namespace) throws Exception {
>      this.cls = cls;
>
>             for (final Field field: cls.getFields()) {
>              final String fname = field.getName();
>              getColumns().add(new TableView.Column() {{
>              setName(fname);
>                     setWidth(3, true);
>                     if (fname.equals("flag")) {
>                      setCellRenderer(new TableViewImageCellRenderer() {{
>                      }}); // INSTANCE, name:
> <content:TableViewImageCellRenderer>
>                     } else {
>                      setHeaderData(getCapitalName(fname));
>                     }
>                     System.out.println(">>> fname: "+fname);
>                 }});
>             }
>             getTableViewSortListeners().add(new
> TableViewSortListener.Adapter() {
>                 @Override
>                 @SuppressWarnings("unchecked")
>                 public void sortChanged(TableView tableView) {
>                  tableView.getTableData().setComparator(new
> org.apache.pivot.wtk.content.TableViewRowComparator(tableView));
>                 }
>             });
>         }
>
>      public void add(T... ts) {
>      for (T t: ts) {
>      getTableData().add(t);
>      }
>      }
>
>      static String getCapitalName(String name) {
>      if (name.length() == 0) return name;
>      return Character.toUpperCase(name.charAt(0))+name.substring(1);
>      }
>     }
>
>     static java.util.List<OlympicStanding> createOlympicStandings() throws
> Exception {
>         java.util.List<OlympicStanding> ts = new
> java.util.ArrayList<OlympicStanding>();
>
>         // tableViewSortListeners(): LISTENER_LIST_PROPERTY
>         ts.add(new OlympicStanding() {{
>             setNation("China");
>             setGold(51);
>             setSilver(21);
>             setBronze(28);
>             setFlag(new
> URL("file:/share/workspace/pivot/tutorials/src/org/apache/pivot/tutorials/tableviews/cn.png"));
>         }}); // INSTANCE, name: <tableviews:OlympicStanding>
>         ts.add(new OlympicStanding() {{
>             setNation("United States");
>             setGold(36);
>             setSilver(38);
>             setBronze(36);
>             setFlag(new
> URL("file:/share/workspace/pivot/tutorials/src/org/apache/pivot/tutorials/tableviews/us.png"));
>         }}); // INSTANCE, name: <tableviews:OlympicStanding>
>         return ts;
>  }
>
>     static Window create() throws Exception {
>         return new Window() {{
>             final Map<String, Object> namespace = new HashMap<String,
> Object>();
>             setTitle("Table Views");
>             setMaximized(true);
>             setContent(new Border() {{
>                 setContent(new ScrollPane() {{
>
>  setHorizontalScrollBarPolicy(ScrollPane.ScrollBarPolicy.FILL);
>                     setView(new
> GenericTableView<OlympicStanding>(OlympicStanding.class, namespace){{
>                         namespace.put("tableView", this);
>
>                         for (OlympicStanding os: createOlympicStandings())
> {
>                      add(os);
>                      }
>                     }}); // INSTANCE, name: <TableView>
>                     // columnHeader(): WRITABLE_PROPERTY
>                     setColumnHeader(new TableViewHeader() {{
>
>  setTableView((TableView)namespace.get("tableView"));
>                         setSortMode(TableViewHeader.SortMode.MULTI_COLUMN);
>                     }}); // INSTANCE, name: <TableViewHeader>
>                 }}); // INSTANCE, name: <ScrollPane>
>             }}); // INSTANCE, name: <Border>
>             CodeEmitterRuntime.initialize(this, namespace);
>         }};
>     }
>
>
>
>>
>> > I wondered if Pivot is really designed to support normal Java class
>> based GUI implementation.
>>
>> It most certainly is.  :-)  BXML is just a shortcut to coding your UI by
>> hand. Anything you can do in BXML, you can do in Java (though, in many
>> cases, not quite as conveniently).
>>
>> > Regarding to the translator, since there is no detail sample how to use
>> these Java API directly, it would be helpful if we have such bxml to Java
>> translator.
>> > But ideally, Pivot site should include more detailed sample/explanation
>> for Java Pivot API based approach(without bxml). Then we would not need such
>> a tool.
>>
>> If you read the BXML Primer, you should have a good understanding of how
>> BXML maps to Java. There's no magic to it - it is very straightforward.
>>
>> > Also if we may really have declarative GUI design, using Scala may be
>> more attractive way. Scala would allow declaring GUI in equivalent code side
>> as BXML.
>>
>> I'm not sure how this would work. Scala is conceptually more akin to Java
>> than markup. Could you elaborate?
>>
>> > BTW, I still wonder where the following code went wrong.  I would
>> appreciate your suggestion for the following code(java verson of
>> custom_table_view.bxml).
>> > When it is run, it opens the applet window, but it does not show
>> anything.
>>
>> Two errors:
>>
>> - You need to call border.setContent(scrollPane), not
>> border.add(scrollPane).
>>
>> - You need to call scrollPane.setView(tableView). Otherwise, the scroll
>> pane won't know what it's content is.
>>
>> I made these changes and the app worked fine.
>>
>> G
>>
>>
>>
>
>
> --
> Cheers,
> calathus
>
>
>
>


-- 
Cheers,
calathus

Reply via email to