// Copyright 2012 Google Inc. All Rights Reserved. // // 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 com.google.collide.client.code.debugging; import com.google.collide.client.ui.tooltip.Tooltip; import com.google.collide.client.util.CssUtils; import com.google.collide.client.util.Elements; import com.google.collide.mvp.CompositeView; import com.google.collide.mvp.UiComponent; import com.google.common.annotations.VisibleForTesting; import com.google.gwt.resources.client.ClientBundle; import com.google.gwt.resources.client.CssResource; import elemental.events.CustomEvent; import elemental.events.Event; import elemental.events.EventListener; import elemental.html.Element; import elemental.html.IFrameElement; import elemental.html.LinkElement; import elemental.html.ScriptElement; /** * Dom Inspector UI. * */ public class DomInspector extends UiComponent<DomInspector.View> { private static final String DEBUGGER_CUSTOM_MESSAGE_REQUEST = "DebuggerCustomMessageRequest"; private static final String DEBUGGER_CUSTOM_MESSAGE_RESPONSE = "DebuggerCustomMessageResponse"; public interface Css extends CssResource { String root(); String domIframe(); } interface Resources extends ClientBundle, Tooltip.Resources { @Source("DomInspector.css") Css workspaceEditorDomInspectorCss(); } /** * The view of the Dom Inspector. */ static class View extends CompositeView<ViewEvents> { private final Css css; private final IFrameElement domInspectorIframe; private final EventListener customDebuggerMessageRequestListener = new EventListener() { @Override public void handleEvent(Event evt) { Object detail = ((CustomEvent) evt).getDetail(); if (detail != null) { getDelegate().onCustomMessageRequest(detail.toString()); } } }; View(Resources resources) { css = resources.workspaceEditorDomInspectorCss(); domInspectorIframe = Elements.createIFrameElement(css.domIframe()); domInspectorIframe.setOnLoad(new EventListener() { @Override public void handleEvent(Event evt) { onDomInspectorIframeLoaded(); } }); CssUtils.setDisplayVisibility(domInspectorIframe, false); Element rootElement = Elements.createDivElement(css.root()); rootElement.appendChild(domInspectorIframe); setElement(rootElement); } private void show() { if (!isVisible()) { CssUtils.setDisplayVisibility(domInspectorIframe, true); // Ping with an empty message to re-initialize. sendCustomMessageResponseToInspector(""); } } private void hide() { CssUtils.setDisplayVisibility(domInspectorIframe, false); } private boolean isVisible() { return CssUtils.isVisible(domInspectorIframe); } private void onDomInspectorIframeLoaded() { // <link href="test.css" rel="stylesheet" type="text/css"> LinkElement linkElement = Elements.getDocument().createLinkElement(); linkElement.setRel("stylesheet"); linkElement.setType("text/css"); linkElement.setHref("/static/dominspector_css_compiled.css"); Elements.getHead(domInspectorIframe.getContentDocument()).appendChild(linkElement); ScriptElement scriptElement = Elements.getDocument().createScriptElement(); scriptElement.setSrc("/static/dominspector_js_compiled.js"); Elements.getBody(domInspectorIframe.getContentDocument()).appendChild(scriptElement); domInspectorIframe.getContentWindow().addEventListener( DEBUGGER_CUSTOM_MESSAGE_REQUEST, customDebuggerMessageRequestListener, false); } private void sendCustomMessageResponseToInspector(String response) { if (domInspectorIframe.getContentDocument() != null && domInspectorIframe.getContentWindow() != null) { CustomEvent evt = (CustomEvent) domInspectorIframe.getContentDocument().createEvent( "CustomEvent"); evt.initCustomEvent(DEBUGGER_CUSTOM_MESSAGE_RESPONSE, true, true, response); domInspectorIframe.getContentWindow().dispatchEvent(evt); } } } /** * The view events. */ private interface ViewEvents { void onCustomMessageRequest(String message); } static DomInspector create(View view, DebuggerState debuggerState) { return new DomInspector(view, debuggerState); } private final DebuggerState debuggerState; private final DebuggerState.CustomMessageListener customDebuggerMessageResponseListener = new DebuggerState.CustomMessageListener() { @Override public void onCustomMessageResponse(String response) { getView().sendCustomMessageResponseToInspector(response); } }; @VisibleForTesting DomInspector(View view, DebuggerState debuggerState) { super(view); this.debuggerState = debuggerState; debuggerState.getCustomMessageListenerRegistrar().add(customDebuggerMessageResponseListener); view.setDelegate(new ViewEvents() { @Override public void onCustomMessageRequest(String message) { DomInspector.this.debuggerState.sendCustomMessage(message); } }); } void show() { getView().show(); } void hide() { getView().hide(); } }