/*! * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software * Foundation. * * You should have received a copy of the GNU Lesser General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html * or from the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * 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 Lesser General Public License for more details. * * Copyright (c) 2002-2013 Pentaho Corporation.. All rights reserved. */ package org.pentaho.mantle.client.solutionbrowser.tabs; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.IFrameElement; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.FormPanel; import com.google.gwt.user.client.ui.NamedFrame; import com.google.gwt.user.client.ui.VerticalPanel; import org.pentaho.mantle.client.objects.SolutionFileInfo; import org.pentaho.mantle.client.solutionbrowser.filelist.FileItem; import java.util.Set; import java.util.Stack; public class IFrameTabPanel extends VerticalPanel { private String url; private String deepLinkUrl; private String name; private CustomFrame frame; private SolutionFileInfo fileInfo; private FormPanel form; private boolean saveEnabled, editContentEnabled, editContentSelected; // We hold onto a Javascript object that gets various notifications of PUC events. // (edit content button clicked, etc.) protected JavaScriptObject jsCallback; private Set<String> overlayIds; public IFrameTabPanel() { this.name = "" + System.currentTimeMillis(); this.frame = new CustomFrame( name, "about:blank" ); add( frame ); } public IFrameTabPanel( String name ) { this.name = name; frame = new CustomFrame( name ); frame.getElement().setAttribute( "id", name + System.currentTimeMillis() ); //$NON-NLS-1$ frame.setWidth( "100%" ); //$NON-NLS-1$ frame.setHeight( "100%" ); //$NON-NLS-1$ add( frame ); } public void setName( String name ) { this.name = name; frame.getElement().setAttribute( "name", name ); frame.getElement().setAttribute( "id", name + System.currentTimeMillis() ); //$NON-NLS-1$ } public void reload() { if ( form != null ) { form.submit(); } else { // frame.setUrl(getCurrentUrl()); reloadFrame( frame.getElement() ); } } public native void reloadFrame( Element frameElement ) /*-{ frameElement.contentWindow.location.reload(); }-*/; public void back() { frame.back(); } public void setFileInfo( SolutionFileInfo info ) { fileInfo = info; } public void setFileInfo( FileItem item ) { SolutionFileInfo fileInfo = new SolutionFileInfo(); fileInfo.setName( item.getName() ); fileInfo.setPath( item.getPath() ); setFileInfo( fileInfo ); } public SolutionFileInfo getFileInfo() { return fileInfo; } /* * frame.getUrl returns the original URL, but not the current one. This method accesses the DOM directly to get * that URL */ private String getCurrentUrl() { return IFrameElement.as( this.frame.getElement() ).getContentDocument().getURL(); } public String getUrl() { return url; } public void setUrl( String url ) { this.url = url; setSaveEnabled( url.contains( "analysisview.xaction" ) ); //$NON-NLS-1$ setUrl( frame.getElement(), url ); } public static native void setUrl( Element f, String url )/*-{ try{ f.contentWindow.location.href = url; } catch(e){ // XSS error or frame not yet on document, set attribute instead f.src = url; } }-*/; public void openTabInNewWindow() { Window.open( getCurrentUrl(), "_blank", "" ); //$NON-NLS-1$ //$NON-NLS-2$ } public NamedFrame getFrame() { return frame; } public void setFrame( CustomFrame frame ) { this.frame = frame; } public FormPanel getForm() { return form; } public void setForm( FormPanel form ) { this.form = form; } public class CustomFrame extends NamedFrame { private boolean ignoreNextHistoryAdd = false; private Stack<String> history = new Stack<String>(); private static final String ALLOW_TRANSPARENCY_ATTRIBUTE = "allowTransparency"; private CustomFrame( String name ) { super( name ); this.getElement().setAttribute( ALLOW_TRANSPARENCY_ATTRIBUTE, "true" ); } private CustomFrame( String name, String url ) { super( name ); setUrl( url ); IFrameTabPanel.setUrl( this.getElement(), url ); this.getElement().setAttribute( ALLOW_TRANSPARENCY_ATTRIBUTE, "true" ); } public void back() { if ( !history.empty() ) { ignoreNextHistoryAdd = true; IFrameTabPanel.setUrl( frame.getElement(), history.pop() ); } } public void addHistory( String url ) { if ( ignoreNextHistoryAdd || url.equals( "about:blank" ) ) { //$NON-NLS-1$ ignoreNextHistoryAdd = false; return; } history.add( url ); } @Override protected void onAttach() { super.onAttach(); attachEventListeners( frame.getElement(), this ); } public native void removeEventListeners( Element ele ) /*-{ var wind = ele.contentWindow; try { wind.onmouseup = null; wind.onmousedown = null; wind.onmousemove = null; wind.onunload = null; } catch(e) { // Swallow. Most probably due to Same Domain Origin Policy. } $wnd.watchWindow = null; }-*/; public native void attachEventListeners( Element ele, CustomFrame frame ) /*-{ var iwind = ele.contentWindow; //IFrame's window instance var funct = function(event){ event = iwind.parent.translateInnerMouseEvent(ele, event); iwind.parent.sendMouseEvent(event); } // Hooks up mouse and unload events $wnd.hookEvents = function(wind){ try{ if(wind == null){ wind = $wnd.watchWindow } wind.onmouseup = funct; wind.onmousedown = funct; wind.onmousemove = funct; wind.onunload = unloader; wind.mantleEventsIn = true; $wnd.watchWindow = null; } catch(e){ //You're most likely here because of Cross-site scripting permissions... consuming } } // IFrame URL watching code // Called on iFrame unload, calls containing Window to start monitoring it for Url change var unloader = function(event){ //CHECKSTYLE IGNORE LineLength FOR NEXT 1 LINES frame.@org.pentaho.mantle.client.solutionbrowser.tabs.IFrameTabPanel$CustomFrame::addHistory(Ljava/lang/String;)(iwind.location.href); $wnd.startIFrameWatcher(iwind); } // Starts the watching loop. $wnd.startIFrameWatcher = function(wind){ $wnd.watchWindow = wind; $wnd.setTimeout("rehookEventsTimer()", 300); } // loop that's started when an iFrame unloads, when the url changes it adds back in the hooks $wnd.rehookEventsTimer = function(){ try { if($wnd.watchWindow.mantleEventsIn == undefined){ //location changed hook back up event interceptors $wnd.setTimeout("hookEvents()", 300); } else { $wnd.setTimeout("rehookEventsTimer()", 300); } } catch(e) { // Swallow. Most probably due to Same Domain Origin Policy. } } // Scope helper funct. function rehookEventsTimer(){ $wnd.rehookEventsTimer(); } //Hook up the mouse and unload event handlers for iFrame being created $wnd.hookEvents(iwind); }-*/; } public boolean isSaveEnabled() { return saveEnabled; } public void setSaveEnabled( boolean enabled ) { saveEnabled = enabled; } public Set<String> getOverlayIds() { return overlayIds; } public void addOverlay( String id ) { overlayIds.add( id ); } public void setEditEnabled( boolean enable ) { this.editContentEnabled = enable; } public boolean isEditEnabled() { return editContentEnabled; } public void setEditSelected( boolean selected ) { this.editContentSelected = selected; } public boolean isEditSelected() { return this.editContentSelected; } public boolean isPrintVisible() { return checkFrameWindowPrintVisible( frame.getElement() ); } private native boolean checkFrameWindowPrintVisible( Element frame )/*-{ try { return frame.contentWindow.printVisible; } catch (e) { } return false; }-*/; public void setId( String id ) { frame.getElement().setAttribute( "id", id ); //$NON-NLS-1$ } public String getDeepLinkUrl() { return deepLinkUrl; } public void setDeepLinkUrl( String deepLinkUrl ) { this.deepLinkUrl = deepLinkUrl; } }