/******************************************************************************* * Copyright (c) 2012 Google, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Google, Inc. - initial API and implementation *******************************************************************************/ package com.windowtester.eclipse.ui.inspector; import org.eclipse.jface.dialogs.PopupDialog; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.forms.widgets.ScrolledForm; import org.eclipse.ui.forms.widgets.TableWrapLayout; import com.windowtester.eclipse.ui.dialogs.Mover; import com.windowtester.eclipse.ui.usage.ProfiledAction; import com.windowtester.internal.runtime.Platform; import com.windowtester.recorder.event.user.IWidgetDescription; import com.windowtester.runtime.swt.internal.display.DisplayExec; public class InspectorPopup extends PopupDialog { public static interface PopupClosedCallback { void popupClosed(); } private static final PopupClosedCallback NULL_CALLBACK = new PopupClosedCallback() { public void popupClosed() { //no-op }; }; private class CloseAction extends ProfiledAction { public ImageDescriptor getImageDescriptor() { if (!Platform.isRunning()) { Image image = ImageManager.getImage("delete.gif"); if (image == null) return null; return ImageDescriptor.createFromImage(image); } return PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_TOOL_DELETE); } public String getToolTipText() { return "Close"; } /* (non-Javadoc) * @see com.windowtester.eclipse.ui.usage.ProfiledAction#doRun() */ public void doRun() { close(); } } private static final String FOOTER_TEXT = null; private Composite composite; private final InspectorFormToolkit toolkit; private ScrolledForm form; private final IWidgetDescription widget; private final PopupClosedCallback callback; private Mover mover; @SuppressWarnings("deprecation") public InspectorPopup(Shell parent, IWidgetDescription widget, PopupClosedCallback callback) { super(parent, SWT.ON_TOP, false, false, true, false, null /*title is handed in form */, FOOTER_TEXT); this.widget = widget; this.toolkit = new InspectorFormToolkit(); this.callback = callback != null ? callback : NULL_CALLBACK; } public InspectorPopup(Shell parent, IWidgetDescription widget) { this(parent, widget, NULL_CALLBACK); } /* (non-Javadoc) * @see org.eclipse.jface.dialogs.PopupDialog#getInitialLocation(org.eclipse.swt.graphics.Point) */ protected Point getInitialLocation(Point initialSize) { Point widgetLocation = widget.getHoverPoint(); if (widgetLocation == null) widgetLocation = Display.getDefault().getCursorLocation(); return new Point(widgetLocation.x + 10, widgetLocation.y + 10); } /* (non-Javadoc) * @see org.eclipse.jface.window.Window#create() */ public void create() { super.create(); addListeners(); startCloseTimer(); } private void startCloseTimer() { DisplayExec.sync(new Runnable() { Runnable runnable = new Runnable() { public void run() { Display display = Display.getDefault(); try { Point cursorLocation = display.getCursorLocation(); Shell shell = InspectorPopup.this.getShell(); if (shell == null) { doClose(display); return; } Rectangle bounds = shell.getBounds(); if (bounds == null) { doClose(display); return; } if (bounds.contains(cursorLocation) || mover.isMoving() ) { startTimer(display); } else { doClose(display); } } catch (Throwable th) { //<--- safety: just close doClose(display); } } private void startTimer(Display display) { display.timerExec(2000, this); } private void doClose(Display display) { display.timerExec(-1, this); InspectorPopup.this.close(); } }; public void run() { Display.getDefault().timerExec(3000, runnable); } }); } /* (non-Javadoc) * @see org.eclipse.jface.dialogs.PopupDialog#createContents(org.eclipse.swt.widgets.Composite) */ protected Control createContents(Composite parent) { getShell().setBackground(getShell().getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY)); initializeBounds(); return createDialogArea(parent); } private void addListeners() { mover = Mover.forShell(getShell()); form.getForm().getHead().addMouseListener(mover); } /* (non-Javadoc) * @see org.eclipse.jface.dialogs.PopupDialog#createDialogArea(org.eclipse.swt.widgets.Composite) */ protected Control createDialogArea(Composite parent) { initializeComposite(parent); initializeForm(); initializeSections(); parent.pack(); return composite; } private void initializeSections() { new LocatorSection().addTo(widget, form, toolkit); new PropertiesSection().addTo(widget, form, toolkit); //TODO: consider putting this in menu? //new DebugSection().addTo(widget, form, toolkit); } private void initializeComposite(Composite parent) { this.composite = (Composite) super.createDialogArea(parent); } private void initializeForm() { form = toolkit.createScrolledForm(composite); /* $codepro.preprocessor.if version >= 3.3 $ */ toolkit.decorateFormHeading(form.getForm()); /* $codepro.preprocessor.endif $ */ form.setText(WidgetDescriptionLabelProvider.getDescription(widget)); Image image = ImageManager.getImage("spy.gif"); if (!Platform.isRunning()) image = null; //workaround to address strange initialization ordering issues. form.setImage(image); addToolbarActions(); addMenuActions(); form.getToolBarManager().update(true); TableWrapLayout layout = new TableWrapLayout(); layout.leftMargin = 10; layout.rightMargin = 10; layout.topMargin = 10; layout.verticalSpacing = 10; form.getBody().setLayout(layout); } private void addMenuActions() { // TODO how to do this? } private void addToolbarActions() { form.getToolBarManager().add(new CloseAction()); } public boolean contains(Point point) { Shell shell = getShell(); if (shell == null) return false; Rectangle bounds = shell.getBounds(); if (bounds == null) return false; return bounds.contains(point); } /* (non-Javadoc) * @see org.eclipse.jface.dialogs.PopupDialog#close() */ public boolean close() { System.out.println("InspectorPopup.close()"); boolean closed = super.close(); callback.popupClosed(); return closed; } }