    001    // This file is part of the Attempto Java Packages.
    002    // Copyright 2008, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch).
    003    //
    004    // The Attempto Java Packages is free software: you can redistribute it and/or modify it under the
    005    // terms of the GNU Lesser General Public License as published by the Free Software Foundation,
    006    // either version 3 of the License, or (at your option) any later version.
    007    //
    008    // The Attempto Java Packages is distributed in the hope that it will be useful, but WITHOUT ANY
    009    // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
    010    // PURPOSE. See the GNU Lesser General Public License for more details.
    011    //
    012    // You should have received a copy of the GNU Lesser General Public License along with the Attempto
    013    // Java Packages. If not, see http://www.gnu.org/licenses/.
    014
    015    package ch.uzh.ifi.attempto.acewiki.gui.editor;
    016
    017    import nextapp.echo2.app.Alignment;
    018    import nextapp.echo2.app.Column;
    019    import nextapp.echo2.app.Component;
    020    import nextapp.echo2.app.ContentPane;
    021    import nextapp.echo2.app.Extent;
    022    import nextapp.echo2.app.Font;
    023    import nextapp.echo2.app.Grid;
    024    import nextapp.echo2.app.Insets;
    025    import nextapp.echo2.app.ResourceImageReference;
    026    import nextapp.echo2.app.Row;
    027    import nextapp.echo2.app.event.ActionEvent;
    028    import nextapp.echo2.app.event.ActionListener;
    029    import nextapp.echo2.app.layout.GridLayoutData;
    030    import ch.uzh.ifi.attempto.acewiki.Wiki;
    031    import ch.uzh.ifi.attempto.acewiki.core.ontology.OntologyElement;
    032    import ch.uzh.ifi.attempto.acewiki.core.text.OntologyTextElement;
    033    import ch.uzh.ifi.attempto.acewiki.core.text.TextElemFactory;
    034    import ch.uzh.ifi.attempto.echocomp.GeneralButton;
    035    import ch.uzh.ifi.attempto.echocomp.Label;
    036    import ch.uzh.ifi.attempto.echocomp.MessageWindow;
    037    import ch.uzh.ifi.attempto.echocomp.SolidLabel;
    038    import ch.uzh.ifi.attempto.echocomp.TextField;
    039    import ch.uzh.ifi.attempto.echocomp.WindowPane;
    040
    041    /**
    042     * This abstract class contains the basic structure for forms to create and modify words
    043     * (represented by ontology elements).
    044     *
    045     * @author Tobias Kuhn
    046     */
    047    public abstract class FormPane extends ContentPane implements ActionListener {
    048
    049            private Wiki wiki;
    050            private ActionListener actionListener;
    051
    052            private Column column;
    053            private WindowPane window;
    054            private Grid iconRow;
    055            private GeneralButton okButton;
    056            private GeneralButton cancelButton;
    057
    058            /**
    059             * Initializes the form pane.
    060             *
    061             * @param window The host window.
    062             * @param wiki The wiki instance.
    063             * @param actionListener The actionlistener.
    064             */
    065            protected FormPane(WindowPane window, Wiki wiki, ActionListener actionListener) {
    066                    this.window = window;
    067                    this.wiki = wiki;
    068                    this.actionListener = actionListener;
    069
    070                    Grid grid = new Grid(1);
    071                    grid.setRowHeight(0, new Extent(330));
    072                    grid.setRowHeight(1, new Extent(30));
    073
    074                    column = new Column();
    075                    column.setInsets(new Insets(10, 20, 0, 0));
    076                    column.setCellSpacing(new Extent(10));
    077                    GridLayoutData gridLayout = new GridLayoutData();
    078                    gridLayout.setAlignment(new Alignment(Alignment.LEFT, Alignment.TOP));
    079                    column.setLayoutData(gridLayout);
    080                    grid.add(column);
    081
    082                    iconRow = new Grid(2);
    083                    iconRow.setRowHeight(0, new Extent(110));
    084                    iconRow.setColumnWidth(0, new Extent(100));
    085                    iconRow.setInsets(new Insets(0, 0, 10, 20));
    086                    column.add(iconRow);
    087
    088                    Row footerRow = new Row();
    089                    footerRow.setInsets(new Insets(10, 0, 0, 0));
    090                    footerRow.add(new Label("* required field", Font.ITALIC, 11));
    091                    grid.add(footerRow);
    092
    093                    Row buttonBar = new Row();
    094                    buttonBar.setAlignment(new Alignment(Alignment.RIGHT, Alignment.CENTER));
    095                    buttonBar.setInsets(new Insets(10, 10, 10, 10));
    096                    buttonBar.setCellSpacing(new Extent(5));
    097                    okButton = new GeneralButton("OK", 70, this);
    098                    buttonBar.add(okButton);
    099                    cancelButton = new GeneralButton("Cancel", 70, this);
    100                    buttonBar.add(cancelButton);
    101                    grid.add(buttonBar);
    102
    103                    add(grid);
    104            }
    105
    106            /**
    107             * Returns the wiki instance.
    108             *
    109             * @return The wiki instance.
    110             */
    111            protected Wiki getWiki() {
    112                    return wiki;
    113            }
    114
    115            /**
    116             * This method should try to save the word with the current properties and should show
    117             * error messages if this is not successful. In the case of success, one of the
    118             * finished-methods has to be called.
    119             *
    120             * @see #finished(OntologyElement)
    121             * @see #finished(OntologyElement, int)
    122             */
    123            protected abstract void save();
    124
    125            /**
    126             * This method should be called when the saving process is finished successfully.
    127             *
    128             * @param el The created or modified ontology element.
    129             */
    130            protected void finished(OntologyElement el) {
    131                    finished(el, 0);
    132            }
    133
    134            /**
    135             * This method should be called when the saving process is finished successfully.
    136             *
    137             * @param el The created or modified ontology element.
    138             * @param wordNumber The word form id.
    139             */
    140            protected void finished(OntologyElement el, int wordNumber) {
    141                    window.setVisible(false);
    142                    dispose();
    143
    144                    // a text element is used to store the ontology element and the word number in one object:
    145                    OntologyTextElement te = TextElemFactory.createTextElement(el, wordNumber);
    146                    actionListener.actionPerformed(new ActionEvent(te, ""));
    147            }
    148
    149            /**
    150             * Adds a new row to the form.
    151             *
    152             * @param labelText The text for the label shown on the left hand side of the component.
    153             * @param component The component, i.e. a text field.
    154             * @param explanation An explanation text shown under the component.
    155             * @param required Defines whether the component should be marked as required.
    156             */
    157            protected void addRow(String labelText, Component component, String explanation, boolean required) {
    158                    Grid grid = new Grid(3);
    159                    grid.setInsets(new Insets(0, 0, 5, 0));
    160                    grid.setColumnWidth(0, new Extent(120));
    161                    grid.add(new SolidLabel(labelText, Font.ITALIC));
    162                    if (component instanceof TextField) {
    163                            ((TextField) component).setWidth(new Extent(550));
    164                    }
    165                    grid.add(component);
    166                    if (required) {
    167                            grid.add(new Label("*", Font.ITALIC, 11));
    168                    } else {
    169                            grid.add(new Label());
    170                    }
    171                    grid.add(new Label());
    172                    grid.add(new Label(explanation, Font.ITALIC, 11));
    173                    column.add(grid);
    174            }
    175
    176            /**
    177             * Sets the icon row. The icon row is shown at the top of the form and shows an icon of the
    178             * ontological structure that is represented by the word. On the right hand side of the icon,
    179             * an explanatory text is shown.
    180             *
    181             * @param iconName The name of the icon, one of "individual", "concept", or "role".
    182             * @param text The explanatory text.
    183             */
    184            protected void setIconRow(String iconName, String text) {
    185                    iconRow.removeAll();
    186                    iconRow.add(new Label(new ResourceImageReference("ch/uzh/ifi/attempto/acewiki/gui/img/" + iconName + ".png")));
    187                    iconRow.add(new Label(text, Font.ITALIC));
    188            }
    189
    190            /**
    191             * Shows an error message.
    192             *
    193             * @param text The error text.
    194             */
    195            protected void showErrorMessage(String text) {
    196                    wiki.showWindow(new MessageWindow("Error", text, window, "OK"));
    197            }
    198
    199            public void actionPerformed(ActionEvent e) {
    200                    if (e.getSource() == okButton) {
    201                            save();
    202                    } else if (e.getSource() == cancelButton) {
    203                            window.setVisible(false);
    204                            dispose();
    205                    }
    206            }
    207
    208            /**
    209             * Normalizes the string. All white spaces are replaced by underscores. Afterwards, leading and
    210             * trailing underscores are removed and successive underscores are replaced by just one underscore.
    211             *
    212             * @param s The string to be normalized.
    213             * @return The normalized string.
    214             */
    215            protected static String normalize(String s) {
    216                    return s.replaceAll("\\s", "_").replaceAll("(_)+", "_").replaceAll("^_", "").replaceAll("_$", "");
    217            }
    218
    219            /**
    220             * Returns true if the string is a valid to be used as a word form. The first character must be
    221             * one of a-z, A-Z. The following characters have to be one of a-z, A-Z, 0-9, -, _.
    222             *
    223             * @param s The string to be checked for validity.
    224             * @return true if the string is valid.
    225             */
    226            protected static boolean isValidString(String s) {
    227                    if (s.length() == 0) return true;
    228                    boolean first = true;
    229                    for (byte b : s.getBytes()) {
    230                            if (first) {
    231                                    first = false;
    232                                    if (b >= 'a' && b <= 'z') continue;
    233                                    if (b >= 'A' && b <= 'Z') continue;
    234                                    return false;
    235                            } else {
    236                                    if (b >= 'a' && b <= 'z') continue;
    237                                    if (b >= 'A' && b <= 'Z') continue;
    238                                    if (b >= '0' && b <= '9') continue;
    239                                    if (b == '-') continue;
    240                                    if (b == '_') continue;
    241                                    return false;
    242                            }
    243                    }
    244                    return true;
    245            }
    246
    247    }