Let the user change the column order in Java/Swing

November 18th, 2011 · No Comments

Do you have the requirement to let the user of your application change the order
of his columns and your app is based on Swing?

Then you should read further. Below you find a TableColumnModel that has
two states: STANDARD and USERDEFINED.
In the STANDARD state the user may not change the order of the columns by drag’n'drop,
in USERDEFINED he may. The good thing: If you toogle the state the column order is restored.

Just a hint: If you want to store the column order, first get it by calling getColumnMap().

Before you ask you to use it. Try setModel of your JTable class ;)

Have fun!

public class StatefulTableColumnModel extends DefaultTableColumnModel {
 
    public enum Mode {
        STANDARD, USERDEFINED;
    }
 
    private int columnMap[];
    private Mode mode = Mode.STANDARD; 
 
    public StatefulTableColumnModel(Mode mode, int[] columnMap) {
        this.columnMap = columnMap;
        if(mode!=null) 
            setMode(mode);
        else
            setMode(Mode.STANDARD);
    }
 
    public void setMode(Mode mode) {
        this.mode = mode;
        refresh();
    }
 
    public Mode getMode() {
        return this.mode;
    }
 
    public int[] getColumnMap() {
        return columnMap;
    }
 
    /* (non-Javadoc)
     * @see javax.swing.table.DefaultTableColumnModel#fireColumnMoved(javax.swing.event.TableColumnModelEvent)
     */
    @Override
    protected void fireColumnMoved(TableColumnModelEvent e) {
        switch(mode) {
        case USERDEFINED:
            // if columns have been moved there might have been Drag'n'Drop operations,
            // so update the state 
            columnMap = getColumnPositions();
            break;
        case STANDARD:
            // in standard mode drag'n'drop operations are not permitted, so reset the order
            resetColumnPositions();
            break;
        }
        super.fireColumnMoved(e);
    }
 
    /**
     * re-order table columns depending on their model index (this resets the original order), don't update view
     */
    private void resetColumnPositions() {
        Collections.sort(tableColumns, new Comparator<TableColumn>() {
            public int compare(TableColumn o1, TableColumn o2) {
                return new Integer(o1.getModelIndex()).compareTo(o2.getModelIndex());
            }
        });
    }
 
    /**
     * set the visible column positions (independent of state), don't update view
     */
    private void setColumnPositions(final int columnMap[]) {
        resetColumnPositions();
        if(columnMap!=null) {
            Vector<TableColumn> newOrder = new Vector<TableColumn>(tableColumns.capacity());
            newOrder.setSize(tableColumns.size());
            int i=0;
            for(TableColumn column: tableColumns) {
                // lookup new position in newOrder
                int newPos = columnMap[i++];
                newOrder.set(newPos, column);
            }
            tableColumns = newOrder;
        }
    }
 
    /**
     * @return the visible column positions (independent of state)
     */
    private int[] getColumnPositions() {
        int result[] = new int[tableColumns.size()];
        int i=0;
        for(TableColumn column: tableColumns) {
            int modelIndex = column.getModelIndex();
            result[modelIndex] = i++;
        }
        return result;
    }
 
    /**
     * 
     */
    public void refresh() {
        switch(mode) {
        case STANDARD:
            // reset position
            resetColumnPositions();
            break;
        case USERDEFINED:
            setColumnPositions(columnMap);
            break;
        }        
        // inform view that column order has changed (seems to be sufficient to just tell 0 has moved to 1)
        super.fireColumnMoved(new TableColumnModelEvent(this, 0, 1));        
    }
 
}

→ No CommentsTopics: · , , ,

Openbahn-API – Bahn-Webseite als Webservice

June 22nd, 2011 · 4 Comments

As this is only of interest for German users – this article is in German only. It’s about a new project of mine. Sorry folks.

Ich bin gerade dabei eine Android-App zu entwickeln, mit der es möglich ist Fahrkarten für Bahn-Pendler einfacher zu buchen.
Bei der Entwicklung ist mir aufgefallen, dass die Bahn leider keine Webservices nach außen zur Verfügung stellt – die Webseite www.bahn.de ist zusammen mit der mobilen Variante m.bahn.de die einzige Schnittstelle.

Daher habe ich das Projekt Openbahn-API ins Leben gerufen: Es handelt sich um eine API, die Funktionalitäten der Bahn-Webseite als Webservices zur Verfügung stellt. Über diese Services können eigene Programme die verfügbaren Bahnhöfe oder Zugverbindungen inkl. Zeiten und Preise abrufen. Des Weiteren ist es über die Schnittstelle möglich, Zugtickets zu buchen oder Sitzplätze zu reservieren.

Die Dokumentation und URLs zu den einzelnen Services finden sich auf der Projektseite unter http://code.google.com/p/openbahn-api. Diese werden über HTTP-GET aufgerufen und liefern JSON Objekte zurück. So gibt der Aufruf von http://openbahnapi.appspot.com/rest/stations/list?contains=karlsr eine Liste von JSON-Objekten zurück, die alle Bahnhöfe enthalten, die im Namen „karlsr“ enthalten. Im Beispiel sind dies die gesamten Bahnhöfe im Stadtgebiet von Karlsruhe.

Die API kann verwendet werden, um eigene Anwendungen zu entwickeln, die Bahndaten benötigen.

Um die Qualität des Parsers zu sichern, wird der Code komplett als GPL auf Google Code unter http://code.google.com/p/openbahn-api zur Verfügung gestellt – jeder Entwickler ist herzlich dazu eingeladen Verbesserungen und Erweiterungen vorzunehmen. Das Hosting erfolgt über die Google AppEngine. Die Ergebnisse der Anfragen werden über einen Cache zwischengespeichert, so dass die Kommunikation mit der Bahn-Webseite minimiert wird und für vorhandene Ergebnisse auch funktioniert, wenn diese offline ist.

Ich bin gespannt auf eure Meinung und wünsche euch viel Spaß mit der neuen API.

→ 4 CommentsTopics: · , , , , , , ,

How to detect whether an element is in a scrollable parent

November 2nd, 2009 · 1 Comment

Just think of having an element in a scrollable parent (the CSS property overflow is set to scroll) and you want to test whether the element is visible or not.

Using this little function you can do the trick:

function isInView(node){
            var offsetParent = node.offsetParent;
            var top = offsetParent.scrollTop;
            var height = offsetParent.offsetHeight;
            var y = node.offsetTop;
            return y >= top && y <= (top + height);
}

And here’s a small use case – this one scrolls the element into the visible region, if it is not already in the view:

if(!isInView(element)) {
            element.scrollIntoView();
}

→ 1 CommentTopics: · , , , , , , , , ,

Let the user select an item in a modal dialog

August 5th, 2009 · 1 Comment

After having used the shiny new YUI3 library for a project, it’s about time to share my YUI3 experiences with you.
For the project I built an item selector: A modal dialog is openend and the user has to select an item. After selection the dialog is closed and the selected item is passed to a callback function.

Here you can find the full source for the item selector. An example to use the selector can be as simple as this:

ms.ItemSelector.selectItem(['Bart', 'Lisa', 'Homer', 'Marge', 'Maggie', 'Ned', 'Barney', 'Bob'], function(item){
  alert(item + ' is your favorite character.');
});

Just click on the following button, to start the example. Enjoy and let me know your comments.


→ 1 CommentTopics: · , , , , , ,

Quince: UX Pattern Explorer

June 13th, 2009 · No Comments

Just in case you don’t already know it: Quince – calls itself an UX Patterns Explorer and that’s just what it is.

You want to improve the user experience of your applications? Just take a look at this marble. It contains a large number of design patterns for creating great user interfaces.

Even the exploration part of this tool is innovative: The patterns are not only ordered alphabetically by name but can be found by the tasks the user wants to accomplish.

→ No CommentsTopics: · , , ,