PageRenderTime 68ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/plugins/org.integratedmodelling.aries.http.explorer/src/org/integratedmodelling/aries/webapp/view/storyline/ModelStorylineView.java

https://github.com/kbagstad/aries
Java | 430 lines | 322 code | 72 blank | 36 comment | 40 complexity | 4b0dd8b3fb3f237cb4be2c2d4e00c152 MD5 | raw file
  1. package org.integratedmodelling.aries.webapp.view.storyline;
  2. import java.awt.image.BufferedImage;
  3. import java.util.ArrayList;
  4. import org.apache.commons.lang.StringUtils;
  5. import org.integratedmodelling.aries.webapp.view.AriesBrowser;
  6. import org.integratedmodelling.aries.webapp.view.STYLE;
  7. import org.integratedmodelling.aries.webapp.visualization.WebZKVisualization;
  8. import org.integratedmodelling.corescience.interfaces.IObservationContext;
  9. import org.integratedmodelling.modelling.context.Context;
  10. import org.integratedmodelling.modelling.storyline.ModelStoryline;
  11. import org.integratedmodelling.modelling.storyline.Storyline;
  12. import org.integratedmodelling.modelling.visualization.VisualizationFactory;
  13. import org.integratedmodelling.modelling.visualization.WebVisualization;
  14. import org.integratedmodelling.modelling.visualization.storyline.StorylineTemplate;
  15. import org.integratedmodelling.modelling.visualization.storyline.StorylineTemplate.Page;
  16. import org.integratedmodelling.thinklab.exception.ThinklabException;
  17. import org.integratedmodelling.thinklab.exception.ThinklabRuntimeException;
  18. import org.integratedmodelling.thinklab.interfaces.knowledge.IConcept;
  19. import org.integratedmodelling.thinklab.webapp.ZK;
  20. import org.integratedmodelling.thinklab.webapp.ZK.ZKComponent;
  21. import org.integratedmodelling.utils.Pair;
  22. import org.integratedmodelling.utils.image.ImageUtil;
  23. import org.zkoss.zk.ui.event.Event;
  24. import org.zkoss.zk.ui.event.EventListener;
  25. import org.zkoss.zk.ui.event.MouseEvent;
  26. import org.zkoss.zul.Div;
  27. /**
  28. * The view that allows data display for a computed visualization, or information display for one still to be
  29. * computed. Should have methods to interact with the storyline (e.g. to start the computation) and if the
  30. * storyline has any children (scenarios) it should allow comparison of the computed data with its own.
  31. *
  32. * @author Ferdinando
  33. *
  34. */
  35. public class ModelStorylineView extends StorylineView {
  36. private StorylineControlPanel cpanel;
  37. int patch = -1;
  38. private String[] currentPlotType;
  39. private String covUrl = null;
  40. public ModelStorylineView(Storyline s, AriesBrowser browser, StorylineControlPanel badge) {
  41. super(s, browser);
  42. this.cpanel = badge;
  43. try {
  44. render();
  45. } catch (ThinklabException e) {
  46. throw new ThinklabRuntimeException(e);
  47. }
  48. }
  49. public StorylineControlPanel getControlPanel() {
  50. return cpanel;
  51. }
  52. public void initPages() throws ThinklabException {
  53. showSequence();
  54. currentPlotType = new String[getPageSequence().size()];
  55. for (int i = 0; i < getPageSequence().size(); i++) {
  56. currentPlotType[i] =
  57. getPageSequence().get(i).getPlotType() + ".png";
  58. }
  59. }
  60. private static final long serialVersionUID = -7984552889374835100L;
  61. protected String getImage() throws ThinklabException {
  62. String ret = null;
  63. if (currentPage < 0) {
  64. if (storyline.getStatus() == ModelStoryline.COMPUTING ||
  65. storyline.getStatus() == ModelStoryline.PENDING) {
  66. ret = "/aries/images/computing.png";
  67. patch = (VIEWPORT_Y - 2 - 166)/2;
  68. } else if (storyline.getStatus() == ModelStoryline.COMPUTED) {
  69. ret = "/aries/images/computed.png";
  70. patch = (VIEWPORT_Y - 2 - 166)/2;
  71. initPages();
  72. } else if (storyline.getContext() != null){
  73. if (covUrl == null) {
  74. Pair<Integer,Integer> xy =
  75. VisualizationFactory.get().getPlotSize(vx-2, vy-2, storyline.getContext());
  76. patch = (vy - 2 - xy.getSecond())/2;
  77. Pair<String, String> zr =
  78. browser.getApplication().getNewResourceUrl(".png", browser.getSession());
  79. /*
  80. * create coverage image
  81. */
  82. BufferedImage bim = storyline.getCoverageMap(xy.getFirst(), xy.getSecond());
  83. if (bim != null) {
  84. ImageUtil.saveImage(bim, zr.getFirst());
  85. }
  86. patch = (VIEWPORT_Y - 2 - xy.getSecond())/2;
  87. covUrl = zr.getSecond();
  88. }
  89. ret = covUrl;
  90. }
  91. } else {
  92. Pair<Integer,Integer> xy =
  93. VisualizationFactory.get().getPlotSize(vx-2, vy-2, storyline.getContext());
  94. patch = (vy - 2 - xy.getSecond())/2;
  95. ret = ((WebZKVisualization)(storyline.getVisualization())).getStateUrl(
  96. getPageSequence().get(currentPage).getConcept(),
  97. currentPlotType[currentPage]);
  98. }
  99. return ret;
  100. }
  101. @Override
  102. protected boolean isPageEnabled(StorylineTemplate.Page page) {
  103. return
  104. !page.getBoolean("disabled") &&
  105. Context.getState(page.getConcept(),
  106. (IObservationContext) storyline.getContext()) != null;
  107. }
  108. @Override
  109. protected ZKComponent getRibbon(int width, int height) throws ThinklabException {
  110. ZKComponent ret = null;
  111. if (storyline.getStatus() == ModelStoryline.IDLE) {
  112. /*
  113. * TODO message, launch button
  114. */
  115. ret =
  116. ZK.vbox(
  117. ZK.spacer(28),
  118. ZK.label("Click the play button in the sidebar to start computing this storyline.")).
  119. align("center").sclass(STYLE.TEXT_LARGE_BOLD_GREY);
  120. } else if (storyline.getStatus() == ModelStoryline.COMPUTING) {
  121. /*
  122. * TODO icon, progress bar etc
  123. */
  124. ret =
  125. ZK.vbox(
  126. ZK.spacer(28),
  127. ZK.label("The storyline is being computed. Results will appear in this area.")).
  128. align("center").sclass(STYLE.TEXT_LARGE_BOLD_GREY);
  129. } else if (storyline.getStatus() == ModelStoryline.ERROR) {
  130. /*
  131. * TODO "more info" link, icons etc.
  132. */
  133. ret =
  134. ZK.vbox(
  135. ZK.spacer(28),
  136. ZK.label("The computation ended with errors.")).
  137. align("center").sclass(STYLE.TEXT_LARGE_BOLD_RED);
  138. } else if (storyline.getStatus() == ModelStoryline.DISABLED) {
  139. ret =
  140. ZK.vbox(
  141. ZK.spacer(28),
  142. ZK.label("Computation of this storyline is not possible in this region.")).
  143. align("center").sclass(STYLE.TEXT_LARGE_BOLD_GREY);
  144. } else {
  145. /*
  146. * Make the ribbon for the result dataset corresponding to the various pages.
  147. * Call the vis first or we won't get our sequence right the first time.
  148. */
  149. WebVisualization visualization =
  150. (WebZKVisualization)(storyline.getVisualization());
  151. Pair<Integer, Integer> xy =
  152. VisualizationFactory.get().getPlotSize(110, 64, storyline.getContext());
  153. ArrayList<ZKComponent> components = new ArrayList<ZK.ZKComponent>();
  154. for (int i = 0; i < getPageSequence().size(); i++) {
  155. Page p = getPageSequence().get(i);
  156. final int idx = i;
  157. String img = visualization.getStateUrl(p.getConcept(), VisualizationFactory.PLOT_GEOSURFACE_2D);
  158. if (img != null) {
  159. components.add(
  160. ZK.div(
  161. ZK.vbox(
  162. ZK.image(img).width(xy.getFirst()).height(xy.getSecond()).sclass(currentPage == i ? STYLE.BRIGHT_BORDER : null),
  163. ZK.label(StringUtils.abbreviate(p.getName(),24)).sclass(STYLE.TEXT_VERYSMALL).align("center").fillx())).
  164. align("center").
  165. width(120).
  166. tooltip(p.getRunningHead()).
  167. hand().listener("onClick", new EventListener() {
  168. @Override
  169. public void onEvent(Event arg0) throws Exception {
  170. switchPage(idx);
  171. }
  172. }).tmargin(64 - xy.getSecond()));
  173. }
  174. }
  175. ret =
  176. ZK.ribbon(
  177. width, height, 120,
  178. components.toArray(new ZKComponent[components.size()])).
  179. selected(currentPage);
  180. }
  181. return ret;
  182. }
  183. @Override
  184. protected ZKComponent getImageArea(int width, int height) throws ThinklabException {
  185. String img = getImage();
  186. if (currentPage >= 0) {
  187. String units = getPageSequence().get(currentPage).get("units");
  188. String totals = "";
  189. String statsReq = getPageSequence().get(currentPage).get("statistics");
  190. if (statsReq != null && statsReq.contains("totals")) {
  191. totals =
  192. " " +
  193. ((WebZKVisualization)(storyline.getVisualization())).getAggregatedDescription(
  194. getPageSequence().get(currentPage).getConcept(),
  195. getPageSequence().get(currentPage).get("units"));
  196. } else {
  197. totals = " click map for values";
  198. }
  199. /*
  200. * list of buttons to switch images among the allowed views.
  201. */
  202. ArrayList<ZKComponent> ibuts = new ArrayList<ZK.ZKComponent>();
  203. ibuts.add(ZK.spacer(4));
  204. ibuts.add(
  205. ZK.imagebutton("/aries/images/" + getPageSequence().get(currentPage).getPlotType() + ".png")
  206. .tooltip(VisualizationFactory.getPlotDescription(getPageSequence().get(currentPage).getPlotType() + ".png"))
  207. .listener("onClick", new EventListener() {
  208. @Override
  209. public void onEvent(Event arg0) throws Exception {
  210. // TODO Auto-generated method stub
  211. currentPlotType[currentPage] =
  212. getPageSequence().get(currentPage).
  213. getWith("plot-type", "default", "true") + ".png";
  214. render();
  215. }
  216. }));
  217. for (String s : getPageSequence().get(currentPage).getAllWithout("plot-type", "default")) {
  218. final String zing = s;
  219. ibuts.add(
  220. ZK.imagebutton("/aries/images/" + s + ".png")
  221. .tooltip(VisualizationFactory.getPlotDescription(s + ".png"))
  222. .listener("onClick", new EventListener() {
  223. @Override
  224. public void onEvent(Event arg0) throws Exception {
  225. // TODO Auto-generated method stub
  226. currentPlotType[currentPage] = zing + ".png";
  227. render();
  228. }
  229. }));
  230. }
  231. return
  232. ZK.div(
  233. ZK.vbox(
  234. ZK.div(
  235. ZK.hbox(
  236. ZK.div(
  237. ZK.vbox(
  238. ZK.spacer(8),
  239. ZK.hbox(
  240. ibuts.toArray(new ZKComponent[ibuts.size()])
  241. ).spacing(4))).align("left"),
  242. ZK.spacer(6),
  243. ZK.vbox(
  244. ZK.spacer(8),
  245. ZK.label(VisualizationFactory.getPlotDescription(currentPlotType[currentPage]) +
  246. " :: " +
  247. totals)
  248. ),
  249. ZK.div(
  250. ZK.vbox(
  251. ZK.spacer(8),
  252. ZK.hbox(
  253. ZK.imagebutton("/images/icons/camera_go.png").
  254. listener("onClick", new EventListener() {
  255. @Override
  256. public void onEvent(Event arg0) throws Exception {
  257. //exportImages();
  258. }
  259. }).
  260. tooltip("Export the selected layer as a PNG image"),
  261. ZK.imagebutton("/images/icons/folder_go.png").
  262. listener("onClick", new EventListener() {
  263. @Override
  264. public void onEvent(Event arg0) throws Exception {
  265. // exportGIS();
  266. }
  267. }).
  268. tooltip("Export the selected layer as a GeoTIFF file, suitable for GIS applications."),
  269. ZK.imagebutton("/images/icons/google-earth.png").
  270. listener("onClick", new EventListener() {
  271. @Override
  272. public void onEvent(Event arg0) throws Exception {
  273. // exportKML();
  274. }
  275. }).
  276. tooltip("View the selected layer in Google Earth"),
  277. ZK.spacer(4)
  278. ).spacing(4))).align("right")
  279. ).fillx()
  280. ).sclass(STYLE.GLASSTOP_SMALL).width(vx).height(TOPBAR_H),
  281. ZK.div(
  282. ZK.vbox(
  283. ZK.separator().height(patch),
  284. ZK.image(img).
  285. listener("onClick", new EventListener() {
  286. @Override
  287. public void onEvent(Event arg0) throws Exception {
  288. int x = ((MouseEvent)arg0).getX();
  289. int y = ((MouseEvent)arg0).getY();
  290. showDataAt(getPageSequence().get(currentPage).getConcept(), x, y);
  291. }
  292. }))).
  293. align("center").
  294. sclass(STYLE.TEXTURED).
  295. width(width).
  296. height(height - BOTBAR_H - TOPBAR_H),
  297. ZK.div(
  298. ZK.hbox(
  299. ZK.div(
  300. ZK.vbox(
  301. ZK.spacer(20),
  302. ZK.hbox(
  303. ZK.spacer(16),
  304. ((WebZKVisualization)(storyline.getVisualization())).
  305. getLegend(getPageSequence().get(currentPage).getConcept(), units, currentPlotType[currentPage])
  306. ))).align("left"),
  307. ZK.div().align("right").id("datawin")
  308. ).fillx()
  309. ).sclass(STYLE.GLASSBOTTOM_LARGE).width(vx).height(BOTBAR_H)).spacing(0)).
  310. width(width).
  311. height(height).
  312. sclass(STYLE.BORDERED_SUNK);
  313. }
  314. /*
  315. * TODO
  316. * no map to show
  317. */
  318. return
  319. ZK.div(
  320. ZK.vbox(
  321. ZK.separator().height(patch),
  322. ZK.image(getImage()))).
  323. align("center").
  324. sclass(STYLE.TEXTURED_SUNK).
  325. width(width).
  326. height(height);
  327. }
  328. private void showDataAt(IConcept concept, int imgX, int imgY) throws ThinklabException {
  329. Div div = (Div) ZK.getComponentById(this, "datawin");
  330. ZKComponent content =
  331. ZK.vbox(
  332. ZK.hbox(
  333. ((WebZKVisualization)(storyline.getVisualization())).
  334. getStateDescriptionAt(
  335. concept, imgX, imgY,
  336. getPageSequence().get(currentPage).get("units")),
  337. ZK.bar(),
  338. ZK.vbox(
  339. ZK.spacer(12),
  340. ((WebZKVisualization)(storyline.getVisualization())).
  341. getLatLonDescriptionAt(imgX, imgY)
  342. ),
  343. ZK.spacer(12)
  344. )
  345. );
  346. ZK.resetComponent(div);
  347. div.appendChild(content.get());
  348. }
  349. public void initialize(Storyline sl, AriesBrowser browser, StorylineControlPanel badge) {
  350. initialize(sl, browser);
  351. this.cpanel = badge;
  352. try {
  353. render();
  354. } catch (ThinklabException e) {
  355. throw new ThinklabRuntimeException(e);
  356. }
  357. }
  358. }