Java tutorial
/** * ========================================================================================== * = JAHIA'S DUAL LICENSING - IMPORTANT INFORMATION = * ========================================================================================== * * http://www.jahia.com * * Copyright (C) 2002-2017 Jahia Solutions Group SA. All rights reserved. * * THIS FILE IS AVAILABLE UNDER TWO DIFFERENT LICENSES: * 1/GPL OR 2/JSEL * * 1/ GPL * ================================================================================== * * IF YOU DECIDE TO CHOOSE THE GPL LICENSE, YOU MUST COMPLY WITH THE FOLLOWING TERMS: * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * * 2/ JSEL - Commercial and Supported Versions of the program * =================================================================================== * * IF YOU DECIDE TO CHOOSE THE JSEL LICENSE, YOU MUST COMPLY WITH THE FOLLOWING TERMS: * * Alternatively, commercial and supported versions of the program - also known as * Enterprise Distributions - must be used in accordance with the terms and conditions * contained in a separate written agreement between you and Jahia Solutions Group SA. * * If you are unsure which license is appropriate for your use, * please contact the sales department at sales@jahia.com. */ package org.jahia.ajax.gwt.client.widget.edit.mainarea; import com.allen_sauer.gwt.log.client.Log; import com.extjs.gxt.ui.client.GXT; import com.extjs.gxt.ui.client.Style; import com.extjs.gxt.ui.client.core.XTemplate; import com.extjs.gxt.ui.client.data.ModelData; import com.extjs.gxt.ui.client.event.*; import com.extjs.gxt.ui.client.util.Margins; import com.extjs.gxt.ui.client.util.Point; import com.extjs.gxt.ui.client.widget.Component; import com.extjs.gxt.ui.client.widget.LayoutContainer; import com.extjs.gxt.ui.client.widget.button.ToolButton; import com.extjs.gxt.ui.client.widget.layout.*; import com.extjs.gxt.ui.client.widget.tips.ToolTipConfig; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.Scheduler; import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.IFrameElement; import com.google.gwt.dom.client.NodeList; import com.google.gwt.http.client.URL; import com.google.gwt.storage.client.Storage; import com.google.gwt.user.client.*; import com.google.gwt.user.client.EventListener; import com.google.gwt.user.client.ui.AbstractImagePrototype; import com.google.gwt.user.client.ui.Frame; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.Image; import org.jahia.ajax.gwt.client.core.JahiaGWTParameters; import org.jahia.ajax.gwt.client.data.GWTJahiaChannel; import org.jahia.ajax.gwt.client.data.GWTJahiaLanguage; import org.jahia.ajax.gwt.client.data.node.GWTJahiaNode; import org.jahia.ajax.gwt.client.data.publication.GWTJahiaPublicationInfo; import org.jahia.ajax.gwt.client.data.toolbar.GWTEditConfiguration; import org.jahia.ajax.gwt.client.data.toolbar.GWTJahiaToolbarItem; import org.jahia.ajax.gwt.client.messages.Messages; import org.jahia.ajax.gwt.client.util.icons.ToolbarIconProvider; import org.jahia.ajax.gwt.client.widget.Linker; import org.jahia.ajax.gwt.client.widget.contentengine.EditContentEnginePopupListener; import org.jahia.ajax.gwt.client.widget.contentengine.EngineLoader; import org.jahia.ajax.gwt.client.widget.edit.EditLinker; import org.jahia.ajax.gwt.client.widget.edit.InfoLayers; import org.jahia.ajax.gwt.client.widget.edit.ToolbarHeader; import org.jahia.ajax.gwt.client.widget.toolbar.ActionContextMenu; import java.util.*; /** * First module of any rendered element. * Sub content will be created as ListModule or SimpleModule. */ public class MainModule extends Module { private static final String[] RESERVED_REQUESTPARAMETERS = new String[] { "channel", "variant" }; private static MainModule module; private EditLinker editLinker; private Storage storage; private ActionContextMenu contextMenu; private GWTEditConfiguration config; private Map<String, GWTEditConfiguration> configs = new HashMap<String, GWTEditConfiguration>(); private InfoLayers infoLayers = new InfoLayers(); private Map<String, Boolean> activeLayers = new HashMap<String, Boolean>(); private boolean ctrlActive = false; private Map<Module, Selection> selections = new HashMap<Module, Selection>(); private boolean needParseAfterLayout = false; private Map<Element, Module> moduleMap; protected LayoutContainer scrollContainer; protected LayoutContainer center; protected EditFrame frame; private Element mainModuleElement; protected String frameError = null; protected boolean frameErrorRedirect = false; private final LayoutContainer headContainer; private String newLocation = null; private boolean firstLoad = true; protected String template; private GWTJahiaChannel activeChannel; private String activeChannelVariant; private static boolean globalSelectionDisabled = false; protected Point framePosition = new Point(0, 0); public MainModule(final String path, final String template, String nodeTypes, GWTEditConfiguration config) { super("main", path, nodeTypes, new BorderLayout()); setScrollMode(Style.Scroll.NONE); this.id = "main"; this.path = path; this.template = template; this.config = config; configs.put(this.config.getName(), this.config); this.depth = 0; storage = Storage.getSessionStorageIfSupported(); if (storage != null) { String user = storage.getItem("currentUser"); if (user != null && !user.equals(JahiaGWTParameters.getCurrentUser())) { storage.clear(); } storage.setItem("currentUser", JahiaGWTParameters.getCurrentUser()); } head = new ToolbarHeader(); head.addStyleName("x-panel-header"); head.setStyleAttribute("z-index", "999"); head.setStyleAttribute("position", "relative"); headContainer = new LayoutContainer(new FitLayout()); headContainer.add(head); add(headContainer, new BorderLayoutData(Style.LayoutRegion.NORTH, 32)); if (config.getMainModuleToolbar() == null || config.getMainModuleToolbar().getGwtToolbarItems().isEmpty()) { headContainer.hide(); } frame = new EditFrame(); frame.setWidth("100%"); frame.setHeight("100%"); frame.addStyleName("x-noshim"); frame.sinkEvents( Event.ONLOAD /*+ Event.ONCLICK + Event.ONCONTEXTMENU + Event.ONMOUSEOVER + Event.ONMOUSEOUT*/); scrollContainer = new LayoutContainer(new FlowLayout()) { @Override protected void onRightClick(ComponentEvent ce) { if (contextMenu != null && fireEvent(Events.ContextMenu, ce)) { Point position = MainModule.getInstance().getContainer().getPosition(false); final int x = ce.getClientX() + position.x; final int y = ce.getClientY() + position.y; ce.stopEvent(); DeferredCommand.addCommand(new Command() { public void execute() { onShowContextMenu(x, y); } }); } } }; scrollContainer.addStyleName("gwt-body-edit"); scrollContainer.setStyleAttribute("position", "relative"); scrollContainer.addListener(Events.OnClick, new Listener<BaseEvent>() { public void handleEvent(BaseEvent be) { if (contextMenu != null && contextMenu.isVisible()) { contextMenu.hide(); } } }); scrollContainer.add(frame); center = new LayoutContainer(new FitLayout()); center.setScrollMode(Style.Scroll.NONE); add(center, new BorderLayoutData(Style.LayoutRegion.CENTER)); Hover.getInstance().setMainModule(this); module = this; exportStaticMethod(); } boolean inframe = false; public boolean isInframe() { return inframe; } public static boolean isGlobalSelectionDisabled() { return globalSelectionDisabled; } public Map<Module, Selection> getSelections() { return selections; } public void initWithLinker(EditLinker linker) { this.editLinker = linker; ((ToolbarHeader) head).removeAllTools(); if (config.getMainModuleToolbar() != null && !config.getMainModuleToolbar().getGwtToolbarItems().isEmpty()) { for (GWTJahiaToolbarItem item : config.getMainModuleToolbar().getGwtToolbarItems()) { ((ToolbarHeader) head).addItem(linker, item); } head.addTool(new ToolButton("x-tool-refresh", new SelectionListener<IconButtonEvent>() { public void componentSelected(IconButtonEvent event) { Map<String, Object> data = new HashMap<String, Object>(); data.put(Linker.REFRESH_MAIN, true); refresh(data); } })); ((ToolbarHeader) head).attachTools(); headContainer.add(head); headContainer.show(); } else { headContainer.hide(); } String location = newLocation; newLocation = null; String hash = Window.Location.getHash(); if (location == null && !hash.equals("") && hash.contains("|")) { location = hash.substring(hash.indexOf('|') + 1); } if (location == null) { location = Window.Location.getPath(); } if (location.contains("://")) { location = location.substring(location.indexOf("://") + 3); location = location.substring(location.indexOf("/")); } if (location.startsWith(JahiaGWTParameters.getContextPath() + config.getDefaultUrlMapping() + "/")) { location = location.replaceFirst(config.getDefaultUrlMapping(), config.getDefaultUrlMapping() + "frame"); } if (location.contains("frame/") && !isValidUrl(location)) { String start = location.substring(0, location.indexOf("frame/")); start = start.substring(JahiaGWTParameters.getContextPath().length()); location = location.replaceFirst(start + "frame/", config.getDefaultUrlMapping() + "frame/"); } StringBuilder url = new StringBuilder(64); url.append(URL.decode(location)); appendQueryString(url); location = url.toString(); resetFramePosition(); goToUrl(location, true, true, true); // scrollContainer.sinkEvents(); Listener<ComponentEvent> listener = new Listener<ComponentEvent>() { public void handleEvent(ComponentEvent ce) { setCtrlActive(ce); makeSelected(); } }; // on click listener scrollContainer.addListener(Events.OnClick, listener); // on double click listener scrollContainer.addListener(Events.OnDoubleClick, new EditContentEnginePopupListener(this, editLinker)); if (config.getContextMenu() != null) { // contextMenu contextMenu = new ActionContextMenu(config.getContextMenu(), editLinker) { @Override public boolean beforeShow() { makeSelected(); if (editLinker.getSelectionContext().getSingleSelection() == editLinker.getSelectionContext() .getMainNode()) { Module selectedModule = editLinker.getSelectedModule(); return selectedModule != null && selectedModule instanceof SimpleModule && super.beforeShow(); } return super.beforeShow(); } }; scrollContainer.setContextMenu(contextMenu); } infoLayers.initWithLinker(linker); } private boolean isValidUrl(String url) { return url.startsWith(JahiaGWTParameters.getContextPath() + config.getDefaultUrlMapping() + "frame/"); } private void layoutChannel() { center.removeAll(); if (activeChannel == null || "generic".equals(activeChannel.getValue()) || !config.isSupportChannelsDisplay()) { scrollContainer.setPosition(0, 0); center.setLayout(new FitLayout()); center.setScrollMode(Style.Scroll.NONE); center.add(scrollContainer); } else { int variantIndex = activeChannel.getVariants().indexOf(activeChannelVariant); if (variantIndex == -1) { variantIndex = 0; } // first let setup the device decorator layout container LayoutContainer deviceDecoratorContainer = new LayoutContainer(new AbsoluteLayout()); deviceDecoratorContainer.setBorders(false); int[] decoratorImageSize = activeChannel.getVariantDecoratorImageSize(variantIndex); if (decoratorImageSize.length == 0) { decoratorImageSize = new int[] { -1, -1 }; } deviceDecoratorContainer.setSize(decoratorImageSize[0], decoratorImageSize[1]); deviceDecoratorContainer.setStyleAttribute("margin-left", "auto"); deviceDecoratorContainer.setStyleAttribute("margin-right", "auto"); AbsoluteData deviceOuterData = new AbsoluteData(0, 0); deviceOuterData.setMargins(new Margins(0, 0, 0, 0)); if (activeChannel.getVariantDecoratorImage(variantIndex) != null) { deviceDecoratorContainer.add(new Image( JahiaGWTParameters.getContextPath() + activeChannel.getVariantDecoratorImage(variantIndex)), deviceOuterData); } int[] usableResolution = getUsableDeviceResolution(activeChannel, variantIndex); scrollContainer.setSize(usableResolution[0], usableResolution[1]); scrollContainer.setScrollMode(Style.Scroll.NONE); int[] screenPosition = null; screenPosition = activeChannel.getVariantDecoratorScreenPosition(variantIndex); if (screenPosition == null || screenPosition.length == 0) { screenPosition = new int[] { 0, 0 }; } AbsoluteData deviceData = new AbsoluteData(screenPosition[0], screenPosition[1]); deviceData.setMargins(new Margins(0, 0, 0, 0)); deviceDecoratorContainer.add(scrollContainer, deviceData); center.setLayout(new FlowLayout()); center.setScrollMode(Style.Scroll.AUTO); center.add(deviceDecoratorContainer); } // layout(); } private int[] getUsableDeviceResolution(GWTJahiaChannel activeChannel, int activeChannelIndex) { int[] usableResolution; if (activeChannel != null) { usableResolution = activeChannel.getVariantUsableResolution(activeChannelIndex); if (usableResolution.length == 0) { usableResolution = new int[] { -1, -1 }; } } else { usableResolution = new int[] { getWidth(), getHeight() - (head != null ? head.getOffsetHeight() : 0) }; } return usableResolution; } /** * select current module */ public void makeSelected() { if (selectable && !MainModule.isGlobalSelectionDisabled()) { editLinker.onModuleSelection(null); } } /** * Returns an instance of the edit linker. * * @return an instance of the edit linker */ public EditLinker getEditLinker() { return editLinker; } /** * Performs refresh of the main module, based on the provided data. * * @param data the refresh data */ public void refresh(Map<String, Object> data) { if (data != null && (data.containsKey(Linker.REFRESH_ALL) || data.containsKey(Linker.REFRESH_MAIN) || needRefresh(data))) { saveCurrentFramePosition(); boolean forceCssRefresh = false; boolean forceJavascriptRefresh = false; if (data.containsKey("node")) { GWTJahiaNode n = (GWTJahiaNode) data.get("node"); if (n != null) { forceCssRefresh = n.getNodeTypes().contains("jnt:cssFile"); forceJavascriptRefresh = n.getNodeTypes().contains("jnt:javascriptFile"); } } // we preserve the available query string during refresh of main area final String url = getUrl(path, template, activeChannel != null ? activeChannel.getValue() : null, activeChannelVariant, true); goToUrl(url, data.containsKey("forceImageRefresh"), forceCssRefresh, forceJavascriptRefresh); } } public boolean needRefresh(Map<String, Object> data) { List<String> paths = (List<String>) data.get("publishedNodes"); if (paths != null) { for (String s : paths) { List<Module> modules = ModuleHelper.getModulesByPath().get(s); if (modules != null && !modules.isEmpty()) { return true; } } } return false; } /** * Changes the frame URL to the provided one. * * @param url the URL to be used for the frame * @param forceImageRefresh should we force refresh of the images? * @param forceCssRefresh should we force refresh of the CSS files? * @param forceJavascriptRefresh should we force refresh of the JavaScript files? */ public void goToUrl(final String url, final boolean forceImageRefresh, boolean forceCssRefresh, boolean forceJavascriptRefresh) { mask(Messages.get("label.loading", "Loading..."), "x-mask-loading"); setChannelFromUrl(url); layoutChannel(); frame.setForceImageRefresh(forceImageRefresh); frame.setForceCssRefresh(forceCssRefresh); frame.setForceJavascriptRefresh(forceJavascriptRefresh); frame.setUrl(url); center.layout(true); } private void setChannelFromUrl(String url) { if (config.isSupportChannelsDisplay()) { activeChannel = editLinker.getActiveChannel(); activeChannelVariant = editLinker.getActiveChannelVariant(); Map<String, String> params = getParamsFromUrl(url); if (params.containsKey("channel")) { String channelName = params.get("channel"); for (GWTJahiaChannel gwtJahiaChannel : JahiaGWTParameters.getChannels()) { if (gwtJahiaChannel.getValue().equals(channelName)) { this.activeChannel = gwtJahiaChannel; this.activeChannelVariant = null; break; } } if (params.containsKey("variant")) { activeChannelVariant = params.get("variant"); } } } else { activeChannel = null; activeChannelVariant = null; } } private Map<String, String> getParamsFromUrl(String url) { Map<String, String> m = new HashMap<String, String>(); if (url.contains("?")) { String[] params = url.substring(url.indexOf('?') + 1).split("&"); for (String param : params) { if (param.contains("=")) { String[] v = param.split("="); m.put(v[0], v[1]); } } } return m; } public static void waitingMask(String text) { getInstance().mask(text, "x-mask-loading"); } public static void hideMask() { getInstance().unmask(); } public static void editContent(String path) { List<Module> modules = ModuleHelper.getModulesByPath().get(path); EngineLoader.showEditEngine(getInstance().getEditLinker(), modules.get(0).getNode(), null); } public String getUrl(String path, String template, String channel, String variant) { return getUrl(path, template, channel, variant, false); } public String getUrl(String path, String template, String channel, String variant, boolean preserveQueryString) { if (template != null && "default".equals(template)) { template = null; } StringBuilder url = new StringBuilder( getBaseUrl() + path + (template != null && !template.equals("") ? ("." + template) : "") + ".html"); // add channel parameters if needed if (channel != null && channel.equals("generic") && (editLinker.getActiveChannel() == null || editLinker.getActiveChannel().getValue().equals("generic"))) { channel = null; variant = null; } else if (channel == null && editLinker.getActiveChannel() != null && !editLinker.getActiveChannel().getValue().equals("generic")) { channel = editLinker.getActiveChannel().getValue(); variant = editLinker.getActiveChannelVariant(); } if (channel != null && channel.length() > 0) { url.append("?channel=").append(channel); if (variant != null && variant.length() > 0) { url.append("&variant=").append(variant); } } if (preserveQueryString) { appendQueryString(url); } return url.toString(); } /** * Appends the current URL query string (if present) to the specified one. */ private static void appendQueryString(StringBuilder url) { List<String[]> paramsToPreserve = getQueryStringParametersToPreserve(RESERVED_REQUESTPARAMETERS); if (paramsToPreserve == null || paramsToPreserve.isEmpty()) { // no query string available return; } url.append(url.indexOf("?") == -1 ? '?' : '&'); boolean first = true; for (String[] p : paramsToPreserve) { if (!first) { url.append('&'); } else { first = false; } url.append(p[0]).append('=').append(URL.encodeQueryString(p[1])); } } private static List<String[]> getQueryStringParametersToPreserve(String... reservedParameters) { String queryString = Window.Location.getQueryString(); if (queryString == null || queryString.length() == 0 || queryString.equals("?")) { // no query string available return null; } // we need to rebuild the query string to avoid duplicate entries Map<String, List<String>> params = Window.Location.getParameterMap(); if (params.isEmpty()) { // no parameters to append return null; } if (reservedParameters != null && reservedParameters.length > 0) { // filter out reserved parameters params = new HashMap<String, List<String>>(params); for (String reserved : reservedParameters) { params.remove(reserved); } } if (params.isEmpty()) { // all are filtered out: no parameters left to append return null; } List<String[]> toAppend = new ArrayList<String[]>(); for (Map.Entry<String, List<String>> p : params.entrySet()) { for (String v : p.getValue()) { toAppend.add(new String[] { p.getKey(), v }); } } return toAppend; } /** * Computes the base URL for the main module frame. * * @return the base URL for the main module frame */ public String getBaseUrl() { String baseUrl = JahiaGWTParameters.getBaseUrl(); baseUrl = baseUrl.substring(0, baseUrl.indexOf("/" + JahiaGWTParameters.getWorkspace() + "/")); baseUrl += "frame/" + JahiaGWTParameters.getWorkspace(); baseUrl += "/" + (editLinker.getLocale() == null ? JahiaGWTParameters.getLanguage() : editLinker.getLocale()); return baseUrl; } @Override public Element getInnerElement() { if (frame != null) { IFrameElement iframe = IFrameElement.as(frame.getElement()); com.google.gwt.dom.client.Element body = iframe.getContentDocument().getElementsByTagName("body") .getItem(0); return (Element) body; } return super.getInnerElement(); } public static native void setDocumentTitle(String title) /*-{ $doc.title = title; }-*/; private void refreshImages(Element element) { NodeList<com.google.gwt.dom.client.Element> elementsByTagName = element.getElementsByTagName("img"); if (elementsByTagName == null) { return; } String base = JahiaGWTParameters.getContextPath() + "/files/default/"; String suffix = "tst=" + System.currentTimeMillis(); for (int i = 0; i < elementsByTagName.getLength(); i++) { com.google.gwt.dom.client.Element el = elementsByTagName.getItem(i); String url = el.getAttribute("src"); if (url != null && url.startsWith(base)) { el.setAttribute("src", url + (url.indexOf('?') == -1 ? "?" : "&") + suffix); } } } private void refreshCSS(Element element) { NodeList<com.google.gwt.dom.client.Element> elementsByTagName = element.getElementsByTagName("link"); if (elementsByTagName == null) { return; } String base = JahiaGWTParameters.getContextPath() + "/modules/"; String suffix = "tst=" + System.currentTimeMillis(); for (int i = 0; i < elementsByTagName.getLength(); i++) { com.google.gwt.dom.client.Element el = elementsByTagName.getItem(i); String url = el.getAttribute("href"); String type = el.getAttribute("type"); if (type != null && type.equals("text/css") && url != null && url.startsWith(base)) { el.setAttribute("href", url + (url.indexOf('?') == -1 ? "?" : "&") + suffix); } } } private void refreshScripts(Element element) { NodeList<com.google.gwt.dom.client.Element> elementsByTagName = element.getElementsByTagName("script"); if (elementsByTagName == null) { return; } String base = JahiaGWTParameters.getContextPath() + "/modules/"; String suffix = "tst=" + System.currentTimeMillis(); for (int i = 0; i < elementsByTagName.getLength(); i++) { com.google.gwt.dom.client.Element el = elementsByTagName.getItem(i); String url = el.getAttribute("src"); String type = el.getAttribute("type"); if (type != null && type.equals("text/javascript") && url != null && url.startsWith(base)) { el.setAttribute("src", url + (url.indexOf('?') == -1 ? "?" : "&") + suffix); } } } @Override protected void onAfterLayout() { super.onAfterLayout(); if (needParseAfterLayout) { if (moduleMap != null) { ModuleHelper.move(moduleMap); } scrollContainer.setHeight(getHeight() - (head != null ? head.getOffsetHeight() : 0)); scrollContainer.setWidth(getWidth()); if (activeChannel != null && !"default".equals(activeChannel.getValue())) { int[] usableResolution = getUsableDeviceResolution(activeChannel, editLinker.getActiveChannelVariantIndex()); scrollContainer.setSize(usableResolution[0], usableResolution[1]); } needParseAfterLayout = false; } } protected void onResize(int width, int height) { super.onResize(width, height); scrollContainer.setHeight(getHeight() - (head != null ? head.getOffsetHeight() : 0)); scrollContainer.setWidth(getWidth()); if (activeChannel != null && !"default".equals(activeChannel.getValue())) { int[] usableResolution = getUsableDeviceResolution(activeChannel, editLinker.getActiveChannelVariantIndex()); scrollContainer.setSize(usableResolution[0], usableResolution[1]); } if (editLinker.getSelectedModule() != null) { for (Selection s : selections.values()) { s.hide(); s.show(); } } } public LayoutContainer getContainer() { return scrollContainer; } public boolean isCtrlActive() { return ctrlActive; } public void setCtrlActive(DomEvent event) { this.ctrlActive = Window.Navigator.getPlatform().toLowerCase().contains("mac") ? DOM.eventGetMetaKey(event.getEvent()) : event.isControlKey(); } public void parse(List<Element> el) { if (moduleMap != null) { ModuleHelper.deleteAll(moduleMap); List<Component> l = new ArrayList<Component>(scrollContainer.getItems()); for (Component component : l) { if (component instanceof Module) { component.removeFromParent(); } } } moduleMap = ModuleHelper.parse(this, null, el); } public String getModuleId() { return "main"; } public static void staticGoTo(String path, String template) { module.goTo(path, template, null, null); } public static void staticGoTo(String path, String template, String channel, String variant) { module.goTo(path, template, channel, variant); } public static void staticGoToUrl(String path) { module.resetFramePosition(); module.goToUrl(path, false, false, false); } public static void popState(String location, String config) { MainModule m = getInstance(); if (!config.equals(m.getConfig().getName())) { m.getEditLinker().switchConfig(m.configs.get(config), location + "##", true, true, null); } else { module.resetFramePosition(); m.goToUrl(location + "##", false, false, false); } } public void goTo(String path, String template, String channel, String variant) { resetFramePosition(); goToUrl(getUrl(path, template, channel, variant), false, false, false); } private void setHashMarker(String path) { String currentHref = Window.Location.getHref(); if (currentHref.endsWith(path)) { return; } if (supportPushState()) { if (!path.endsWith("##")) { String pathWithoutFrame = path.replaceFirst("frame/", "/"); if (Window.Location.getQueryString().contains("gwt.codesvr")) { Map<String, String> m = getParamsFromUrl(Window.Location.getQueryString()); pathWithoutFrame += (pathWithoutFrame.contains("?") ? '&' : '?') + "gwt.codesvr=" + m.get("gwt.codesvr"); } if (!pathWithoutFrame.equals(currentHref) || firstLoad) { firstLoad = false; pushState(pathWithoutFrame, path, config.getName()); } } } else { int hashPosition = currentHref.indexOf('#'); if (hashPosition > 0) { currentHref = currentHref.substring(0, hashPosition); } Window.Location.assign( currentHref + "#" + MainModule.getInstance().getConfig().getName() + "|" + URL.encode(path)); } path = path .substring(path.indexOf(JahiaGWTParameters.getContextPath() + JahiaGWTParameters.getServletPath())); if (storage != null) { String storedPath = path; if (storedPath.endsWith("##")) { storedPath = storedPath.substring(0, storedPath.length() - 2); } storage.setItem(MainModule.getInstance().getConfig().getName() + "_path", storedPath); } } public void switchLanguage(GWTJahiaLanguage language) { if (!language.getLanguage().equals(JahiaGWTParameters.getLanguage())) { editLinker.setLocale(language); Map<String, Object> data = new HashMap<String, Object>(); data.put(Linker.REFRESH_MAIN, true); data.put("event", "languageChanged"); editLinker.refresh(data); } } public void switchChannel(GWTJahiaChannel channel, String variant) { editLinker.setActiveChannelVariant(variant); editLinker.setActiveChannel(channel); if (!editLinker.isInSettingsPage()) { goTo(path, template, channel.getValue(), variant); } } public void setNodeTypes(String nodeTypes) { this.nodeTypes = nodeTypes; } public void setReferenceTypes(String referenceTypes) { this.referenceTypes = referenceTypes; } public void setMainModuleElement(Element mainModuleElement) { this.mainModuleElement = mainModuleElement; } @Override public void setNode(GWTJahiaNode node) { mainModule = this; super.setNode(node); if (node.getNodeTypes().contains("jmix:markedForDeletion")) { overlayLabel = new HTML(Messages.get("label.deleted", "Deleted")); overlayLabel.setStyleName("deleted-overlay"); overlayColorText = "#f00"; opacity = "0.4"; } if (node.isShared()) { this.setToolTip(new ToolTipConfig(Messages.get("info_important", "Important"), Messages.get("info_sharednode", "This is a shared node"))); } final List<String> types = node.getNodeTypes(); final List<String> inheritedTypes = node.getInheritedNodeTypes(); editLinker.setInSettingsPage(!types.contains("jnt:page") && !types.contains("jnt:template") && !types.contains("jnt:content") && !inheritedTypes.contains("jnt:page") && !inheritedTypes.contains("jnt:template") && !inheritedTypes.contains("jnt:content")); setDocumentTitle(Messages.get("label." + config.getName().substring(0, config.getName().length() - 4), config.getName()) + " - " + node.getDisplayName()); if (head != null) { ((ToolbarHeader) head).handleNewMainNodeLoaded(node); } editLinker.handleNewMainNodeLoaded(); if (head != null && head instanceof ToolbarHeader) { ((ToolbarHeader) head).handleNewMainNodeLoaded(node); } if (overlayLabel != null) { DOM.setStyleAttribute(mainModuleElement, "position", "relative"); mainModuleElement.getParentElement().insertFirst(overlayLabel.getElement()); overlayLabel.setHeight("100%"); overlayLabel.setWidth("100%"); DOM.setStyleAttribute(mainModuleElement, "opacity", opacity); layout(); } } public GWTEditConfiguration getConfig() { return config; } /** * Set edit mode configuration and location. * A path can be explicitly specified. * It can also be stored and recalled from the HTML5 web storage, if available. * * @param config * @param newPath */ public void setConfig(GWTEditConfiguration config, String newPath) { JahiaGWTParameters.changeServletMapping(this.config.getDefaultUrlMapping(), config.getDefaultUrlMapping()); activeChannel = null; activeChannelVariant = null; if (newPath != null) { newLocation = newPath; } else { newLocation = frame.getCurrentFrameUrl().replaceFirst(this.config.getDefaultUrlMapping(), config.getDefaultUrlMapping()); } this.config = config; configs.put(this.config.getName(), this.config); } public void handleNewModuleSelection(Module selectedModule) { Selection l = new Selection(selectedModule); if (!ctrlActive || selectedModule == null) { for (Selection s : selections.values()) { s.hide(); } selections.clear(); } if (selectedModule != null && !(selectedModule instanceof MainModule)) { selections.put(selectedModule, l); l.select(); l.show(); } if (head != null) { ((ToolbarHeader) head).handleNewLinkerSelection(); } l.layout(); } public void handleNewMainSelection(String path, String template) { if (storage != null) { storage.setItem(MainModule.getInstance().getConfig().getName() + "_nodePath", path); } Map<String, List<String>> params = null; if ((this.path != null ? this.path.equals(path) : path == null) && (this.template != null ? this.template.equals(template) : template == null) && (this.moduleParams != null ? this.moduleParams.equals(params) : params == null)) { return; } this.path = path; this.template = template; moduleParams = params; if (head != null) { ((ToolbarHeader) head).handleNewLinkerSelection(); } } public void setInfoLayer(String key, boolean value) { if (value) { activeLayers.put(key, value); } else { activeLayers.remove(key); } refreshInfoLayer(); } public void refreshInfoLayer() { infoLayers.removeAll(); if (!activeLayers.isEmpty()) { infoLayers.setMainModule(this); List<Module> modules = ModuleHelper.getModules(); String lastUnpublished = null; if (modules != null) { for (Module m : modules) { if (m instanceof AreaModule || !m.getPath().endsWith("*")) { GWTJahiaNode currentNode = m.getNode(); if (currentNode != null) { List<LayoutContainer> images = new ArrayList<LayoutContainer>(); if (activeLayers.containsKey("acl") && currentNode.isHasAcl()) { AbstractImagePrototype icon = ToolbarIconProvider.getInstance() .getIcon("viewACLStatus"); LayoutContainer layoutContainer = new LayoutContainer(new CenterLayout()); layoutContainer.add(icon.createImage()); images.add(layoutContainer); } if (activeLayers.containsKey("publication")) { GWTJahiaPublicationInfo info = currentNode.getAggregatedPublicationInfo(); if (lastUnpublished == null || !currentNode.getPath().startsWith(lastUnpublished)) { if (info.isLocked()) { AbstractImagePrototype icon = ToolbarIconProvider.getInstance() .getIcon("publication/locked"); LayoutContainer layoutContainer = new LayoutContainer(new CenterLayout()); layoutContainer.add(icon.createImage()); images.add(layoutContainer); } if (info.getStatus() == GWTJahiaPublicationInfo.NOT_PUBLISHED || info.getStatus() == GWTJahiaPublicationInfo.UNPUBLISHED) { lastUnpublished = currentNode.getPath(); if (info.getStatus() == GWTJahiaPublicationInfo.UNPUBLISHED) { AbstractImagePrototype icon = ToolbarIconProvider.getInstance() .getIcon("publication/unpublished"); LayoutContainer layoutContainer = new LayoutContainer( new CenterLayout()); layoutContainer.add(icon.createImage()); images.add(layoutContainer); } else { AbstractImagePrototype icon = ToolbarIconProvider.getInstance() .getIcon("publication/notpublished"); LayoutContainer layoutContainer = new LayoutContainer( new CenterLayout()); layoutContainer.add(icon.createImage()); images.add(layoutContainer); } } else if (info.getStatus() == GWTJahiaPublicationInfo.MODIFIED) { AbstractImagePrototype icon = ToolbarIconProvider.getInstance() .getIcon("publication/modified"); LayoutContainer layoutContainer = new LayoutContainer(new CenterLayout()); layoutContainer.add(icon.createImage()); images.add(layoutContainer); } else if (info .getStatus() == GWTJahiaPublicationInfo.MANDATORY_LANGUAGE_UNPUBLISHABLE) { AbstractImagePrototype icon = ToolbarIconProvider.getInstance() .getIcon("publication/mandatorylanguageunpublishable"); LayoutContainer layoutContainer = new LayoutContainer(new CenterLayout()); layoutContainer.add(icon.createImage()); images.add(layoutContainer); } else if (info .getStatus() == GWTJahiaPublicationInfo.MANDATORY_LANGUAGE_VALID) { AbstractImagePrototype icon = ToolbarIconProvider.getInstance() .getIcon("publication/mandatorylanguagevalid"); LayoutContainer layoutContainer = new LayoutContainer(new CenterLayout()); layoutContainer.add(icon.createImage()); images.add(layoutContainer); } } } if (activeLayers.containsKey("visibility")) { Map<GWTJahiaNode, ModelData> visibility = currentNode.getVisibilityInfo(); if (!visibility.isEmpty()) { if (currentNode.isVisible()) { AbstractImagePrototype icon = ToolbarIconProvider.getInstance() .getIcon("visibilityStatusGreen"); Image image = icon.createImage(); LayoutContainer layoutContainer = new LayoutContainer(new CenterLayout()); layoutContainer.add(image); Set<Map.Entry<GWTJahiaNode, ModelData>> entries = visibility.entrySet(); StringBuilder toolTip = new StringBuilder(); for (Map.Entry<GWTJahiaNode, ModelData> entry : entries) { if (toolTip.length() > 0) { toolTip.append("<br/>"); } XTemplate tpl = XTemplate .create((String) entry.getValue().get("xtemplate")); toolTip.append(tpl.applyTemplate( com.extjs.gxt.ui.client.util.Util.getJsObject(entry.getKey()))); } layoutContainer.setToolTip(toolTip.toString()); images.add(layoutContainer); } else { AbstractImagePrototype icon = ToolbarIconProvider.getInstance() .getIcon("visibilityStatusRed"); LayoutContainer layoutContainer = new LayoutContainer(new CenterLayout()); layoutContainer.add(icon.createImage()); Set<Map.Entry<GWTJahiaNode, ModelData>> entries = visibility.entrySet(); StringBuilder toolTip = new StringBuilder(); for (Map.Entry<GWTJahiaNode, ModelData> entry : entries) { if (toolTip.length() > 0) { toolTip.append("<br/>"); } XTemplate tpl = XTemplate .create((String) entry.getValue().get("xtemplate")); toolTip.append(tpl.applyTemplate( com.extjs.gxt.ui.client.util.Util.getJsObject(entry.getKey()))); } layoutContainer.setToolTip(toolTip.toString()); images.add(layoutContainer); } } } if (!images.isEmpty()) { infoLayers.addInfoLayer(m, images, null, true, "1"); } } } } } } } public boolean isDraggable() { return false; } public static MainModule getInstance() { return module; } public static native void exportStaticMethod() /*-{ $wnd.goTo = function (path, template, params) { @org.jahia.ajax.gwt.client.widget.edit.mainarea.MainModule::staticGoTo(Ljava/lang/String;Ljava/lang/String;)(path, template); } $wnd.goToUrl = function (path, template, params) { @org.jahia.ajax.gwt.client.widget.edit.mainarea.MainModule::staticGoToUrl(Ljava/lang/String;)(path); } $wnd.addEventListener("popstate", function (event) { if (event.state) { @org.jahia.ajax.gwt.client.widget.edit.mainarea.MainModule::popState(Ljava/lang/String;Ljava/lang/String;)(event.state.location, event.state.config); } }); $wnd.waitingMask = function (text) { @org.jahia.ajax.gwt.client.widget.edit.mainarea.MainModule::waitingMask(Ljava/lang/String;)(text); }; $wnd.hideMask = function () { @org.jahia.ajax.gwt.client.widget.edit.mainarea.MainModule::hideMask()(); }; $wnd.editContent = function (path) { @org.jahia.ajax.gwt.client.widget.edit.mainarea.MainModule::editContent(Ljava/lang/String;)(path); }; $wnd.disableGlobalSelection = function (value) { @org.jahia.ajax.gwt.client.widget.edit.mainarea.MainModule::globalSelectionDisabled = value; }; }-*/; public InfoLayers getInfoLayers() { return infoLayers; } private native boolean supportPushState() /*-{ if ($wnd.history && $wnd.history.pushState) { return true; } else { return false; } }-*/; private native boolean pushState(String path, String location, String config) /*-{ var state = {location: location, config: config}; if ($wnd.history.state) { $wnd.history.pushState(state, null, path); } else { $wnd.history.replaceState(state, null, path); } return true; }-*/; public void goToExternalUrl(String url) { mask(Messages.get("label.loading", "Loading..."), "x-mask-loading"); frame.setExternalUrl(url); } private void parseFrameContent(boolean forceImageRefresh, boolean forceCssRefresh, boolean forceJavascriptRefresh) { try { frameError = null; final IFrameElement iframe = IFrameElement.as(frame.getElement()); Document contentDocument = iframe.getContentDocument(); Element body = (Element) contentDocument.getElementsByTagName("body").getItem(0); Element head = (Element) contentDocument.getElementsByTagName("head").getItem(0); setHashMarker(frame.getCurrentFrameUrl()); if (forceImageRefresh) { refreshImages(body); } if (head != null) { if (forceCssRefresh) { refreshCSS(head); } if (forceJavascriptRefresh) { refreshScripts(head); } } Hover.getInstance().removeAll(); List<Element> el = null; List<Element> elBody = null; if ("true".equals(body.getAttribute("jahia-parse-html"))) { Element innerElement = getInnerElement(); elBody = ModuleHelper.getAllJahiaTypedElementsRec(body); if (body.equals(innerElement)) { el = elBody; } else { el = ModuleHelper.getAllJahiaTypedElementsRec(getInnerElement()); } } else if (body.getAttribute("jahia-error-code") != null && !"".equals(body.getAttribute("jahia-error-code"))) { frameError = body.getAttribute("jahia-error-code"); } else { NodeList<com.google.gwt.dom.client.Element> el1 = body.getElementsByTagName("div"); int i = 0; Element e = null; while (i < el1.getLength()) { e = (Element) el1.getItem(i); if ("mainmodule".equals(e.getAttribute(ModuleHelper.JAHIA_TYPE))) { el = Arrays.asList(e); elBody = Arrays.asList(e); break; } i++; } } if (contextMenu != null) { contextMenu.hide(); } if (el != null && elBody != null) { ModuleHelper.tranformLinks((Element) contentDocument.getDocumentElement()); ModuleHelper.initAllModules(MainModule.this, body, el, elBody, config); editLinker.getSidePanel().enable(); } else { // if body empty, this is not a jahia page path = ""; // clear side panel editLinker.getSidePanel().disable(); } editLinker.getMainModule().unmask(); needParseAfterLayout = true; layout(); } catch (Exception e) { Log.error("Error in EditFrame: " + e.getMessage(), e); } } // reset the frame position to its initial value public void resetFramePosition() { framePosition = new Point(0, 0); } // save the current position of the frame public Point saveCurrentFramePosition() { if (!GXT.isIE10) { framePosition.x = IFrameElement.as(frame.getElement()).getContentDocument().getScrollLeft(); framePosition.y = IFrameElement.as(frame.getElement()).getContentDocument().getScrollTop(); } else { framePosition.x = getIE10FrameLeft(); framePosition.y = getIE10FrameTop(); } return framePosition; } private class EditFrame extends Frame { private String url = null; private boolean forceImageRefresh = false; private boolean forceCssRefresh = false; private boolean forceJavascriptRefresh = false; private EditFrame() { } public void onBrowserEvent(Event event) { try { if (event.getTypeInt() == Event.ONLOAD) { if (isValidUrl(url)) { final IFrameElement iframe = IFrameElement.as(frame.getElement()); Document contentDocument = iframe.getContentDocument(); parseFrameContent(forceImageRefresh, forceCssRefresh, forceJavascriptRefresh); DOM.sinkEvents((Element) contentDocument.getDocumentElement(), Event.ONMOUSEMOVE + Event.ONMOUSEUP + Event.ONCONTEXTMENU + Event.ONCLICK + Event.ONMOUSEDOWN); DOM.setEventListener((Element) contentDocument.getDocumentElement(), new EventListener() { public void onBrowserEvent(Event event) { if (event.getTypeInt() == Event.ONMOUSEMOVE || event.getTypeInt() == Event.ONMOUSEUP || event.getTypeInt() == Event.ONMOUSEDOWN) { inframe = true; Event.fireNativePreviewEvent(event); inframe = false; } else { GWT.log("event:" + event.getTypeInt()); scrollContainer.onBrowserEvent(event); } } }); Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() { @Override public void execute() { if (frameError != null && !frameErrorRedirect) { frameErrorRedirect = true; setUrl(getBaseUrl() + config.getDefaultLocation()); } else { frameErrorRedirect = false; onGWTFrameReady(iframe); moveToSavePosition(); // once pgae rendered, reset the frame position resetFramePosition(); } } }); } else { editLinker.getMainModule().unmask(); } } } catch (Exception e) { Log.error("Error in EditFrame: " + e.getMessage(), e); } } private String getCurrentFrameUrl() { return getFrameUrl(IFrameElement.as(frame.getElement())); } @Override public void setUrl(String url) { url = getPathFromUrl(url); if (isValidUrl(url)) { if (getElement() != null) { this.url = url; super.setUrl(url); } else { this.url = url; } } } public void setExternalUrl(String url) { if (isAttached()) { this.url = url; super.setUrl(url); } else { this.url = url; } } public void setForceImageRefresh(boolean forceImageRefresh) { this.forceImageRefresh = forceImageRefresh; } public void setForceCssRefresh(boolean forceCssRefresh) { this.forceCssRefresh = forceCssRefresh; } public void setForceJavascriptRefresh(boolean forceJavascriptRefresh) { this.forceJavascriptRefresh = forceJavascriptRefresh; } @Override protected void onAttach() { super.onAttach(); IFrameElement iframe = IFrameElement.as(frame.getElement()); iframe.setAttribute("frameborder", "0"); // iframe.setAttribute("sandbox","allows-scripts"); if (url != null && !super.getUrl().endsWith(URL.encode(url))) { super.setUrl(url); } } public final native String getFrameUrl(IFrameElement iFrameElement) /*-{ // This is known to work on all modern browsers. return iFrameElement.contentWindow.location.href; }-*/; public final native String onGWTFrameReady(IFrameElement iFrameElement) /*-{ if (iFrameElement.contentWindow.onGWTFrameLoaded != null) { var onFrameLoaded = iFrameElement.contentWindow.onGWTFrameLoaded; for (var i = 0; i < onFrameLoaded.length; i++) { onFrameLoaded[i]() } iFrameElement.contentWindow.onGWTFrameLoaded = []; } }-*/; } private String getPathFromUrl(String url) { if (url.contains("://")) { url = url.substring(url.indexOf("://") + 3); url = url.substring(url.indexOf('/')); } return url; } public String getTemplate() { return template; } public final int getIE10FrameTop() { return getIE10FrameTop(IFrameElement.as(frame.getElement())); } public final int getIE10FrameLeft() { return getIE10FrameLeft(IFrameElement.as(frame.getElement())); } public final void moveToSavePosition() { scrollTo(IFrameElement.as(frame.getElement()), framePosition.x, framePosition.y); } public final native int getIE10FrameTop(IFrameElement iFrameElement) /*-{ if (iFrameElement.contentWindow.document.documentElement != null) { return iFrameElement.contentWindow.document.documentElement.scrollTop; } }-*/; public final native int getIE10FrameLeft(IFrameElement iFrameElement) /*-{ if (iFrameElement.contentWindow.document.documentElement != null) { return iFrameElement.contentWindow.document.documentElement.scrollLeft; } }-*/; public final native int scrollTo(IFrameElement iFrameElement, int x, int y) /*-{ iFrameElement.contentWindow.scrollTo(x, y); }-*/; }