/gwt/src/com/rhizospherejs/gwt/client/RhizosphereUserAgent.java

https://code.google.com/p/rhizosphere/ · Java · 611 lines · 240 code · 44 blank · 327 comment · 33 complexity · cbee6d344ff60220cb27ec87efe13065 MD5 · raw file

  1. /*
  2. Copyright 2011 The Rhizosphere Authors. All Rights Reserved.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package com.rhizospherejs.gwt.client;
  14. import com.google.gwt.core.client.JavaScriptObject;
  15. import com.google.gwt.core.client.JsArray;
  16. import com.google.gwt.core.client.JsArrayString;
  17. import com.google.gwt.json.client.JSONBoolean;
  18. import com.google.gwt.json.client.JSONNull;
  19. import com.google.gwt.json.client.JSONObject;
  20. import com.google.gwt.json.client.JSONValue;
  21. import com.rhizospherejs.gwt.client.handlers.ErrorEvent;
  22. import com.rhizospherejs.gwt.client.handlers.FilterEvent;
  23. import com.rhizospherejs.gwt.client.handlers.LayoutEvent;
  24. import com.rhizospherejs.gwt.client.handlers.ModelChangeEvent;
  25. import com.rhizospherejs.gwt.client.handlers.SelectionEvent;
  26. import com.rhizospherejs.gwt.client.handlers.UserActionEvent;
  27. import java.util.ArrayList;
  28. import java.util.Collection;
  29. import java.util.HashMap;
  30. import java.util.List;
  31. import java.util.Map;
  32. import java.util.Set;
  33. /**
  34. * The UserAgent is an high-level interface to programmatically drive a
  35. * Rhizosphere visualization like a user would do. This allows Rhizosphere
  36. * visualizations to communicate bidirectionally with any other interacting
  37. * third party existing in the same GWT application.
  38. *
  39. * @author battlehorse@google.com (Riccardo Govoni)
  40. */
  41. public class RhizosphereUserAgent<T> {
  42. private Rhizosphere<T> ownerVisualization;
  43. private JavaScriptObject nativeUserAgent;
  44. /**
  45. * Creates a new instance.
  46. * @param nativeUserAgent The native Javascript {@code rhizo.UserAgent} this
  47. * class wraps.
  48. */
  49. public RhizosphereUserAgent(JavaScriptObject nativeUserAgent) {
  50. this.nativeUserAgent = nativeUserAgent;
  51. }
  52. /**
  53. * Binds this user agent to the Rhizosphere visualization that spawned it.
  54. * @param visualization The visualization to bind to.
  55. */
  56. void bindTo(Rhizosphere<T> visualization) {
  57. ownerVisualization = visualization;
  58. this.nativeWireListeners(nativeUserAgent);
  59. }
  60. /**
  61. * @return The selection manager associated to the Rhizosphere visualization
  62. * this user agent is bound to.
  63. */
  64. final RhizosphereSelectionManager getSelectionManager() {
  65. return nativeGetSelectionManager(nativeUserAgent);
  66. }
  67. private native RhizosphereSelectionManager nativeGetSelectionManager(
  68. JavaScriptObject nativeUserAgent) /*-{
  69. return nativeUserAgent.getProject().selectionManager();
  70. }-*/;
  71. /**
  72. * Returns the rendering associated to a given model.
  73. *
  74. * @param model The model to resolve.
  75. * @return The Rhizosphere rendering bound to the specified model.
  76. */
  77. final RhizosphereRendering getRendering(RhizosphereModelRef model) {
  78. return nativeGetRendering(nativeUserAgent, model);
  79. }
  80. private native RhizosphereRendering nativeGetRendering(
  81. JavaScriptObject nativeUserAgent, RhizosphereModelRef model) /*-{
  82. return nativeUserAgent.getProject().model(model.id).rendering();
  83. }-*/;
  84. /**
  85. * Performs a programmatic selection of visualization models.
  86. * Different types of operations can be performed. See
  87. * <a href="http://code.google.com/p/rhizosphere/source/browse/src/js/rhizo.selection.js">
  88. * rhizo.seletion.js</a> for the list of supported operations.
  89. *
  90. * @param action The type of operation to perform.
  91. * @param models The collection of visualization models the operation applies
  92. * to. Not all operations use this parameter and it can be optionally
  93. * omitted at times. Refer to the documentation above for details.
  94. * Use {@code null} when unneeded.
  95. * @param cb An optional callback invoked with the outcome of the selection
  96. * operation.
  97. */
  98. void doSelection(String action,
  99. Collection<RhizosphereModelRef> models,
  100. RhizosphereCallback cb) {
  101. doSelection(action, models, true, cb);
  102. }
  103. /**
  104. * Programmatically performs a selection operation on the visualization
  105. * models. Different types of operations can be performed. See
  106. * <a href="http://code.google.com/p/rhizosphere/source/browse/src/js/rhizo.selection.js">
  107. * rhizo.seletion.js</a> for the list of supported operations.
  108. *
  109. * @param action The type of operation to perform.
  110. * @param models The collection of visualization models the operation applies
  111. * to. Not all operations use this parameter and it can be optionally
  112. * omitted at times. Refer to the documentation above for details.
  113. * Use {@code null} when unneeded.
  114. * @param incremental Whether the operation should be incremental or not.
  115. * Relevant only for 'hide' and 'focus' operations.
  116. * @param cb An optional callback invoked with the outcome of the selection
  117. * operation.
  118. */
  119. void doSelection(String action,
  120. Collection<RhizosphereModelRef> models,
  121. boolean incremental,
  122. RhizosphereCallback cb) {
  123. JsArray<RhizosphereModelRef> modelRefs = null;
  124. if (models != null && !models.isEmpty()) {
  125. modelRefs = nativeNewJsArray();
  126. for (RhizosphereModelRef modelRef : models) {
  127. modelRefs.push(modelRef);
  128. }
  129. }
  130. nativeDoSelection(nativeUserAgent, action, modelRefs, incremental, cb);
  131. }
  132. private final native void nativeDoSelection(JavaScriptObject nativeUserAgent,
  133. String action,
  134. JsArray<RhizosphereModelRef> modelRefs,
  135. boolean incremental,
  136. RhizosphereCallback cb) /*-{
  137. if (modelRefs) {
  138. for (var i = 0; i < modelRefs.length; i++) {
  139. modelRefs[i] = modelRefs[i].id;
  140. }
  141. }
  142. nativeUserAgent.doSelection(action, modelRefs, incremental, function(status, details) {
  143. if (cb) {
  144. cb.@com.rhizospherejs.gwt.client.RhizosphereCallback::run(ZLjava/lang/String;)(status, details);
  145. }
  146. });
  147. }-*/;
  148. /**
  149. * Programmatically applies a faceted filter on visualization models on the
  150. * given model attribute.
  151. * @param key The name of the Rhizosphere model attribute, as defined by
  152. * {@link RhizosphereModelAttribute#name()}, the filter applies to.
  153. * @param value The filtering criteria. The specific format of the filtering
  154. * criteria depends on the attribute kind. For example, attributes with
  155. * the RANGE kind expect the criteria to be a JSONObject with two numeric
  156. * {@code min} and {@code max} entries. Use a {@code null} to remove any
  157. * pre-existing filter on the attribute.
  158. * @param cb An optional callback invoked with the outcome of the filter
  159. * operation.
  160. */
  161. void doFilter(String key, JSONValue value, RhizosphereCallback cb) {
  162. if (value == null) {
  163. value = JSONNull.getInstance();
  164. }
  165. JSONObject filterObj = new JSONObject();
  166. filterObj.put(key, value);
  167. doFilter(filterObj, cb);
  168. }
  169. /**
  170. * Programmatically applies one or more faceted filters on visualization
  171. * models.
  172. *
  173. * @param filters The set of filters to apply. Each key should be a valid
  174. * Rhizosphere model attribute name, as defined by
  175. * {@link RhizosphereModelAttribute#name()}, for a filter to apply to.
  176. * Each value should represent the filtering criteria. The specific
  177. * format of the filtering criteria depends on the attribute kind.
  178. * For example, attributes with the RANGE kind expect the criteria to be
  179. * a JSONObject with two numeric {@code min} and {@code max} entries.
  180. * Use a {@code null} to remove any pre-existing filter on the attribute.
  181. * @param cb An optional callback invoked with the outcome of the filter
  182. * operation.
  183. */
  184. void doFilter(Map<String, JSONValue> filters, RhizosphereCallback cb) {
  185. JSONObject filterObj = new JSONObject();
  186. for (Map.Entry<String, JSONValue> filter: filters.entrySet()) {
  187. filterObj.put(filter.getKey(), filter.getValue());
  188. }
  189. doFilter(filterObj, cb);
  190. }
  191. /**
  192. * As {@link #doFilter(Map, RhizosphereCallback)}, with the filters defined
  193. * as a JSONObject instead of a Map.
  194. * @param filterObj The set of filters to apply.
  195. * @param cb An optional callback invoked with the outcome of the filter
  196. * operation.
  197. */
  198. void doFilter(JSONObject filterObj, RhizosphereCallback cb) {
  199. nativeDoFilter(nativeUserAgent, filterObj.getJavaScriptObject(), cb);
  200. }
  201. private final native void nativeDoFilter(JavaScriptObject nativeUserAgent,
  202. JavaScriptObject filterObj,
  203. RhizosphereCallback cb) /*-{
  204. nativeUserAgent.doFilter(filterObj, function(status, details) {
  205. if (cb) {
  206. cb.@com.rhizospherejs.gwt.client.RhizosphereCallback::run(ZLjava/lang/String;)(status, details);
  207. }
  208. });
  209. }-*/;
  210. /**
  211. * Programmatically resets all the filters currently applied to visualization
  212. * models.
  213. * @param cb An optional callback invoked with the outcome of the filter
  214. * operation.
  215. */
  216. void doResetFilters(RhizosphereCallback cb) {
  217. nativeDoResetFilters(nativeUserAgent, cb);
  218. }
  219. private final native void nativeDoResetFilters(JavaScriptObject nativeUserAgent,
  220. RhizosphereCallback cb) /*-{
  221. nativeUserAgent.doResetFilters(function(status, details) {
  222. if (cb) {
  223. cb.@com.rhizospherejs.gwt.client.RhizosphereCallback::run(ZLjava/lang/String;)(status, details);
  224. }
  225. });
  226. }-*/;
  227. /**
  228. * Programmatically changes the layout algorithm to visually arrange
  229. * visualization models.
  230. *
  231. * @param engine The layout engine to use. Must be one the valid engine
  232. * names as defined in <a href="http://code.google.com/p/rhizosphere/source/browse/src/js/rhizo.layout.js">
  233. * rhizo.layout.js</a> in the {@code rhizo.layout.layouts} structure.
  234. * Use {@code null} to re-use the current layout engine.
  235. * @param state The layout state to use. The state is the set of
  236. * configuration options that each layout engine accepts to customize its
  237. * behavior. The state definition is layout-specific. Use {@code null}
  238. * to let the layout use its last (or default) state.
  239. * @param positions An optional collection of explicit positioning
  240. * information for visualization models, that will override any position
  241. * the layout engine would otherwise define. Leave {@code null} if
  242. * unneeded.
  243. * @param flags An optional set of configuration flags to tweak the layout
  244. * operation.
  245. * @param cb An optional callback invoked with the outcome of the layout
  246. * operation.
  247. */
  248. void doLayout(String engine,
  249. JSONObject state,
  250. Collection<RhizosphereModelPosition> positions,
  251. Set<RhizosphereLayoutFlags> flags,
  252. RhizosphereCallback cb) {
  253. JsArray<RhizosphereModelPosition> modelPositions = null;
  254. if (positions != null && !positions.isEmpty()) {
  255. modelPositions = nativeNewJsArray();
  256. for(RhizosphereModelPosition p : positions) {
  257. modelPositions.push(p);
  258. }
  259. }
  260. JSONObject options = new JSONObject();
  261. if (flags != null && !flags.isEmpty()) {
  262. for (RhizosphereLayoutFlags flag: flags) {
  263. options.put(flag.name().toLowerCase(), JSONBoolean.getInstance(true));
  264. }
  265. }
  266. nativeDoLayout(nativeUserAgent,
  267. engine,
  268. state != null ? state.getJavaScriptObject() : null,
  269. modelPositions,
  270. options.getJavaScriptObject(),
  271. cb);
  272. }
  273. private native void nativeDoLayout(JavaScriptObject nativeUserAgent,
  274. String engine,
  275. JavaScriptObject state,
  276. JsArray<RhizosphereModelPosition> positions,
  277. JavaScriptObject options,
  278. RhizosphereCallback cb) /*-{
  279. nativeUserAgent.doLayout(engine, state, positions, options, function(status, details) {
  280. if (cb) {
  281. cb.@com.rhizospherejs.gwt.client.RhizosphereCallback::run(ZLjava/lang/String;)(status, details);
  282. }
  283. });
  284. }-*/;
  285. /**
  286. * Forces an out-of-band layout operation for the current layout engine and
  287. * state, which won't be published on the 'layout' channel. This is useful
  288. * when a layout is not directly requested by the user, but still necessary
  289. * as a consequence of other operations (such as UI resizing).
  290. */
  291. void forceLayout() {
  292. nativeForceLayout(nativeUserAgent);
  293. }
  294. private native void nativeForceLayout(JavaScriptObject nativeUserAgent) /*-{
  295. nativeUserAgent.getProject().layoutManager().forceLayout();
  296. }-*/;
  297. /**
  298. * Programmatically adds one model to the visualization.
  299. *
  300. * @param modelRef The model to add to the visualization. It must not be
  301. * already part of it.
  302. * @param cb An optional callback invoked with the outcome of the model
  303. * addition operation.
  304. */
  305. void addModel(RhizosphereModelRef modelRef, RhizosphereCallback cb) {
  306. JsArray<RhizosphereModelRef> modelRefs = nativeNewJsArray();
  307. if (modelRef != null) {
  308. modelRefs.push(modelRef);
  309. }
  310. nativeAddModels(nativeUserAgent, modelRefs, cb);
  311. }
  312. /**
  313. * Programmatically adds one or more models to the visualization.
  314. *
  315. * @param models The collection of visualization models to add to the
  316. * visualization. The models must not be already part of it.
  317. * @param cb An optional callback invoked with the outcome of the model
  318. * addition operation.
  319. */
  320. void addModels(Collection<RhizosphereModelRef> models, RhizosphereCallback cb) {
  321. JsArray<RhizosphereModelRef> modelRefs = null;
  322. if (models != null && !models.isEmpty()) {
  323. modelRefs = nativeNewJsArray();
  324. for (RhizosphereModelRef modelRef : models) {
  325. modelRefs.push(modelRef);
  326. }
  327. }
  328. nativeAddModels(nativeUserAgent, modelRefs, cb);
  329. }
  330. private native void nativeAddModels(JavaScriptObject nativeUserAgent,
  331. JsArray<RhizosphereModelRef> modelRefs,
  332. RhizosphereCallback cb) /*-{
  333. nativeUserAgent.addModels(modelRefs, function(status, details) {
  334. if (cb) {
  335. cb.@com.rhizospherejs.gwt.client.RhizosphereCallback::run(ZLjava/lang/String;)(status, details);
  336. }
  337. });
  338. }-*/;
  339. /**
  340. * Programmatically removes one model from the visualization.
  341. *
  342. * @param modelRef The model to remove.
  343. * @param cb An optional callback invoked with the outcome of the model
  344. * removal operation.
  345. */
  346. void removeModel(RhizosphereModelRef modelRef, RhizosphereCallback cb) {
  347. JsArray<RhizosphereModelRef> modelRefs = nativeNewJsArray();
  348. if (modelRef != null) {
  349. modelRefs.push(modelRef);
  350. }
  351. nativeRemoveModels(nativeUserAgent, modelRefs, cb);
  352. }
  353. /**
  354. * Programmatically removes one or more models from the visualization.
  355. *
  356. * @param models The collection of visualization models to remove from the
  357. * visualization.
  358. * @param cb An optional callback invoked with the outcome of the model
  359. * removal operation.
  360. */
  361. void removeModels(Collection<RhizosphereModelRef> models, RhizosphereCallback cb) {
  362. JsArray<RhizosphereModelRef> modelRefs = null;
  363. if (models != null && !models.isEmpty()) {
  364. modelRefs = nativeNewJsArray();
  365. for (RhizosphereModelRef modelRef : models) {
  366. modelRefs.push(modelRef);
  367. }
  368. }
  369. nativeRemoveModels(nativeUserAgent, modelRefs, cb);
  370. }
  371. private native void nativeRemoveModels(JavaScriptObject nativeUserAgent,
  372. JsArray<RhizosphereModelRef> modelRefs,
  373. RhizosphereCallback cb) /*-{
  374. nativeUserAgent.removeModels(modelRefs, function(status, details) {
  375. if (cb) {
  376. cb.@com.rhizospherejs.gwt.client.RhizosphereCallback::run(ZLjava/lang/String;)(status, details);
  377. }
  378. });
  379. }-*/;
  380. /**
  381. * Adds an error notification to the visualization. The notification will
  382. * not be displayed unless
  383. * {@link RhizosphereOptions#setShowErrorsInViewport(boolean)} is set to
  384. * {@code true}.
  385. *
  386. * @param errorDetails The contents of the error notification.
  387. * @param cb An optional callback invoked with the outcome of the error
  388. * addition operation.
  389. */
  390. void addError(String errorDetails, RhizosphereCallback cb) {
  391. nativeAddError(nativeUserAgent, errorDetails, cb);
  392. }
  393. private native void nativeAddError(JavaScriptObject nativeUserAgent,
  394. String errorDetails,
  395. RhizosphereCallback cb) /*-{
  396. nativeUserAgent.addError([errorDetails], function(status, details) {
  397. if (cb) {
  398. cb.@com.rhizospherejs.gwt.client.RhizosphereCallback::run(ZLjava/lang/String;)(status, details);
  399. }
  400. });
  401. }-*/;
  402. /**
  403. * Remove all error notifications currently showing in the visualization.
  404. * @param cb An optional callback invoked with the outcome of the error
  405. * removal operation.
  406. */
  407. void clearErrors(RhizosphereCallback cb) {
  408. nativeClearErrors(nativeUserAgent, cb);
  409. }
  410. private native void nativeClearErrors(JavaScriptObject nativeUserAgent,
  411. RhizosphereCallback cb) /*-{
  412. nativeUserAgent.clearErrors(function(status, details) {
  413. if (cb) {
  414. cb.@com.rhizospherejs.gwt.client.RhizosphereCallback::run(ZLjava/lang/String;)(status, details);
  415. }
  416. });
  417. }-*/;
  418. /**
  419. * Registers native listeners on all event types and binds them to callbacks
  420. * in java space.
  421. */
  422. private native void nativeWireListeners(JavaScriptObject nativeUserAgent) /*-{
  423. nativeUserAgent.addFilterListener(function(message) {
  424. this.@com.rhizospherejs.gwt.client.RhizosphereUserAgent::onFilter(Lcom/google/gwt/core/client/JavaScriptObject;)(message);
  425. }, this);
  426. nativeUserAgent.addSelectionListener(function(message) {
  427. var action = message['action'] || null;
  428. var incremental = typeof(message['incremental']) == 'boolean' ? message['incremental'] : true;
  429. var models = message['models'] || [];
  430. for (var i = 0; i < models.length; i++) {
  431. models[i] = nativeUserAgent.getProject().model(models[i]).unwrap();
  432. }
  433. this.@com.rhizospherejs.gwt.client.RhizosphereUserAgent::onSelection(Ljava/lang/String;Lcom/google/gwt/core/client/JsArray;Z)(action, models, incremental);
  434. }, this);
  435. nativeUserAgent.addLayoutListener(function(message) {
  436. var engine = message['engine'] || null;
  437. var state = message['state'] || {};
  438. var positions = message['positions'] || [];
  439. for (var i = 0; i < positions.length; i++) {
  440. positions[i]['ref'] = nativeUserAgent.getProject().model(positions[i].id).unwrap();
  441. }
  442. this.@com.rhizospherejs.gwt.client.RhizosphereUserAgent::onLayout(Ljava/lang/String;Lcom/google/gwt/core/client/JavaScriptObject;Lcom/google/gwt/core/client/JsArray;)(engine, state, positions);
  443. }, this);
  444. nativeUserAgent.addModelListener(function(message) {
  445. var action = message['action'] || null;
  446. var models = message['models'];
  447. for (var i = 0; i < models.length; i++) {
  448. models[i] = models[i].unwrap();
  449. }
  450. this.@com.rhizospherejs.gwt.client.RhizosphereUserAgent::onModelChange(Ljava/lang/String;Lcom/google/gwt/core/client/JsArray;)(action, models);
  451. }, this);
  452. nativeUserAgent.addErrorListener(function(message) {
  453. if (!!message['clear']) {
  454. this.@com.rhizospherejs.gwt.client.RhizosphereUserAgent::onErrorsClear()();
  455. } else {
  456. var args = message['arguments'] || [];
  457. var errorDetails = [];
  458. for (var i = 0; i < args.length; i++) {
  459. errorDetails.push(String(args[i]));
  460. }
  461. var errorMsg = errorDetails.join(' ');
  462. this.@com.rhizospherejs.gwt.client.RhizosphereUserAgent::onErrorAdd(Ljava/lang/String;)(errorMsg);
  463. }
  464. }, this);
  465. nativeUserAgent.addUserActionListener(function(message) {
  466. var action = message['action'];
  467. var detailKeys = [];
  468. var detailValues = [];
  469. var affectedModels = [];
  470. for (var key in message) {
  471. if (key == 'affectedModels') {
  472. for (var i = 0; i < message[key].length; i++) {
  473. affectedModels.push(nativeUserAgent.getProject().model(message[key][i]).unwrap());
  474. }
  475. } else if (key != 'action') {
  476. detailKeys.push(key);
  477. detailValues.push(String(message[key]));
  478. }
  479. }
  480. this.@com.rhizospherejs.gwt.client.RhizosphereUserAgent::onUserAction(Ljava/lang/String;Lcom/google/gwt/core/client/JsArrayString;Lcom/google/gwt/core/client/JsArrayString;Lcom/google/gwt/core/client/JsArray;)(action, detailKeys, detailValues, affectedModels);
  481. }, this);
  482. }-*/;
  483. /**
  484. * Callback invoked when the visualization filtering criteria change.
  485. * @param jso The filtering criteria that changed.
  486. */
  487. private void onFilter(JavaScriptObject jso) {
  488. FilterEvent.fire(ownerVisualization, new JSONObject(jso));
  489. }
  490. /**
  491. * Callback invoked when a selection operation occurs on the visualization.
  492. */
  493. private void onSelection(String action,
  494. JsArray<RhizosphereModelRef> jsModels,
  495. boolean incremental) {
  496. List<RhizosphereModelRef> models = new ArrayList<RhizosphereModelRef>();
  497. for (int i = 0; i < jsModels.length(); i++) {
  498. models.add(jsModels.get(i));
  499. }
  500. SelectionEvent.fire(ownerVisualization, action, models, incremental);
  501. }
  502. /**
  503. * Callback invoked when a layout operation occurs on the visualization.
  504. */
  505. private void onLayout(String engine,
  506. JavaScriptObject state,
  507. JsArray<RhizosphereModelPosition> jsPositions) {
  508. List<RhizosphereModelPosition> positions = new ArrayList<RhizosphereModelPosition>();
  509. for (int i = 0; i < jsPositions.length(); i++) {
  510. positions.add(jsPositions.get(i));
  511. }
  512. LayoutEvent.fire(ownerVisualization, engine, new JSONObject(state), positions);
  513. }
  514. /**
  515. * Callback invoked when one or more models are added or removed from the
  516. * visualization.
  517. */
  518. private void onModelChange(String action, JsArray<RhizosphereModelRef> jsModels) {
  519. List<RhizosphereModelRef> models = new ArrayList<RhizosphereModelRef>();
  520. for (int i = 0; i < jsModels.length(); i++) {
  521. models.add(jsModels.get(i));
  522. }
  523. ModelChangeEvent.fire(ownerVisualization, action, models);
  524. }
  525. /**
  526. * Callback invoked when error notifications are cleared from the
  527. * visualization.
  528. */
  529. private void onErrorsClear() {
  530. ErrorEvent.fire(ownerVisualization, true, null);
  531. }
  532. /**
  533. * Callback invoked when one error notification is added to the
  534. * visualization.
  535. */
  536. private void onErrorAdd(String errorDetails) {
  537. ErrorEvent.fire(ownerVisualization, false, errorDetails);
  538. }
  539. /**
  540. * Callback invoked when an user action occurs on the visualization.
  541. */
  542. private void onUserAction(
  543. String action,
  544. JsArrayString detailKeys,
  545. JsArrayString detailValues,
  546. JsArray<RhizosphereModelRef> affectedModels) {
  547. Map<String, String> details = new HashMap<String, String>();
  548. for (int i = 0; i < detailKeys.length(); i++) {
  549. details.put(detailKeys.get(i), detailValues.get(i));
  550. }
  551. List<RhizosphereModelRef> models = new ArrayList<RhizosphereModelRef>();
  552. for (int i = 0; i < affectedModels.length(); i++) {
  553. models.add(affectedModels.get(i));
  554. }
  555. UserActionEvent.fire(ownerVisualization, action, details, models);
  556. }
  557. private final native <T> T nativeNewJsArray() /*-{
  558. return [];
  559. }-*/;
  560. }