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 }