package org.geogebra.web.html5.util;
import java.util.ArrayList;
import java.util.Date;
import org.geogebra.common.GeoGebraConstants;
import org.geogebra.common.factories.CASFactory;
import org.geogebra.common.main.App;
import org.geogebra.common.main.App.InputPosition;
import org.geogebra.common.util.debug.Log;
import org.geogebra.web.html5.Browser;
import org.geogebra.web.html5.main.AppW;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NodeList;
import com.google.gwt.dom.client.TagName;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Window.Location;
import com.google.gwt.user.client.ui.Widget;
@TagName(ArticleElement.TAG)
public final class ArticleElement extends Element {
static final String TAG = "article";
/**
* @param element
* Assert, that the given {@link Element} is compatible with this
* class and automatically typecast it.
* @return
*/
public static ArticleElement as(Element element) {
if (element != null) {
element.setTabIndex(10);
}
// assert element.getTagName().equalsIgnoreCase(TAG);
//addNativeHandlers(element);
return (ArticleElement) element;
}
protected ArticleElement() {
}
public void add(Widget w) {
this.appendChild(w.getElement());
}
public void clear() {
this.setInnerHTML("");
}
public boolean remove(Widget w) {
for (int i = 0; i < this.getChildCount(); i++) {
if (this.getChild(i).equals(w.getElement())) {
this.removeChild(this.getChild(i));
return true;
}
}
return false;
}
public static native void addNativeHandlers(Element el, AppW app)/*-{
el.onfocus = function(event) {
app.@org.geogebra.web.html5.main.AppW::addFocusToApp()();
}
}-*/;
/**
* @return the data-param-id article attribute as String if set else
* AppWeb.DEFAULT_APPLET_ID
*/
public String getDataParamId() {
String ret = this.getAttribute("data-param-id");
if (("".equals(ret)) || !ret.matches("[A-Za-z0-9_]+")) {
return AppW.DEFAULT_APPLET_ID;
}
return ret;
}
/**
* @return the data-param-filename article attribute as String if set else
* empty String
*/
public String getDataParamFileName() {
String ret = this.getAttribute("data-param-filename");
return (ret != null) ? ret : "";
}
public String getDataParamJSON() {
String ret = this.getAttribute("data-param-json");
return (ret != null) ? ret : "";
}
/**
* Determines if the "data-param-guiOff" article attribute is set to true If
* it is set to true, the GuiManager should never be created, and only a
* single Graphics View should show in web applets, regardless of what is
* there in the ggb file's construction. This is for speedup, but its
* drawback is that it should be decided before the AppW is created.
*
* @return the data-param-guiOff (default: false)
*/
public boolean getDataParamGuiOff() {
return ("true".equals(this.getAttribute("data-param-guiOff")));
}
/**
* Determines if the "data-param-enableLabelDrags" article attribute is set
* to true
*
* @return the data-param-enableLabelDrags (default: true)
*/
public boolean getDataParamEnableLabelDrags() {
return (!"false".equals(this
.getAttribute("data-param-enableLabelDrags")));
}
/**
* Determines if the "data-param-enableUndoRedo" article attribute is set to
* true
*
* @return the data-param-enableUndoRedo (default: true)
*/
public boolean getDataParamEnableUndoRedo() {
return (!"false"
.equals(this.getAttribute("data-param-enableUndoRedo")));
}
/**
* Determines if the "data-param-enableRightClick" article attribute is set
* to true
*
* @return the data-param-enableRightClick (default: true)
*/
public boolean getDataParamEnableRightClick() {
return (!"false".equals(this
.getAttribute("data-param-enableRightClick")));
}
public boolean getDataParamEnableCAS(boolean def) {
return getBoolParam("data-param-enableCAS", def);
}
public boolean getDataParamEnable3D(boolean def) {
return getBoolParam("data-param-enable3D", def);
}
public boolean getDataParamEnableGraphing(boolean def) {
return getBoolParam("data-param-enableGraphing", def);
}
/*
* Returns true, if there is data-param-enableGraphing attribute, and it is
* not an empty string
*/
public boolean hasDataParamEnableGraphing() {
return !"".equals(this.getAttribute("data-param-enableGraphing"));
}
public String getDataParamRounding() {
return this.getAttribute("data-param-rounding");
}
/**
* @return the data-param-ggbbase64 article attribute as String if set else
* empty String
*/
public String getDataParamBase64String() {
String ret = this.getAttribute("data-param-ggbbase64");
return (ret != null) ? ret : "";
}
/**
* @return the data-param-showMenuBar (default: false)
*/
public boolean getDataParamShowMenuBar(boolean def) {
return getBoolParam("data-param-showMenuBar",
def) || getDataParamApp();
}
public boolean getDataParamShowMenuBar2(boolean def) {
return getBoolParam("data-param-showMenuBar", def);
}
public boolean getDataParamAllowStyleBar(boolean def) {
return getBoolParam("data-param-allowStyleBar", def);
}
/**
* @return the data-param-showToolBar (default: false)
*/
public boolean getDataParamShowToolBar(boolean def) {
if (getDataParamShowMenuBar(false) || getDataParamApp()) {
return true;
}
return getBoolParam("data-param-showToolBar", def);
}
public boolean getDataParamShowToolBarHelp(boolean def) {
if (!getDataParamShowToolBar(false) && !getDataParamApp()) {
return false;
}
return getBoolParam("data-param-showToolBarHelp", def);
}
/**
*
* @return the data-param-customToolBar (default: null)
*/
public String getDataParamCustomToolBar() {
return this.getAttribute("data-param-customToolBar");
}
/**
* @return the data-param-showAlgebraInput (default: true)
*/
public boolean getDataParamShowAlgebraInput(boolean def) {
return getBoolParam("data-param-showAlgebraInput", def);
}
public InputPosition getAlgebraPosition(InputPosition def) {
String pos = this.getAttribute("data-param-algebraInputPosition").toLowerCase().trim();
if("top".equals(pos)){
return InputPosition.top;
}
if("bottom".equals(pos)){
return InputPosition.bottom;
}
if(pos.length() > 0){
return InputPosition.algebraView;
}
return def;
}
private boolean getBoolParam(String attr, boolean def) {
return (def && !"false".equals(this.getAttribute(attr)))
|| "true".equals(this.getAttribute(attr));
}
/**
* @return the data-param-showResetIcon (default: false)
*/
public boolean getDataParamShowResetIcon() {
return ("true".equals(this.getAttribute("data-param-showResetIcon")));
}
/**
* @return the data-param-showAnimationButton (default: true)
*/
public boolean getDataParamShowAnimationButton() {
return (!"false".equals(this
.getAttribute("data-param-showAnimationButton")));
}
public int getDataParamCapturingThreshold() {
int threshold = App.DEFAULT_THRESHOLD;
if ("".equals(this.getAttribute("data-param-capturingThreshold"))) {
return threshold;
}
try {
threshold = Integer.parseInt(this
.getAttribute("data-param-capturingThreshold"));
} catch (Throwable t) {
Log.error("Invalid capturing threshold: "
+ this.getAttribute("data-param-capturingThreshold"));
}
return threshold;
}
/**
* eg "de"
*
* @return the data-param-showResetIcon (default: null)
*/
public String getDataParamLanguage() {
return this.getAttribute("data-param-language");
}
/**
*
* eg "AT"
*
* @return the data-param-showResetIcon (default: null)
*/
public String getDataParamCountry() {
return this.getAttribute("data-param-country");
}
/**
*
* @return the data-param-allowJSscripting (default: true)
*/
public boolean getDataParamUseBrowserForJS() {
return (!"false"
.equals(this.getAttribute("data-param-useBrowserForJS")));
}
/**
* @return the data-param-enableShiftDragZoom (default: true)
*/
public boolean getDataParamShiftDragZoomEnabled() {
return (!"false".equals(this
.getAttribute("data-param-enableShiftDragZoom")));
}
/**
* @return integer value of the data-param-width, 0 if not present
*/
public int getDataParamWidth() {
return getIntegerAttribute("data-param-width", 0);
}
private int getIntegerAttribute(String string, int fallback) {
String val = this.getAttribute(string);
if(val == null || val.isEmpty()){
return fallback;
}
try{
return Integer.parseInt(val, 10);
} catch (Exception e) {
Log.warn("Invalid value of " + string + ":" + val);
}
return fallback;
}
/**
* @return integer value of the data-param-height, 0 if not present
*/
public int getDataParamHeight() {
return getIntegerAttribute("data-param-height", 0);
}
/**
* @return wheter the applet should fit to screen
*/
public boolean getDataParamFitToScreen() {
return "true".equals(this.getAttribute("data-param-fittoscreen"))
|| getDataParamApp();
}
public String getDataParamBorder() {
return this.getAttribute("data-param-borderColor");
}
/**
* @return the data-param-showLogging (default: false)
*/
public boolean getDataParamShowLogging() {
return ("true".equals(this.getAttribute("data-param-showLogging")) || Location
.getParameter("GeoGebraDebug") != null);
}
/**
* @return the data-param-allowSymbolTable (default: true)
*/
public boolean getDataParamAllowSymbolTable() {
return (!"false".equals(this
.getAttribute("data-param-allowSymbolTable")));
}
/**
*
* @return that the article element has (inherited) direction attribute
*/
public native boolean isRTL() /*-{
var style;
if ($wnd.getComputedStyle) {
style = $wnd.getComputedStyle(this);
return style.direction === "rtl";
} else if (this.currentStyle) {
return this.currentStyle.direction === "rtl";
}
return false;
}-*/;
private static native String getTransform(JavaScriptObject style) /*-{
return style.transform || style.webkitTransform || style.MozTransform
|| style.msTransform || style.oTransform || "";
}-*/;
private native double envScale(String type) /*-{
var current = this;
var sx = 1;
var sy = 1;
do {
var matrixRegex = /matrix\((-?\d*\.?\d+),\s*(-?\d*\.?\d+),\s*(-?\d*\.?\d+),\s*(-?\d*\.?\d+),\s*(-?\d*\.?\d+),\s*(-?\d*\.?\d+)\)/, style = $wnd
.getComputedStyle(current);
if (style) {
var transform = style.transform || style.webkitTransform
|| style.MozTransform || style.msTransform
|| style.oTransform || "";
var matches = transform.match(matrixRegex);
if (matches && matches.length) {
sx *= $wnd.parseFloat(matches[1]);
sy *= $wnd.parseFloat(matches[4]);
} else if (transform.indexOf("scale") === 0) {
var mul = $wnd.parseFloat(transform.substr(transform
.indexOf("(") + 1));
sx *= mul;
sy *= mul;
}
}
current = current.parentElement;
} while (current);
return type === "x" ? sx : sy;
}-*/;
/**
* @return the CSS scale attached to the article element
*/
public double getScaleX() {
// no instance fields in subclasses of Element, so no way to assign it
// to
// a simple field
if ("".equals(this.getAttribute("data-scalex"))) {
this.setAttribute("data-scalex", String.valueOf(envScale("x")));
}
return Double.parseDouble(this.getAttribute("data-scalex"));
}
public double readScaleX() {
if ("".equals(this.getAttribute("data-scalex"))) {
return envScale("x");
}
return Double.parseDouble(this.getAttribute("data-scalex"));
}
/**
* @return the CSS scale attached to the article element
*
*/
public double getScaleY() {
// no instance fields in subclasses of Element, so no way to asign it to
// a simple field
if ("".equals(this.getAttribute("data-scaley"))) {
this.setAttribute("data-scaley", String.valueOf(envScale("y")));
}
return Double.parseDouble(this.getAttribute("data-scaley"));
}
/**
* @return default false
*/
public boolean getDataParamAllowStyleBar() {
return "true".equals(getAttribute("data-param-allowStyleBar"));
}
public boolean getDataParamApp() {
return "true".equals(this.getAttribute("data-param-app"));
}
public boolean getDataParamScreenshotGenerator() {
return "true".equals(this
.getAttribute("data-param-screenshotGenerator"));
}
public String getDataParamLAF() {
return this.getAttribute("data-param-laf");
}
/**
* @return wheter focus prevented (use in multiple applets)
*/
public boolean preventFocus() {
return this.getAttribute("data-param-preventFocus") != null;
}
public String getDataClientID() {
return this.getAttribute("data-param-clientid");
}
public String getDataParamPerspective() {
String ret = this.getAttribute("data-param-perspective");
return ret == null ? "" : ret;
}
public double getDataParamScale() {
String scale = this.getAttribute("data-param-scale");
if (scale.length() < 1) {
return 1;
}
double ret = 1;
try {
ret = Double.parseDouble(scale);
} catch (Throwable t) {
Log.warn("Invalid scale");
}
return ret;
}
/**
* Sync data-scale params with external environment
*
*/
public void adjustScale() {
if (getDataParamApp()
|| (getAttribute("data-scalex") != null && !""
.equals(getAttribute("data-scalex")))) {
return;
}
double externalScale = getDataParamScale();
Element parent = this.getParentElement();
if (parent.getParentElement() != null
&& "applet_container".equals(parent.getParentElement().getId())) {
parent = parent.getParentElement();
}
Browser.scale(parent, externalScale, 0, 0);
setAttribute("data-scalex", "" + envScale("x"));
setAttribute("data-scaley", "" + envScale("y"));
}
public String getDataParamPrerelease() {
return getAttribute("data-param-prerelease").trim().toLowerCase();
}
public String getDataParamTubeID() {
return getAttribute("data-param-tubeid");
}
/*
* public boolean getDataParamNo3D() { return
* "true".equals(getAttribute("data-param-no3d")); }
*
* public boolean getDataParamNoCAS() { return
* "true".equals(getAttribute("data-param-nocas")); }
*/
public boolean getDataParamShowStartTooltip(boolean def) {
return getBoolParam("data-param-showTutorialLink", def);
}
/**
* @return whether to enable file menu
*/
public boolean getDataParamEnableFileFeatures() {
return !"false".equals(getAttribute("data-param-enableFileFeatures"));
}
public static ArrayList<ArticleElement> getGeoGebraMobileTags() {
NodeList<Element> nodes = Dom
.getElementsByClassName(GeoGebraConstants.GGM_CLASS_NAME);
ArrayList<ArticleElement> articleNodes = new ArrayList<ArticleElement>();
for (int i = 0; i < nodes.getLength(); i++) {
ArticleElement ae = ArticleElement.as(nodes.getItem(i));
ae.initID(i);
articleNodes.add(ae);
}
return articleNodes;
}
public void initID(int i) {
String paramID = getDataParamId();
if (paramID.length() > 0) {
int suffix = 0;
while (DOM.getElementById(paramID) != null) {
paramID = getDataParamId() + suffix;
suffix++;
}
setId(paramID);
return;
}
Date creationDate = new Date();
setId(GeoGebraConstants.GGM_CLASS_NAME + i + creationDate.getTime());
}
public boolean disableHiRes3D() {
return "true".equals(getAttribute("data-param-disablehires3d"));
}
public boolean getDataParamErrorDialogsActive() {
return !"false"
.equals(this.getAttribute("data-param-errorDialogsActive"));
}
public String getApiKey() {
return this.getAttribute("data-param-apiKey");
}
public static boolean isEnableUsageStats() {
return ((CASFactory) GWT.create(CASFactory.class)).isEnabled();
}
public String getMaterialsAPIurl() {
return this.getAttribute("data-param-materialsApi");
}
public String getLoginAPIurl() {
return this.getAttribute("data-param-loginApi");
}
public boolean getDataParamShowAppsPicker() {
return this.getBoolParam("data-param-showAppsPicker", false);
}
public int getBorderThickness() {
return getDataParamFitToScreen() ? 0 : 2;
}
}