Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

JavaScriptRendererConnector.java 9.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. /*
  2. * Copyright 2000-2014 Vaadin Ltd.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.vaadin.client.connectors;
  17. import java.util.ArrayList;
  18. import java.util.Collection;
  19. import com.google.gwt.core.client.JavaScriptObject;
  20. import com.google.gwt.core.client.JsArrayString;
  21. import com.google.gwt.dom.client.NativeEvent;
  22. import com.vaadin.client.BrowserInfo;
  23. import com.vaadin.client.JavaScriptConnectorHelper;
  24. import com.vaadin.client.Util;
  25. import com.vaadin.client.communication.HasJavaScriptConnectorHelper;
  26. import com.vaadin.client.renderers.ComplexRenderer;
  27. import com.vaadin.client.renderers.Renderer;
  28. import com.vaadin.client.widget.grid.CellReference;
  29. import com.vaadin.client.widget.grid.RendererCellReference;
  30. import com.vaadin.shared.JavaScriptExtensionState;
  31. import com.vaadin.shared.ui.Connect;
  32. import com.vaadin.ui.renderers.AbstractJavaScriptRenderer;
  33. import elemental.json.JsonObject;
  34. import elemental.json.JsonValue;
  35. /**
  36. * Connector for server-side renderer implemented using JavaScript.
  37. *
  38. * @since 7.4
  39. * @author Vaadin Ltd
  40. */
  41. // This is really typed to <JsonValue>, but because of the way native strings
  42. // are not always instanceof JsonValue, we need to accept Object
  43. @Connect(AbstractJavaScriptRenderer.class)
  44. public class JavaScriptRendererConnector
  45. extends AbstractRendererConnector<Object>
  46. implements HasJavaScriptConnectorHelper {
  47. private final JavaScriptConnectorHelper helper = new JavaScriptConnectorHelper(
  48. this);
  49. private final JavaScriptObject cellReferenceWrapper = createCellReferenceWrapper(
  50. BrowserInfo.get().isIE8());
  51. @Override
  52. protected void init() {
  53. super.init();
  54. helper.init();
  55. addGetRowKey(helper.getConnectorWrapper());
  56. }
  57. private static native JavaScriptObject createCellReferenceWrapper(
  58. boolean isIE8)
  59. /*-{
  60. var reference = {};
  61. if (isIE8) {
  62. // IE8 only supports defineProperty for DOM objects
  63. reference = $doc.createElement('div');
  64. }
  65. var setProperty = function(name, getter, setter) {
  66. var descriptor = {
  67. get: getter
  68. }
  69. if (setter) {
  70. descriptor.set = setter;
  71. }
  72. Object.defineProperty(reference, name, descriptor);
  73. };
  74. setProperty("element", function() {
  75. return reference.target.@CellReference::getElement()();
  76. }, null);
  77. setProperty("rowIndex", function() {
  78. return reference.target.@CellReference::getRowIndex()();
  79. }, null);
  80. setProperty("columnIndex", function() {
  81. return reference.target.@CellReference::getColumnIndex()();
  82. }, null);
  83. setProperty("colSpan", function() {
  84. return reference.target.@RendererCellReference::getColSpan()();
  85. }, function(colSpan) {
  86. reference.target.@RendererCellReference::setColSpan(*)(colSpan);
  87. });
  88. return reference;
  89. }-*/;
  90. @Override
  91. public JavaScriptExtensionState getState() {
  92. return (JavaScriptExtensionState) super.getState();
  93. }
  94. private native void addGetRowKey(JavaScriptObject wrapper)
  95. /*-{
  96. var self = this;
  97. wrapper.getRowKey = $entry(function(rowIndex) {
  98. return @JavaScriptRendererConnector::findRowKey(*)(self, rowIndex);
  99. });
  100. }-*/;
  101. private static String findRowKey(JavaScriptRendererConnector connector,
  102. int rowIndex) {
  103. GridConnector gc = (GridConnector) connector.getParent();
  104. JsonObject row = gc.getWidget().getDataSource().getRow(rowIndex);
  105. return connector.getRowKey(row);
  106. }
  107. private boolean hasFunction(String name) {
  108. return hasFunction(helper.getConnectorWrapper(), name);
  109. }
  110. private static native boolean hasFunction(JavaScriptObject wrapper,
  111. String name)
  112. /*-{
  113. return typeof wrapper[name] === 'function';
  114. }-*/;
  115. @Override
  116. protected Renderer<Object> createRenderer() {
  117. helper.ensureJavascriptInited();
  118. if (!hasFunction("render")) {
  119. throw new RuntimeException(
  120. "JavaScriptRenderer " + helper.getInitFunctionName()
  121. + " must have a function named 'render'");
  122. }
  123. final boolean hasInit = hasFunction("init");
  124. final boolean hasDestroy = hasFunction("destroy");
  125. final boolean hasOnActivate = hasFunction("onActivate");
  126. final boolean hasGetConsumedEvents = hasFunction("getConsumedEvents");
  127. final boolean hasOnBrowserEvent = hasFunction("onBrowserEvent");
  128. return new ComplexRenderer<Object>() {
  129. @Override
  130. public void render(RendererCellReference cell, Object data) {
  131. if (data instanceof JsonValue) {
  132. data = Util.json2jso((JsonValue) data);
  133. }
  134. render(helper.getConnectorWrapper(), getJsCell(cell), data);
  135. }
  136. private JavaScriptObject getJsCell(CellReference<?> cell) {
  137. updateCellReference(cellReferenceWrapper, cell);
  138. return cellReferenceWrapper;
  139. }
  140. public native void render(JavaScriptObject wrapper,
  141. JavaScriptObject cell, Object data)
  142. /*-{
  143. wrapper.render(cell, data);
  144. }-*/;
  145. @Override
  146. public void init(RendererCellReference cell) {
  147. if (hasInit) {
  148. init(helper.getConnectorWrapper(), getJsCell(cell));
  149. }
  150. }
  151. private native void init(JavaScriptObject wrapper,
  152. JavaScriptObject cell)
  153. /*-{
  154. wrapper.init(cell);
  155. }-*/;
  156. private native void updateCellReference(
  157. JavaScriptObject cellWrapper, CellReference<?> target)
  158. /*-{
  159. cellWrapper.target = target;
  160. }-*/;
  161. @Override
  162. public void destroy(RendererCellReference cell) {
  163. if (hasDestroy) {
  164. destory(helper.getConnectorWrapper(), getJsCell(cell));
  165. } else {
  166. super.destroy(cell);
  167. }
  168. }
  169. private native void destory(JavaScriptObject wrapper,
  170. JavaScriptObject cell)
  171. /*-{
  172. wrapper.destory(cell);
  173. }-*/;
  174. @Override
  175. public boolean onActivate(CellReference<?> cell) {
  176. if (hasOnActivate) {
  177. return onActivate(helper.getConnectorWrapper(),
  178. getJsCell(cell));
  179. } else {
  180. return super.onActivate(cell);
  181. }
  182. }
  183. private native boolean onActivate(JavaScriptObject wrapper,
  184. JavaScriptObject cell)
  185. /*-{
  186. return !!wrapper.onActivate(cell);
  187. }-*/;
  188. @Override
  189. public Collection<String> getConsumedEvents() {
  190. if (hasGetConsumedEvents) {
  191. JsArrayString events = getConsumedEvents(
  192. helper.getConnectorWrapper());
  193. ArrayList<String> list = new ArrayList<String>(
  194. events.length());
  195. for (int i = 0; i < events.length(); i++) {
  196. list.add(events.get(i));
  197. }
  198. return list;
  199. } else {
  200. return super.getConsumedEvents();
  201. }
  202. }
  203. private native JsArrayString getConsumedEvents(
  204. JavaScriptObject wrapper)
  205. /*-{
  206. var rawEvents = wrapper.getConsumedEvents();
  207. var events = [];
  208. for(var i = 0; i < rawEvents.length; i++) {
  209. events[i] = ""+rawEvents[i];
  210. }
  211. return events;
  212. }-*/;
  213. @Override
  214. public boolean onBrowserEvent(CellReference<?> cell,
  215. NativeEvent event) {
  216. if (hasOnBrowserEvent) {
  217. return onBrowserEvent(helper.getConnectorWrapper(),
  218. getJsCell(cell), event);
  219. } else {
  220. return super.onBrowserEvent(cell, event);
  221. }
  222. }
  223. private native boolean onBrowserEvent(JavaScriptObject wrapper,
  224. JavaScriptObject cell, NativeEvent event)
  225. /*-{
  226. return !!wrapper.onBrowserEvent(cell, event);
  227. }-*/;
  228. };
  229. }
  230. @Override
  231. public Object decode(JsonValue value) {
  232. // Let the js logic decode the raw json that the server sent
  233. return value;
  234. }
  235. @Override
  236. public void onUnregister() {
  237. super.onUnregister();
  238. helper.onUnregister();
  239. }
  240. @Override
  241. public JavaScriptConnectorHelper getJavascriptConnectorHelper() {
  242. return helper;
  243. }
  244. }