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 }