001 // This file is part of the Attempto Java Packages. 002 // Copyright 2008-2009, 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; 016 017 import java.util.Collections; 018 import java.util.List; 019 020 import nextapp.echo2.app.Color; 021 import nextapp.echo2.app.Column; 022 import nextapp.echo2.app.Component; 023 import nextapp.echo2.app.Font; 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 ch.uzh.ifi.attempto.acewiki.Task; 030 import ch.uzh.ifi.attempto.acewiki.Wiki; 031 import ch.uzh.ifi.attempto.acewiki.core.ontology.Individual; 032 import ch.uzh.ifi.attempto.acewiki.core.ontology.NounConcept; 033 import ch.uzh.ifi.attempto.acewiki.core.ontology.OntologyElement; 034 import ch.uzh.ifi.attempto.acewiki.core.ontology.Sentence; 035 import ch.uzh.ifi.attempto.acewiki.core.text.OntologyTextElement; 036 import ch.uzh.ifi.attempto.acewiki.gui.editor.CommentEditorWindow; 037 import ch.uzh.ifi.attempto.acewiki.gui.editor.SentenceEditorHandler; 038 import ch.uzh.ifi.attempto.acewiki.gui.page.ArticlePage; 039 import ch.uzh.ifi.attempto.acewiki.gui.page.LogicPage; 040 import ch.uzh.ifi.attempto.acewiki.gui.page.SentencePage; 041 import ch.uzh.ifi.attempto.acewiki.gui.page.WikiPage; 042 import ch.uzh.ifi.attempto.echocomp.DelayedComponent; 043 import ch.uzh.ifi.attempto.echocomp.HSpace; 044 import ch.uzh.ifi.attempto.echocomp.Label; 045 import ch.uzh.ifi.attempto.echocomp.MessageWindow; 046 import ch.uzh.ifi.attempto.echocomp.SolidLabel; 047 import ch.uzh.ifi.attempto.echocomp.VSpace; 048 import ch.uzh.ifi.attempto.preditor.text.BasicTextElement; 049 import ch.uzh.ifi.attempto.preditor.text.TextElement; 050 051 /** 052 * This class represents a text row that consists of a drop down menu and an ACE text. 053 * 054 * @author Tobias Kuhn 055 */ 056 public class TextRow extends Column implements ActionListener { 057 058 private static final long serialVersionUID = -540135972060005725L; 059 060 private Sentence sentence; 061 private Wiki wiki; 062 private WikiPage hostPage; 063 064 private Row sentenceRow = new Row(); 065 private DropDownMenu dropDown; 066 private Label waitIcon = new Label(new ResourceImageReference("ch/uzh/ifi/attempto/acewiki/gui/img/wait.gif")); 067 068 /** 069 * Creates a new text row. The host page is the page that contains the text row (which is 070 * not necessarily the owner page of the sentence). 071 * 072 * @param sentence The sentence to be shown. 073 * @param hostPage The host page of the text row. 074 */ 075 public TextRow(Sentence sentence, WikiPage hostPage) { 076 this.sentence = sentence; 077 this.hostPage = hostPage; 078 this.wiki = hostPage.getWiki(); 079 update(); 080 } 081 082 private void update() { 083 if (sentence.isInferred()) { 084 dropDown = new DropDownMenu("light-blue", this); 085 } else if (sentence.isReasonerParticipant() || (sentence.isQuestion() && sentence.isOWL()) ) { 086 dropDown = new DropDownMenu("blue", this); 087 } else { 088 dropDown = new DropDownMenu("red", this); 089 } 090 if (!sentence.isIntegrated() && !sentence.isInferred()) { 091 dropDown.addMenuEntry("Reassert"); 092 dropDown.addMenuSeparator(); 093 } 094 if (!sentence.isInferred()) { 095 dropDown.addMenuEntry("Edit..."); 096 } 097 if (hostPage instanceof ArticlePage) { 098 dropDown.addMenuEntry("Add Sentence..."); 099 dropDown.addMenuEntry("Add Comment..."); 100 } 101 if (!sentence.isInferred()) { 102 dropDown.addMenuEntry("Delete"); 103 } 104 dropDown.addMenuSeparator(); 105 dropDown.addMenuEntry("Details"); 106 dropDown.addMenuEntry("Logic"); 107 108 Row r = new Row(); 109 Color color = Color.BLACK; 110 boolean isRed = !sentence.isIntegrated() && !sentence.isInferred() && !sentence.isQuestion(); 111 if (isRed) { 112 color = new Color(193, 0, 0); 113 } 114 for (TextElement e : sentence.getTextElements()) { 115 if (!e.getText().matches("[.?]") && r.getComponentCount() > 0) { 116 r.add(new HSpace()); 117 } 118 if (e instanceof OntologyTextElement) { 119 // Proper names with definite articles are handled differently: 120 // The "the" is not a part of the link. Probably, this should be done at a different place... 121 OntologyTextElement ote = (OntologyTextElement) e; 122 OntologyElement oe = ote.getOntologyElement(); 123 if (oe instanceof Individual) { 124 Individual ind = (Individual) oe; 125 int wn = ote.getWordNumber(); 126 127 if (ind.hasDefiniteArticle(wn)) { 128 SolidLabel l = new SolidLabel(e.getText().substring(0, 3)); 129 l.setForeground(color); 130 r.add(l); 131 r.add(new HSpace()); 132 r.add(new WikiLink(oe, oe.getPrettyWord(wn + 1), wiki, isRed)); 133 } else { 134 r.add(new WikiLink(((OntologyTextElement) e), wiki, isRed)); 135 } 136 } else { 137 r.add(new WikiLink(((OntologyTextElement) e), wiki, isRed)); 138 } 139 } else { 140 SolidLabel l = new SolidLabel(e.getText()); 141 l.setForeground(color); 142 r.add(l); 143 } 144 } 145 146 removeAll(); 147 sentenceRow.removeAll(); 148 sentenceRow.add(dropDown); 149 sentenceRow.add(new HSpace(5)); 150 sentenceRow.add(r); 151 sentenceRow.add(new HSpace(5)); 152 sentenceRow.add(waitIcon); 153 waitIcon.setVisible(false); 154 sentenceRow.add(new HSpace(5)); 155 add(sentenceRow); 156 157 if (sentence.isQuestion() && hostPage instanceof ArticlePage) { 158 159 Column answerColumn = new Column(); 160 answerColumn.setInsets(new Insets(20, 0, 0, 0)); 161 add(answerColumn); 162 163 Column cachedAnswerCol = new Column(); 164 List<OntologyElement> answer = sentence.getCachedAnswer(); 165 if (answer == null) { 166 cachedAnswerCol.add(new SolidLabel("...", Font.ITALIC, 10)); 167 } else if (answer.size() > 0) { 168 Collections.sort(answer); 169 for (OntologyElement oe : answer) { 170 Row answerRow = new Row(); 171 if (oe instanceof NounConcept) { 172 BasicTextElement a = new BasicTextElement("a"); 173 a.checkNeighborTextElements(new BasicTextElement(""), new BasicTextElement(oe.getWord())); 174 answerRow.add(new ListItem(new SolidLabel(a.getText()), new HSpace(), new WikiLink(oe, wiki))); 175 } else { 176 answerRow.add(new ListItem(new WikiLink(oe, wiki))); 177 } 178 cachedAnswerCol.add(answerRow); 179 } 180 } else { 181 cachedAnswerCol.add(new SolidLabel("(no answer found)", Font.ITALIC, 10)); 182 } 183 cachedAnswerCol.add(new VSpace(4)); 184 185 if (sentence.isAnswerCached()) { 186 187 answerColumn.add(cachedAnswerCol); 188 189 } else { 190 waitIcon.setVisible(true); 191 answerColumn.add( 192 new DelayedComponent(cachedAnswerCol, true) { 193 194 private static final long serialVersionUID = 7865984138467729544L; 195 196 public Component initComponent() { 197 Column column = new Column(); 198 List<OntologyElement> answer = sentence.getAnswer(); 199 if (answer == null) { 200 column.add(new SolidLabel("...", Font.ITALIC, 10)); 201 } else if (answer.size() > 0) { 202 Collections.sort(answer); 203 for (OntologyElement oe : answer) { 204 Row answerRow = new Row(); 205 if (oe instanceof NounConcept) { 206 BasicTextElement a = new BasicTextElement("a"); 207 a.checkNeighborTextElements(new BasicTextElement(""), new BasicTextElement(oe.getWord())); 208 answerRow.add(new ListItem(new SolidLabel(a.getText()), new HSpace(), new WikiLink(oe, wiki))); 209 } else { 210 answerRow.add(new ListItem(new WikiLink(oe, wiki))); 211 } 212 column.add(answerRow); 213 } 214 } else { 215 column.add(new SolidLabel("(no answer found)", Font.ITALIC, 10)); 216 } 217 column.add(new VSpace(4)); 218 219 return column; 220 } 221 222 public void finalizeAction() { 223 waitIcon.setVisible(false); 224 } 225 226 } 227 ); 228 } 229 230 } 231 } 232 233 public void actionPerformed(ActionEvent e) { 234 if (e.getActionCommand().equals("Edit...")) { 235 wiki.log("page", "dropdown: edit sentence: " + sentence.getText()); 236 ArticlePage page = ArticlePage.create(sentence.getOwner(), wiki); 237 wiki.showPage(page); 238 wiki.showWindow(SentenceEditorHandler.generatePreditorEditWindow(sentence, page)); 239 } else if (e.getActionCommand().equals("Add Sentence...")) { 240 wiki.log("page", "dropdown: add sentence"); 241 wiki.showWindow(SentenceEditorHandler.generatePreditorAddWindow(sentence, (ArticlePage) hostPage)); 242 } else if (e.getActionCommand().equals("Add Comment...")) { 243 wiki.log("page", "dropdown: add comment"); 244 wiki.showWindow(new CommentEditorWindow(sentence, (ArticlePage) hostPage, false)); 245 } else if (e.getActionCommand().equals("Delete")) { 246 wiki.log("page", "dropdown: delete sentence: " + sentence.getText()); 247 wiki.showWindow(new MessageWindow("Delete", "Do you really want to delete this sentence?", null, this, "Yes", "No")); 248 } else if (e.getActionCommand().equals("Reassert")) { 249 int success = sentence.reassert(); 250 if (success == 1) { 251 wiki.showWindow(new MessageWindow("Conflict", "A sentence is in conflict with the current knowledge. For that reason, it cannot be added to the knowledge base.", "OK")); 252 } else if (success == 2) { 253 wiki.showWindow(new MessageWindow("Error", "A sentence could not be added to the knowledge base because the knowledge base got too complex.", "OK")); 254 } 255 if (sentence.isIntegrated()) { 256 update(); 257 } 258 } else if (e.getActionCommand().equals("Details")) { 259 wiki.log("page", "dropdown: details sentence: " + sentence.getText()); 260 wiki.showPage(new SentencePage(wiki, sentence)); 261 } else if (e.getActionCommand().equals("Logic")) { 262 wiki.log("page", "dropdown: logic sentence: " + sentence.getText()); 263 wiki.showPage(new LogicPage(wiki, sentence)); 264 } else if (e.getSource() instanceof MessageWindow && e.getActionCommand().equals("Yes")) { 265 wiki.log("page", "dropdown: delete confirmed: " + sentence.getText()); 266 267 wiki.enqueueAsyncTask( 268 "Updating", 269 "The sentence is being removed from the knowledge base...", 270 new Task() { 271 public void run() { 272 sentence.getOwner().remove(sentence); 273 } 274 public void updateGUI() { 275 wiki.update(); 276 wiki.refresh(); 277 } 278 } 279 ); 280 } 281 } 282 283 }