Exposing Fn.activate and Fn.activePresenter so they are available from exported packages
2 * HTML via Java(tm) Language Bindings
3 * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 2 of the License.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details. apidesign.org
13 * designates this particular file as subject to the
14 * "Classpath" exception as provided by apidesign.org
15 * in the License file that accompanied this code.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. Look for COPYING file in the top folder.
19 * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
21 package org.apidesign.html.kofx;
23 import java.io.Closeable;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.util.ServiceLoader;
27 import java.util.logging.Logger;
28 import javafx.application.Platform;
29 import net.java.html.js.JavaScriptBody;
30 import netscape.javascript.JSObject;
31 import org.apidesign.html.boot.spi.Fn;
32 import org.apidesign.html.context.spi.Contexts;
33 import org.apidesign.html.json.spi.FunctionBinding;
34 import org.apidesign.html.json.spi.JSONCall;
35 import org.apidesign.html.json.spi.PropertyBinding;
36 import org.apidesign.html.json.spi.Technology;
37 import org.apidesign.html.json.spi.Transfer;
38 import org.apidesign.html.json.spi.WSTransfer;
39 import org.openide.util.lookup.ServiceProvider;
41 /** This is an implementation package - just
42 * include its JAR on classpath and use official {@link Context} API
43 * to access the functionality.
45 * Registers {@link ContextProvider}, so {@link ServiceLoader} can find it.
47 * @author Jaroslav Tulach <jtulach@netbeans.org>
49 public final class FXContext
50 implements Technology.BatchInit<JSObject>, Transfer, WSTransfer<LoadWS> {
51 static final Logger LOG = Logger.getLogger(FXContext.class.getName());
52 private static Boolean javaScriptEnabled;
53 private final Fn.Presenter browserContext;
55 public FXContext(Fn.Presenter browserContext) {
56 this.browserContext = browserContext;
59 @JavaScriptBody(args = {}, body = "return true;")
60 private static boolean isJavaScriptEnabledJs() {
64 static boolean isJavaScriptEnabled() {
65 if (javaScriptEnabled != null) {
66 return javaScriptEnabled;
68 return javaScriptEnabled = isJavaScriptEnabledJs();
71 final boolean areWebSocketsSupported() {
72 return LoadWS.isSupported();
77 public JSObject wrapModel(Object model, PropertyBinding[] propArr, FunctionBinding[] funcArr) {
78 String[] propNames = new String[propArr.length];
79 boolean[] propReadOnly = new boolean[propArr.length];
80 Object[] propValues = new Object[propArr.length];
81 for (int i = 0; i < propNames.length; i++) {
82 propNames[i] = propArr[i].getPropertyName();
83 propReadOnly[i] = propArr[i].isReadOnly();
84 propValues[i] = propArr[i].getValue();
86 String[] funcNames = new String[funcArr.length];
87 for (int i = 0; i < funcNames.length; i++) {
88 funcNames[i] = funcArr[i].getFunctionName();
91 return Knockout.wrapModel(model,
92 propNames, propReadOnly, Knockout.toArray(propValues), propArr,
98 public JSObject wrapModel(Object model) {
99 throw new UnsupportedOperationException();
103 public void bind(PropertyBinding b, Object model, JSObject data) {
104 throw new UnsupportedOperationException();
108 public void valueHasMutated(JSObject data, String propertyName) {
109 Knockout.valueHasMutated(data, propertyName);
113 public void expose(FunctionBinding fb, Object model, JSObject d) {
114 throw new UnsupportedOperationException();
118 public void applyBindings(JSObject data) {
119 Knockout.applyBindings(data);
123 public Object wrapArray(Object[] arr) {
124 return Knockout.toArray(arr);
128 public void extract(Object obj, String[] props, Object[] values) {
129 LoadJSON.extractJSON(obj, props, values);
133 public void loadJSON(final JSONCall call) {
134 LoadJSON.loadJSON(call);
138 public <M> M toModel(Class<M> modelClass, Object data) {
139 if (data instanceof JSObject) {
140 data = ((JSObject)data).getMember("ko-fx.model"); // NOI18N
142 return modelClass.cast(data);
146 public Object toJSON(InputStream is) throws IOException {
147 return LoadJSON.parse(is);
151 public void runSafe(final Runnable r) {
152 class Wrap implements Runnable {
153 @Override public void run() {
154 try (Closeable c = Fn.activate(browserContext)) {
156 } catch (IOException ex) {
163 if (Platform.isFxApplicationThread()) {
166 Platform.runLater(w);
171 public LoadWS open(String url, JSONCall onReply) {
172 return new LoadWS(onReply, url);
176 public void send(LoadWS socket, JSONCall data) {
181 public void close(LoadWS socket) {
185 @ServiceProvider(service = Contexts.Provider.class)
186 public static final class Prvdr implements Contexts.Provider {
188 public void fillContext(Contexts.Builder context, Class<?> requestor) {
189 if (isJavaScriptEnabled()) {
190 FXContext c = new FXContext(Fn.activePresenter());
192 context.register(Technology.class, c, 100);
193 context.register(Transfer.class, c, 100);
194 if (c.areWebSocketsSupported()) {
195 context.register(WSTransfer.class, c, 100);