001 // This file is part of AceWiki. 002 // Copyright 2008-2012, AceWiki developers. 003 // 004 // AceWiki is free software: you can redistribute it and/or modify it under the terms of the GNU 005 // Lesser General Public License as published by the Free Software Foundation, either version 3 of 006 // the License, or (at your option) any later version. 007 // 008 // AceWiki is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 009 // even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 010 // Lesser General Public License for more details. 011 // 012 // You should have received a copy of the GNU Lesser General Public License along with AceWiki. If 013 // not, see http://www.gnu.org/licenses/. 014 015 package ch.uzh.ifi.attempto.acewiki.gui; 016 017 import java.util.ArrayList; 018 import java.util.List; 019 020 import nextapp.echo.app.Column; 021 import nextapp.echo.app.Extent; 022 import nextapp.echo.app.Font; 023 import nextapp.echo.app.Insets; 024 import nextapp.echo.app.Row; 025 import nextapp.echo.app.event.ActionEvent; 026 import nextapp.echo.app.event.ActionListener; 027 import ch.uzh.ifi.attempto.acewiki.Task; 028 import ch.uzh.ifi.attempto.acewiki.core.CachingReasoner; 029 import ch.uzh.ifi.attempto.acewiki.core.Concept; 030 import ch.uzh.ifi.attempto.acewiki.core.LanguageUtils; 031 import ch.uzh.ifi.attempto.acewiki.core.OntologyElement; 032 import ch.uzh.ifi.attempto.acewiki.core.Sentence; 033 import ch.uzh.ifi.attempto.acewiki.core.StatementFactory; 034 import ch.uzh.ifi.attempto.echocomp.SolidLabel; 035 import ch.uzh.ifi.attempto.echocomp.VSpace; 036 037 /** 038 * This class represents a page that shows the super-concepts and sub-concepts for a given concept. 039 * Such super- and sub-concept relations are called "hierarchy" in AceWiki. 040 * 041 * @author Tobias Kuhn 042 */ 043 public class HierarchyPage extends WikiPage implements ActionListener { 044 045 private static final long serialVersionUID = 3126817139010810197L; 046 047 private static final int pageSize = 25; 048 049 private ConceptPage page; 050 private RecalcIcon upRecalcIcon = new RecalcIcon("This list is being updated."); 051 private RecalcIcon downRecalcIcon = new RecalcIcon("This list is being updated."); 052 private Title title; 053 054 private Column upHierarchyColumn = new Column(); 055 private Column downHierarchyColumn = new Column(); 056 private int upChosenPage = 0; 057 private int downChosenPage = 0; 058 059 /** 060 * Creates a new hierarchy page. 061 * 062 * @param page The main page that contains the article. 063 */ 064 public HierarchyPage(ConceptPage page) { 065 super(page.getWiki()); 066 this.page = page; 067 068 addTab("Article", this); 069 addTab("References", this); 070 addTab("Individuals", this); 071 addSelectedTab("Hierarchy"); 072 073 OntologyElement oe = page.getOntologyElement(); 074 title = new Title(getHeading(oe), "- Hierarchy", oe.getType(), this); 075 add(title); 076 addHorizontalLine(); 077 add(new VSpace(12)); 078 079 upRecalcIcon.setVisible(false); 080 addHeadline("Upward", upRecalcIcon); 081 add(new VSpace(5)); 082 add(upHierarchyColumn); 083 084 downRecalcIcon.setVisible(false); 085 addHeadline("Downward", downRecalcIcon); 086 add(new VSpace(5)); 087 add(downHierarchyColumn); 088 } 089 090 protected void doUpdate() { 091 title.setText(getHeading(page.getOntologyElement())); 092 upHierarchyColumn.removeAll(); 093 downHierarchyColumn.removeAll(); 094 095 Concept c = (Concept) page.getOntologyElement(); 096 CachingReasoner cr = getWiki().getOntology().getReasoner(); 097 098 if (cr.areCachedSuperConceptsUpToDate(c)) { 099 upHierarchyColumn.add(new HierarchyComponent(true, true)); 100 } else { 101 upRecalcIcon.setVisible(true); 102 upHierarchyColumn.add(new HierarchyComponent(true, true)); 103 page.getWiki().enqueueWeakAsyncTask(new Task() { 104 105 private HierarchyComponent delayedComp; 106 107 public void run() { 108 delayedComp = new HierarchyComponent(true, false); 109 } 110 111 public void updateGUI() { 112 upHierarchyColumn.removeAll(); 113 upHierarchyColumn.add(delayedComp); 114 upRecalcIcon.setVisible(false); 115 } 116 117 }); 118 } 119 120 if (cr.areCachedSuperConceptsUpToDate(c)) { 121 downHierarchyColumn.add(new HierarchyComponent(false, true)); 122 } else { 123 downRecalcIcon.setVisible(true); 124 downHierarchyColumn.add(new HierarchyComponent(false, true)); 125 page.getWiki().enqueueWeakAsyncTask(new Task() { 126 127 private HierarchyComponent delayedComp; 128 129 public void run() { 130 delayedComp = new HierarchyComponent(false, false); 131 } 132 133 public void updateGUI() { 134 downHierarchyColumn.removeAll(); 135 downHierarchyColumn.add(delayedComp); 136 downRecalcIcon.setVisible(false); 137 } 138 139 }); 140 } 141 } 142 143 public void actionPerformed(ActionEvent e) { 144 if ("Article".equals(e.getActionCommand())) { 145 log("page", "pressed: article"); 146 getWiki().showPage(page); 147 } else if ("References".equals(e.getActionCommand())) { 148 log("page", "pressed: references"); 149 getWiki().showPage(new ReferencesPage(page)); 150 } else if ("Individuals".equals(e.getActionCommand())) { 151 log("page", "pressed: individuals"); 152 getWiki().showPage(new IndividualsPage(page)); 153 } else if (e.getSource() == title) { 154 getWiki().showEditorWindow(page.getOntologyElement()); 155 } 156 } 157 158 public boolean equals(Object obj) { 159 if (obj instanceof HierarchyPage) { 160 return page.equals(((HierarchyPage) obj).page); 161 } 162 return false; 163 } 164 165 public boolean isExpired() { 166 return page.isExpired(); 167 } 168 169 public String toString() { 170 return "-IND- " + page.getOntologyElement().getWord(); 171 } 172 173 private class HierarchyComponent extends Column implements ActionListener { 174 175 private static final long serialVersionUID = 6461817187189387351L; 176 177 private boolean up; 178 private Column column = new Column(); 179 private IndexBar indexBar; 180 private List<Sentence> sentences; 181 182 183 public HierarchyComponent(boolean up, boolean cached) { 184 this.up = up; 185 indexBar = new IndexBar("Page:", 0, this); 186 add(indexBar); 187 column.setInsets(new Insets(10, 2, 5, 10)); 188 column.setCellSpacing(new Extent(2)); 189 add(column); 190 191 Concept concept = (Concept) page.getOntologyElement(); 192 CachingReasoner cr = getWiki().getOntology().getReasoner(); 193 List<Concept> concepts; 194 195 if (up) { 196 if (cached) { 197 concepts = cr.getCachedSuperConcepts(concept); 198 } else { 199 concepts = cr.getSuperConcepts(concept); 200 } 201 } else { 202 if (cached) { 203 concepts = cr.getCachedSubConcepts(concept); 204 } else { 205 concepts = cr.getSubConcepts(concept); 206 } 207 } 208 if (concepts != null) { 209 sentences = new ArrayList<Sentence>(); 210 LanguageUtils.sortOntologyElements(concepts); 211 for (Concept c : concepts) { 212 StatementFactory sf = getWiki().getOntology().getStatementFactory(); 213 if (up) { 214 sentences.add(sf.createHierarchySentence(concept, c)); 215 } else { 216 sentences.add(sf.createHierarchySentence(c, concept)); 217 } 218 } 219 } 220 221 updatePage(); 222 } 223 224 private void updatePage() { 225 column.removeAll(); 226 227 String t; 228 int chosenPage; 229 if (up) { 230 t = "upward"; 231 chosenPage = upChosenPage; 232 } else { 233 t = "downward"; 234 chosenPage = downChosenPage; 235 } 236 237 if (sentences == null) { 238 column.add(new SolidLabel("...", Font.ITALIC, 10)); 239 indexBar.setVisible(false); 240 } else { 241 if (sentences.size() == 0) { 242 indexBar.setVisible(false); 243 column.add(new SolidLabel("(" + t + " hierarchy is empty)", Font.ITALIC, 10)); 244 } else { 245 int i = ((sentences.size()-1) / pageSize) + 1; 246 if (chosenPage > i) chosenPage = 0; 247 indexBar.setNumbers(i); 248 indexBar.setActiveButton(chosenPage); 249 } 250 251 indexBar.setVisible(sentences.size() > pageSize); 252 253 int max = sentences.size(); 254 if (max > (chosenPage + 1) * pageSize) max = (chosenPage + 1) * pageSize; 255 for (int i = chosenPage * pageSize; i < max; i++) { 256 Row r = new Row(); 257 r.add(new SentenceComponent(sentences.get(i), HierarchyPage.this)); 258 column.add(r); 259 } 260 } 261 } 262 263 public void actionPerformed(ActionEvent e) { 264 if (e.getSource() == indexBar) { 265 if (up) { 266 upChosenPage = Integer.parseInt(e.getActionCommand()) - 1; 267 log("page", "pressed: page up:" + (upChosenPage+1)); 268 updatePage(); 269 } else { 270 downChosenPage = Integer.parseInt(e.getActionCommand()) - 1; 271 log("page", "pressed: page down:" + (downChosenPage+1)); 272 updatePage(); 273 } 274 } 275 } 276 277 } 278 279 }