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(140));
161 grid.add(new SolidLabel(labelText, Font.ITALIC));
162 if (component instanceof TextField) {
163 ((TextField) component).setWidth(new Extent(530));
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() == cancelButton) {
201 window.setVisible(false);
202 dispose();
203 } else {
204 save();
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 }