package org.geogebra.web.html5.util; import java.util.HashMap; import org.geogebra.common.GeoGebraConstants; import org.geogebra.common.gui.view.consprotocol.ConstructionProtocolNavigation; import org.geogebra.common.move.ggtapi.models.AjaxCallback; import org.geogebra.common.util.debug.Log; import org.geogebra.web.html5.gui.tooltip.ToolTipManagerW; import org.geogebra.web.html5.main.AppW; import org.geogebra.web.html5.main.GgbAPIW; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.NodeList; public class ViewW { private HashMap<String, String> archiveContent; private Element container; private AppW app; /** Loads file into active GeoGebraFrame */ public static final LoadFilePresenter fileLoader = new LoadFilePresenter(); public ViewW(Element container, AppW app) { this.app = app; this.container = container; } public static String checkLAF() { NodeList<Element> nodes = Dom .getElementsByClassName(GeoGebraConstants.GGM_CLASS_NAME); for (int i = 0; i < nodes.getLength(); i++) { if ("modern" .equals(nodes.getItem(i).getAttribute("data-param-laf"))) { return "modern"; } if ("smart".equals(nodes.getItem(i).getAttribute("data-param-laf"))) { return "smart"; } } return "standard"; } public Element getContainer() { return container; } public void promptUserForGgbFile() { Log.debug("No data-param-fi7/7leName attribute presented"); } public void showError(String errorMessage) { Log.debug(errorMessage); } public void hide() { Log.debug("View.hide called"); } public String getDataParamFileName() { return ((ArticleElement) container).getDataParamFileName(); } public String getDataParamJSON() { return ((ArticleElement) container).getDataParamJSON(); } public String getDataParamBase64String() { return ((ArticleElement) container).getDataParamBase64String(); } public String getDataParamLanguage() { return ((ArticleElement) container).getDataParamLanguage(); } public String getDataParamCountry() { return ((ArticleElement) container).getDataParamCountry(); } public boolean getDataParamUseBrowserForJS() { return ((ArticleElement) container).getDataParamUseBrowserForJS(); } public boolean getDataParamEnableLabelDrags() { return ((ArticleElement) container).getDataParamEnableLabelDrags(); } public boolean getDataParamEnableUndoRedo() { return ((ArticleElement) container).getDataParamEnableUndoRedo(); } public boolean getDataParamEnableRightClick() { return ((ArticleElement) container).getDataParamEnableRightClick(); } public boolean getDataParamShowMenuBar(boolean def) { return ((ArticleElement) container).getDataParamShowMenuBar(def); } public boolean getDataParamShowAlgebraInput(boolean def) { return ((ArticleElement) container).getDataParamShowAlgebraInput(def); } public boolean getDataParamShowToolBar(boolean def) { return ((ArticleElement) container).getDataParamShowToolBar(def); } public boolean getDataParamShowToolBarHelp() { // return ((ArticleElement) container).getDataParamShowToolBarHelp(); return false; } public boolean getDataParamShiftDragZoomEnabled() { return ((ArticleElement) container).getDataParamShiftDragZoomEnabled(); } public boolean getDataParamShowResetIcon() { return ((ArticleElement) container).getDataParamShowResetIcon(); } public boolean getDataParamShowAnimationButton() { return ((ArticleElement) container).getDataParamShowAnimationButton(); } public int getDataParamCapturingThreshold() { return ((ArticleElement) container).getDataParamCapturingThreshold(); } public boolean getDataParamAllowSymbolTable() { return ((ArticleElement) container).getDataParamAllowSymbolTable(); } public boolean getDataParamErrorDialogsActive() { return ((ArticleElement) container).getDataParamErrorDialogsActive(); } public String getDataParamPerspective() { return ((ArticleElement) container).getDataParamPerspective(); } public boolean getDataParamAllowStyleBar() { return ((ArticleElement) container).getDataParamAllowStyleBar(); } public ArticleElement getArticleElement() { return ((ArticleElement) container); } private native void log(Object ex)/*-{ if ($wnd.console) { $wnd.console.log(ex); } }-*/; private void maybeLoadFile() { if (app == null || archiveContent == null) { return; } try { app.loadGgbFile(archiveContent); Log.debug("loadggb finished" + System.currentTimeMillis()); } catch (Throwable ex) { ex.printStackTrace(); log(ex); return; } archiveContent = null; // app.getScriptManager().ggbOnInit(); //this line is moved from here // too, // it should load after the images are loaded Log.debug("file loaded"); // This is used also by touch where dialog manager is null app.notifyFileLoaded(); // reiniting of navigation bar, to show the correct numbers on the label if (app.getGuiManager() != null && app.getUseFullGui()) { ConstructionProtocolNavigation cpNav = this.getApplication() .getGuiManager() .getConstructionProtocolNavigationIfExists(); if (cpNav != null) { cpNav.update(); } } Log.debug("end unzipping" + System.currentTimeMillis()); } public void maybeLoadFile(HashMap<String, String> archiveCont) { archiveContent = archiveCont; maybeLoadFile(); } public AppW getApplication() { return app; } public void processBase64String(String dataParamBase64String) { populateArchiveContent(getBase64Reader(dataParamBase64String)); } private int zippedLength = 0; private void putIntoArchiveContent(String key, String value) { archiveContent.put(key, value); if (archiveContent.size() == zippedLength) { maybeLoadFile(); } } private void populateArchiveContent(JavaScriptObject ggbReader) { String workerUrls = prepareFileReading(); GgbAPIW.setWorkerURL(workerUrls, false); populateArchiveContent(workerUrls, this, ggbReader); } private native void populateArchiveContent(String workerUrls, ViewW view, JavaScriptObject ggbReader) /*-{ // Writer for ASCII strings function ASCIIWriter() { var that = this, data; function init(callback, onerror) { data = ""; callback(); } function writeUint8Array(array, callback, onerror) { var i; for (i = 0; i < array.length; i++) { data += $wnd.String.fromCharCode(array[i]); } callback(); } function getData(callback) { callback(data); } that.init = init; that.writeUint8Array = writeUint8Array; that.getData = getData; } ASCIIWriter.prototype = new $wnd.zip.Writer(); ASCIIWriter.prototype.constructor = ASCIIWriter; function decodeUTF8(str_data) { var tmp_arr = [], i = 0, ac = 0, c1 = 0, c2 = 0, c3 = 0; str_data += ''; while (i < str_data.length) { c1 = str_data.charCodeAt(i); if (c1 < 128) { tmp_arr[ac++] = String.fromCharCode(c1); i++; } else if (c1 > 191 && c1 < 224) { c2 = str_data.charCodeAt(i + 1); tmp_arr[ac++] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63)); i += 2; } else { c2 = str_data.charCodeAt(i + 1); c3 = str_data.charCodeAt(i + 2); tmp_arr[ac++] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); i += 3; } } return tmp_arr.join(''); } // see GGB-63 var imageRegex = /\.(png|jpg|jpeg|gif|bmp|tif|tiff)$/i; var readerCallback = function(reader) { reader.getEntries(function(entries) { view.@org.geogebra.web.html5.util.ViewW::zippedLength = entries.length; for (var i = 0, l = entries.length; i < l; i++) { (function(entry){ var filename = entry.filename; if (entry.filename.match(imageRegex)) { @org.geogebra.common.util.debug.Log::debug(Ljava/lang/String;)(filename+" : image"); var filenameParts = filename.split("."); entry.getData(new $wnd.zip.Data64URIWriter("image/"+filenameParts[filenameParts.length - 1]), function (data) { view.@org.geogebra.web.html5.util.ViewW::putIntoArchiveContent(Ljava/lang/String;Ljava/lang/String;)(filename,data); }); } else { @org.geogebra.common.util.debug.Log::debug(Ljava/lang/String;)(entry.filename+" : text"); if ($wnd.zip.useWebWorkers === false || (typeof $wnd.zip.forceDataURIWriter !== "undefined" && $wnd.zip.forceDataURIWriter === true)) { @org.geogebra.common.util.debug.Log::debug(Ljava/lang/String;)("no worker of forced dataURIWriter"); entry.getData(new $wnd.zip.Data64URIWriter("text/plain"), function(data) { var decoded = $wnd.atob(data.substr(data.indexOf(",")+1)); view.@org.geogebra.web.html5.util.ViewW::putIntoArchiveContent(Ljava/lang/String;Ljava/lang/String;)(filename,decodeUTF8(decoded)); }); } else { @org.geogebra.common.util.debug.Log::debug(Ljava/lang/String;)("worker"); entry.getData(new ASCIIWriter(), function(text) { view.@org.geogebra.web.html5.util.ViewW::putIntoArchiveContent(Ljava/lang/String;Ljava/lang/String;)(filename,decodeUTF8(text)); }); } } })(entries[i]); } reader.close(); }); }; var errorCallback = function (error) { view.@org.geogebra.web.html5.util.ViewW::onError(Ljava/lang/String;)(error); }; $wnd.zip.createReader(ggbReader,readerCallback, errorCallback); }-*/; public void onError(String s) { Log.error(s); // eg 403 if (s.startsWith("Error 40")) { this.app.getScriptManager().ggbOnInit(); ToolTipManagerW.sharedInstance().showBottomMessage( app.getLocalization().getMenu("FileLoadingError"), false, app); } } public void processFileName(String url) { if (url.endsWith(".off")) { HttpRequestW request = new HttpRequestW(); request.sendRequestPost(url, "", new AjaxCallback() { @Override public void onSuccess(String response) { app.openOFF(response); } @Override public void onError(String error) { // TODO Auto-generated method stub } }); return; } if (url.endsWith(".csv")) { HttpRequestW request = new HttpRequestW(); request.sendRequestPost(url, "", new AjaxCallback() { @Override public void onSuccess(String response) { app.openCSV(response); } @Override public void onError(String error) { // TODO Auto-generated method stub } }); return; } populateArchiveContent(getHTTPReader(url)); } private native JavaScriptObject getHTTPReader(String url)/*-{ return new $wnd.zip.HttpReader(url); }-*/; /** * @param binary * string (zipped GGB) */ public void processBinaryString(JavaScriptObject binary) { populateArchiveContent(getBinaryReader(binary)); } private native JavaScriptObject getBinaryReader(Object blob) /*-{ return new $wnd.zip.BlobReader(blob); }-*/; private native JavaScriptObject getBase64Reader(String base64str)/*-{ return new $wnd.zip.Data64URIReader(base64str); }-*/; private String prepareFileReading() { archiveContent = new HashMap<String, String>(); String workerUrls = GgbAPIW.zipJSworkerURL(); Log.debug("start unzipping" + System.currentTimeMillis()); return workerUrls; } private void prepare(int t) { archiveContent = new HashMap<String, String>(); this.zippedLength = t; } public boolean getDataParamApp() { return ((ArticleElement) container).getDataParamApp(); } /** * @param encoded * JSON encoded ZIP file (zip.js format) */ public native void processJSON(String encoded) /*-{ var content = JSON.parse(encoded).archive; this.@org.geogebra.web.html5.util.ViewW::prepare(I)(content.length); for (var k = 0; k < content.length; k++) { this.@org.geogebra.web.html5.util.ViewW::putIntoArchiveContent(Ljava/lang/String;Ljava/lang/String;)(content[k].fileName,content[k].fileContent); } }-*/; public native void processJSON(JavaScriptObject zip) /*-{ var that = this; $wnd .setTimeout( function() { var content = zip.archive; that.@org.geogebra.web.html5.util.ViewW::prepare(I)(content.length); for (var k = 0; k < content.length; k++) { that.@org.geogebra.web.html5.util.ViewW::putIntoArchiveContent(Ljava/lang/String;Ljava/lang/String;)(content[k].fileName,content[k].fileContent); } }, 0); }-*/; public void adjustScale() { ((ArticleElement) this.container).adjustScale(); } public String getDataParamTubeID() { return ((ArticleElement) this.container).getDataParamTubeID(); } }