diff --git a/.gitignore b/.gitignore index e1b1ff2c1..867e2e474 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,4 @@ src-gen /.apt_generated/ /infer-out/ /mavenResources/META-INF/licenses +/doc/ \ No newline at end of file diff --git a/src/main/java/net/bootsfaces/component/ComponentsEnum.java b/src/main/java/net/bootsfaces/component/ComponentsEnum.java index 1c652d1ea..b795a7223 100644 --- a/src/main/java/net/bootsfaces/component/ComponentsEnum.java +++ b/src/main/java/net/bootsfaces/component/ComponentsEnum.java @@ -18,234 +18,96 @@ package net.bootsfaces.component; public enum ComponentsEnum { - accordion(" EVENT_NAMES = Collections.unmodifiableCollection(Arrays.asList("click", +// "dblclick", "dragstart", "dragover", "drop", "mousedown", "mousemove", "mouseout", "mouseover", "mouseup")); + + public OpenStreetMap() { + setRendererType(DEFAULT_RENDERER); + Tooltip.addResourceFiles(); +// AddResourcesListener.addThemedCSSResource("core.css"); +// AddResourcesListener +// .addResourceIfNecessary("https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.1/images/layers-2x.png"); +// AddResourcesListener +// .addResourceIfNecessary("https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.1/images/layers.png"); +// AddResourcesListener.addResourceIfNecessary( +// "https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.1/images/marker-icon-2x.png"); +// AddResourcesListener +// .addResourceIfNecessary("https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.1/images/marker-icon.png"); +// AddResourcesListener.addResourceIfNecessary( +// "https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.1/images/marker-shadow.png"); + AddResourcesListener + .addResourceIfNecessary("https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.1/leaflet-src.js"); + AddResourcesListener + .addResourceIfNecessary("https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.1/leaflet-src.js.map"); + AddResourcesListener.addResourceIfNecessary("https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.1/leaflet.css"); + AddResourcesListener.addResourceIfNecessary("https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.1/leaflet.js"); + AddResourcesListener + .addResourceIfNecessary("https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.1/leaflet.js.map"); + } + + public void setValueExpression(String name, ValueExpression binding) { + name = BsfUtils.snakeCaseToCamelCase(name); + super.setValueExpression(name, binding); + } + + @Override + public boolean getRendersChildren() { + return true; + } + +// public Collection getEventNames() { +// return EVENT_NAMES; +// } + +// public String getDefaultEventName() { +// return "click"; +// } + + public void processEvent(ComponentSystemEvent event) throws AbortProcessingException { +// if (isAutoUpdate()) { +// if (FacesContext.getCurrentInstance().isPostback()) { +// FacesContext.getCurrentInstance().getPartialViewContext().getRenderIds().add(getClientId()); +// } +// super.processEvent(event); +// } + } + + public String getFamily() { + return COMPONENT_FAMILY; + } + + /** + *

+ * Queue an event for broadcast at the end of the current request processing + * lifecycle phase. The default implementation in {@link UIComponentBase} must + * delegate this call to the queueEvent() method of the parent + * {@link UIComponent}. + *

+ * + * @param event {@link FacesEvent} to be queued + * + * @throws IllegalStateException if this component is not a descendant of a + * {@link UIViewRoot} + * @throws NullPointerException if event is null + */ + public void queueEvent(FacesEvent event) { + FacesContext context = FacesContext.getCurrentInstance(); + String indexes = (String) context.getExternalContext().getRequestParameterMap().get("indexes"); + context.getELContext().getELResolver().setValue(context.getELContext(), null, "indexes", indexes); + String typeOfSelection = (String) context.getExternalContext().getRequestParameterMap().get("typeOfSelection"); + context.getELContext().getELResolver().setValue(context.getELContext(), null, "typeOfSelection", + typeOfSelection); + try { + int oldIndex = getRowIndex(); + int index = Integer.valueOf(indexes); + setRowIndex(index); + super.queueEvent(event); + setRowIndex(oldIndex); + } catch (Exception multipleIndexes) { + super.queueEvent(event); + + } + } + +} diff --git a/src/main/java/net/bootsfaces/component/openStreetMap/OpenStreetMapBeanInfo.java b/src/main/java/net/bootsfaces/component/openStreetMap/OpenStreetMapBeanInfo.java new file mode 100644 index 000000000..9a2967ff0 --- /dev/null +++ b/src/main/java/net/bootsfaces/component/openStreetMap/OpenStreetMapBeanInfo.java @@ -0,0 +1,19 @@ +package net.bootsfaces.component.openStreetMap; + +import net.bootsfaces.beans.BsfBeanInfo; + +/** + * BeanInfo class to provide mapping + * of snake-case attributes to camelCase ones + * + * @author durzod + */ +public class OpenStreetMapBeanInfo extends BsfBeanInfo { + /** + * Get the reference decorated class + */ + @Override + public Class getDecoratedClass() { + return OpenStreetMap.class; + } +} \ No newline at end of file diff --git a/src/main/java/net/bootsfaces/component/openStreetMap/OpenStreetMapCore.java b/src/main/java/net/bootsfaces/component/openStreetMap/OpenStreetMapCore.java new file mode 100644 index 000000000..2f03ec1f0 --- /dev/null +++ b/src/main/java/net/bootsfaces/component/openStreetMap/OpenStreetMapCore.java @@ -0,0 +1,368 @@ +/** + * Copyright 2014-2017 Riccardo Massera (TheCoder4.Eu), Dario D'Urzo and Stephan Rauh (http://www.beyondjava.net). + * + * This file is part of BootsFaces. + * +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ + +package net.bootsfaces.component.openStreetMap; + +import javax.faces.component.UIData; + +/** This class holds the attributes of <b:openStreetMap />. */ +public abstract class OpenStreetMapCore extends UIData { + + protected enum PropertyKeys { + center, marker, popupMsg, zoom, width, height, minZoom, maxZoom, dragging, zoomControl, zoomGlobal, attribution, + miniMap, miniMapWidth, miniMapHeight, miniMapPosition, urlTemplate; + String toString; + + PropertyKeys(String toString) { + this.toString = toString; + } + + PropertyKeys() { + } + + public String toString() { + return ((this.toString != null) ? this.toString : super.toString()); + } + } + + /** + * String specifying the center of the map. + * + * @return Returns the value of the attribute, or null, if it hasn't been set by + * the JSF file. + */ + public String getCenter() { + return (String) getStateHelper().eval(PropertyKeys.center); + } + + /** + * String specifying the center of the map. + * + * Usually this method is called internally by the JSF engine. + */ + public void setCenter(String _value) { + getStateHelper().put(PropertyKeys.center, _value); + } + + /** + * marker + * + * @return Returns the value of the attribute, or null, if it hasn't been set by + * the JSF file. + */ + public String getMarker() { + return (String) getStateHelper().eval(PropertyKeys.marker); + } + + /** + * marker + * + * Usually this method is called internally by the JSF engine. + */ + public void setMarker(String _value) { + getStateHelper().put(PropertyKeys.marker, _value); + } + + /** + * popupMsg + * + * @return Returns the value of the attribute, or null, if it hasn't been set by + * the JSF file. + */ + public String getPopupMsg() { + return (String) getStateHelper().eval(PropertyKeys.popupMsg); + } + + /** + * popupMsg + * + * Usually this method is called internally by the JSF engine. + */ + public void setPopupMsg(String _value) { + getStateHelper().put(PropertyKeys.popupMsg, _value); + } + + /** + * zoom + * + * @return Returns the value of the attribute, or null, if it hasn't been set by + * the JSF file. + */ + public Integer getZoom() { + return (Integer) getStateHelper().eval(PropertyKeys.zoom, 10); + } + + /** + * zoom + * + * Usually this method is called internally by the JSF engine. + */ + public void setZoom(Integer _value) { + getStateHelper().put(PropertyKeys.zoom, _value); + } + + /** + * width + * + * @return Returns the value of the attribute, or null, if it hasn't been set by + * the JSF file. + */ + public String getWidth() { + return (String) getStateHelper().eval(PropertyKeys.width, "300px"); + } + + /** + * width + * + * Usually this method is called internally by the JSF engine. + */ + public void setWidth(String _value) { + getStateHelper().put(PropertyKeys.width, _value); + } + + /** + * height + * + * @return Returns the value of the attribute, or null, if it hasn't been set by + * the JSF file. + */ + public String getHeight() { + return (String) getStateHelper().eval(PropertyKeys.height, "200px"); + } + + /** + * height + * + * Usually this method is called internally by the JSF engine. + */ + public void setHeight(String _value) { + getStateHelper().put(PropertyKeys.height, _value); + } + + /** + * minZoom + * + * @return Returns the value of the attribute, or null, if it hasn't been set by + * the JSF file. + */ + public Integer getMinZoom() { + return (Integer) getStateHelper().eval(PropertyKeys.minZoom, 1); + } + + /** + * minZoom + * + * Usually this method is called internally by the JSF engine. + */ + public void setMinZoom(Integer _value) { + getStateHelper().put(PropertyKeys.minZoom, _value); + } + + /** + * maxZoom + * + * @return Returns the value of the attribute, or null, if it hasn't been set by + * the JSF file. + */ + public Integer getMaxZoom() { + return (Integer) getStateHelper().eval(PropertyKeys.maxZoom, 19); + } + + /** + * maxZoom + * + * Usually this method is called internally by the JSF engine. + */ + public void setMaxZoom(Integer _value) { + getStateHelper().put(PropertyKeys.maxZoom, _value); + } + + /** + * Boolean to set whether dragging is enabled. + * + * @return Returns the value of the attribute, or , false, if it hasn't been set + * by the JSF file. + */ + public Boolean getDragging() { + return (Boolean) getStateHelper().eval(PropertyKeys.dragging, true); + } + + /** + * Boolean to set whether dragging is enabled. + * + * Usually this method is called internally by the JSF engine. + */ + public void setDragging(boolean _value) { + getStateHelper().put(PropertyKeys.dragging, _value); + } + + /** + * zoomControl + * + * @return Returns the value of the attribute, or , false, if it hasn't been set + * by the JSF file. + */ + public Boolean getZoomControl() { + return (Boolean) getStateHelper().eval(PropertyKeys.zoomControl, true); + } + + /** + * zoomControl + * + * Usually this method is called internally by the JSF engine. + */ + public void setZoomControl(boolean _value) { + getStateHelper().put(PropertyKeys.zoomControl, _value); + } + + /** + * zoomGlobal + * + * @return Returns the value of the attribute, or , false, if it hasn't been set + * by the JSF file. + */ + public Boolean getZoomGlobal() { + return (Boolean) getStateHelper().eval(PropertyKeys.zoomGlobal, true); + } + + /** + * zoomGlobal + * + * Usually this method is called internally by the JSF engine. + */ + public void setZoomGlobal(boolean _value) { + getStateHelper().put(PropertyKeys.zoomGlobal, _value); + } + + /** + * attribution + * + * @return Returns the value of the attribute, or null, if it hasn't been set by + * the JSF file. + */ + public String getAttribution() { + return (String) getStateHelper().eval(PropertyKeys.attribution, + "Map data © OpenStreetMap contributors,CC-BY-SA"); +// return (String) getStateHelper().eval(PropertyKeys.attribution, +// "Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors,<a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>");} + } + + /** + * attribution + * + * Usually this method is called internally by the JSF engine. + */ + public void setAttribution(String _value) { + getStateHelper().put(PropertyKeys.attribution, _value); + } + + /** + * miniMap + * + * @return Returns the value of the attribute, or , false, if it hasn't been set + * by the JSF file. + */ + public Boolean getMiniMap() { + return (Boolean) getStateHelper().eval(PropertyKeys.miniMap, false); + } + + /** + * miniMap + * + * Usually this method is called internally by the JSF engine. + */ + public void setMiniMap(boolean _value) { + getStateHelper().put(PropertyKeys.miniMap, _value); + } + + /** + * miniMapWidth + * + * @return Returns the value of the attribute, or null, if it hasn't been set by + * the JSF file. + */ + public Integer getMiniMapWidth() { + return (Integer) getStateHelper().eval(PropertyKeys.miniMapWidth, 100); + } + + /** + * miniMapWidth + * + * Usually this method is called internally by the JSF engine. + */ + public void setMiniMapWidth(Integer _value) { + getStateHelper().put(PropertyKeys.miniMapWidth, _value); + } + + /** + * miniMapHeight + * + * @return Returns the value of the attribute, or null, if it hasn't been set by + * the JSF file. + */ + public Integer getMiniMapHeight() { + return (Integer) getStateHelper().eval(PropertyKeys.miniMapHeight, 100); + } + + /** + * miniMapHeight + * + * Usually this method is called internally by the JSF engine. + */ + public void setMiniMapHeight(Integer _value) { + getStateHelper().put(PropertyKeys.miniMapHeight, _value); + } + + /** + * miniMapPosition + * + * @return Returns the value of the attribute, or null, if it hasn't been set by + * the JSF file. + */ + public String getMiniMapPosition() { + return (String) getStateHelper().eval(PropertyKeys.miniMapPosition, "bottomright"); + } + + /** + * miniMapPosition + * + * Usually this method is called internally by the JSF engine. + */ + public void setMiniMapPosition(String _value) { + getStateHelper().put(PropertyKeys.miniMapPosition, _value); + } + + /** + * urlTemplate + * + * @return Returns the value of the attribute, or null, if it hasn't been set by + * the JSF file. + */ + public String getUrlTemplate() { + return (String) getStateHelper().eval(PropertyKeys.urlTemplate, "http://{s}.tile.osm.org/{z}/{x}/{y}.png"); + } + + /** + * urlTemplate + * + * Usually this method is called internally by the JSF engine. + */ + public void setUrlTemplate(String _value) { + getStateHelper().put(PropertyKeys.urlTemplate, _value); + } +} diff --git a/src/main/java/net/bootsfaces/component/openStreetMap/OpenStreetMapRenderer.java b/src/main/java/net/bootsfaces/component/openStreetMap/OpenStreetMapRenderer.java new file mode 100644 index 000000000..c9fab32f0 --- /dev/null +++ b/src/main/java/net/bootsfaces/component/openStreetMap/OpenStreetMapRenderer.java @@ -0,0 +1,137 @@ +/** + * Copyright 2014-2017 Riccardo Massera (TheCoder4.Eu) and Stephan Rauh (http://www.beyondjava.net). + * + * This file is part of BootsFaces. + * +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ + +package net.bootsfaces.component.openStreetMap; + +import java.io.IOException; + +import javax.faces.component.UIComponent; +import javax.faces.context.FacesContext; +import javax.faces.context.ResponseWriter; +import javax.faces.render.FacesRenderer; + +import net.bootsfaces.component.ajax.AJAXRenderer; +import net.bootsfaces.render.CoreRenderer; + +/** This class generates the HTML code of <b:openStreetMap />. */ +@FacesRenderer(componentFamily = "net.bootsfaces.component", rendererType = "net.bootsfaces.component.openStreetMap.OpenStreetMap") +public class OpenStreetMapRenderer extends CoreRenderer { + + @Override + public void decode(FacesContext context, UIComponent component) { + OpenStreetMap openStreetMap = (OpenStreetMap) component; + + decodeBehaviors(context, openStreetMap); // f:ajax + + String clientId = openStreetMap.getClientId(context); + new AJAXRenderer().decode(context, component, clientId); + } + + /** + * This methods generates the HTML code of the current b:openStreetMap. + * encodeBegin generates the start of the component. After the, the + * JSF framework calls encodeChildren() to generate the HTML code + * between the beginning and the end of the component. For instance, in the case + * of a panel component the content of the panel is generated by + * encodeChildren(). After that, encodeEnd() is called + * to generate the rest of the HTML code. + * + * @param context the FacesContext. + * @param component the current b:openStreetMap. + * @throws IOException thrown if something goes wrong when writing the HTML + * code. + */ + @Override + public void encodeBegin(FacesContext context, UIComponent component) throws IOException { + + if (!component.isRendered()) { + return; + } + OpenStreetMap openStreetMap = (OpenStreetMap) component; + + ResponseWriter rw = context.getResponseWriter(); + String clientId = openStreetMap.getClientId(); + + rw.startElement("div", openStreetMap); + rw.writeAttribute("id", clientId, "id"); + rw.writeAttribute("style", "width:" + openStreetMap.getWidth() + "; height:" + openStreetMap.getHeight(), null); + + } + + /** + * This methods generates the HTML code of the current b:openStreetMap. + * encodeBegin generates the start of the component. After the, the + * JSF framework calls encodeChildren() to generate the HTML code + * between the beginning and the end of the component. For instance, in the case + * of a panel component the content of the panel is generated by + * encodeChildren(). After that, encodeEnd() is called + * to generate the rest of the HTML code. + * + * @param context the FacesContext. + * @param component the current b:openStreetMap. + * @throws IOException thrown if something goes wrong when writing the HTML + * code. + */ + @Override + public void encodeEnd(FacesContext context, UIComponent component) throws IOException { + if (!component.isRendered()) { + return; + } + OpenStreetMap openStreetMap = (OpenStreetMap) component; + ResponseWriter rw = context.getResponseWriter(); + String clientIdRaw = openStreetMap.getClientId(); + String clientId = clientIdRaw.replace(":", ""); + + rw.endElement("div"); + + rw.startElement("script", component); + rw.writeText("var " + clientId + "_map = L.map('" + clientId + "', {center: [" + openStreetMap.getCenter() + + "], zoom: " + openStreetMap.getZoom() + ", layers: L.tileLayer('" + openStreetMap.getUrlTemplate() + + "', {id: 'osm', attribution: '" + openStreetMap.getAttribution() + "', maxZoom: " + + openStreetMap.getMaxZoom() + ", minZoom: " + openStreetMap.getMinZoom() + "}), dragging:" + + openStreetMap.getDragging() + ", zoomControl:" + openStreetMap.getZoomControl() + " });", null); + rw.writeText("if('" + openStreetMap.getMarker() + "')", null); + rw.writeText("{", null); + rw.writeText("var " + clientId + "_marker = L.marker([" + openStreetMap.getMarker() + + "],{icon: new L.Icon({iconSize: [25, 41], iconAnchor: [25, 41], popupAnchor: [-12, -45], iconUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.1/images/marker-icon.png', shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.1/images/marker-shadow.png'})}).addTo(" + + clientId + "_map);", null); + rw.writeText("if('" + openStreetMap.getPopupMsg() + "')", null); + rw.writeText(clientId + "_marker.bindPopup('" + openStreetMap.getPopupMsg() + "');", null); + rw.writeText("}", null); + rw.writeText("if(!" + openStreetMap.getZoomGlobal() + ")", null); + rw.writeText("{", null); + rw.writeText(clientId + "_map.touchZoom.disable();", null); + rw.writeText(clientId + "_map.doubleClickZoom.disable();", null); + rw.writeText(clientId + "_map.scrollWheelZoom.disable();", null); + rw.writeText(clientId + "_map.boxZoom.disable();", null); + rw.writeText(clientId + "_map.keyboard.disable();", null); + rw.writeText("}", null); + rw.writeText("if(" + openStreetMap.getMiniMap() + ")", null); + rw.writeText("{", null); + rw.writeText("new L.Control.MiniMap(L.tileLayer('" + openStreetMap.getUrlTemplate() + "', {}), {", null); + rw.writeText("toggleDisplay: true,", null); + rw.writeText("zoomAnimation: true,", null); + rw.writeText("position: '" + openStreetMap.getMiniMapPosition() + "',", null); + rw.writeText("width: " + openStreetMap.getMiniMapWidth() + ",", null); + rw.writeText("height: " + openStreetMap.getMiniMapWidth(), null); + rw.writeText("}).addTo(" + clientId + "_map);", null); + rw.writeText("}", null); + rw.endElement("script"); + } + +} diff --git a/src/main/meta/META-INF/bootsfaces-b.taglib.xml b/src/main/meta/META-INF/bootsfaces-b.taglib.xml index 0794e99b3..7fbdce711 100644 --- a/src/main/meta/META-INF/bootsfaces-b.taglib.xml +++ b/src/main/meta/META-INF/bootsfaces-b.taglib.xml @@ -18365,6 +18365,116 @@ + + + openStreetMap + + net.bootsfaces.component.openStreetMap.OpenStreetMap + + + + center + true + java.lang.String + + + + marker + false + java.lang.String + + + + popupMsg + false + java.lang.String + + + + zoom + false + java.lang.Integer + + + + width + false + java.lang.String + + + + height + false + java.lang.String + + + + minZoom + false + java.lang.Integer + + + + maxZoom + false + java.lang.Integer + + + + dragging + false + java.lang.Boolean + + + + zoomControl + false + java.lang.Boolean + + + + zoomGlobal + false + java.lang.Boolean + + + + attribution + false + java.lang.String + + + + miniMap + false + java.lang.Boolean + + + + miniMapWidth + false + java.lang.Integer + + + + miniMapHeight + false + java.lang.Integer + + + + miniMapPosition + false + java.lang.String + + + + urlTemplate + false + java.lang.String + + + panel diff --git a/xtext/BootsFaces.jsfdsl b/xtext/BootsFaces.jsfdsl index 2c4eefe16..20076e567 100644 --- a/xtext/BootsFaces.jsfdsl +++ b/xtext/BootsFaces.jsfdsl @@ -1607,7 +1607,7 @@ widget navLink widget navbarLinks - implemented_by net.bootsfaces.component.NavBarLinks + implemented_by net.bootsfaces.component.navBarLinks.NavBarLinks has_tooltip { auto-update Boolean "Setting this flag updates the widget on every AJAX request." @@ -1620,6 +1620,27 @@ widget navbarLinks +contentDisabled } +widget openStreetMap + implemented_by net.bootsfaces.component.openStreetMap.OpenStreetMap +{ + center String "center" + marker String "marker" + popupMsg String "popupMsg" + zoom Integer "zoom" + width String "width" + height String "height" + minZoom Integer "minZoom" + maxZoom Integer "maxZoom" + dragging Boolean "dragging" + zoomControl Boolean "zoomControl" + zoomGlobal Boolean "zoomGlobal" + attribution String "attribution" + miniMap Boolean "miniMap" + miniMapWidth Integer "miniMapWidth" + miniMapHeight Integer "miniMapHeight" + miniMapPosition String "miniMapPosition" + urlTemplate String "urlTemplate" +} widget panel implemented_by net.bootsfaces.component.panel.Panel