| /* |
| * Copyright 2008 Google Inc. |
| * |
| * 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.gwt.dev.shell; |
| |
| import com.google.gwt.core.ext.TreeLogger; |
| import com.google.gwt.dev.shell.log.SwingLoggerPanel; |
| import com.google.gwt.dev.util.BrowserLauncher; |
| |
| import java.awt.BorderLayout; |
| import java.awt.Color; |
| import java.awt.HeadlessException; |
| import java.awt.datatransfer.Clipboard; |
| import java.awt.datatransfer.StringSelection; |
| import java.awt.event.ActionEvent; |
| import java.awt.event.ActionListener; |
| import java.awt.event.KeyEvent; |
| import java.io.File; |
| import java.io.IOException; |
| import java.net.URISyntaxException; |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Map; |
| |
| import javax.swing.BorderFactory; |
| import javax.swing.JButton; |
| import javax.swing.JComboBox; |
| import javax.swing.JLabel; |
| import javax.swing.JPanel; |
| |
| /** |
| * Top-level window for the Swing DevMode UI. |
| */ |
| public class ShellMainWindow extends JPanel { |
| |
| /** |
| * Launches a URL by copying it to the clipboard. |
| */ |
| private class CopyToClipboardLauncher extends LaunchMethod { |
| |
| public CopyToClipboardLauncher() { |
| super("Copy URL to clipboard"); |
| } |
| |
| @Override |
| public void launchUrl(URL url) { |
| if (getLogger().isLoggable(TreeLogger.INFO)) { |
| getLogger().log(TreeLogger.INFO, "Paste " + url.toExternalForm() |
| + " into a browser"); |
| } |
| // is it better to use SwingUtilities2.canAccessSystemClipboard() here? |
| Throwable caught = null; |
| try { |
| Clipboard clipboard = logWindow.getToolkit().getSystemClipboard(); |
| StringSelection selection = new StringSelection(url.toExternalForm()); |
| clipboard.setContents(selection, selection); |
| return; |
| } catch (SecurityException e) { |
| caught = e; |
| } catch (HeadlessException e) { |
| caught = e; |
| } |
| getLogger().log(TreeLogger.ERROR, "Unable to copy URL to clipboard", |
| caught); |
| } |
| } |
| |
| /** |
| * Launches a URL using the default browser, as defined by |
| * {@link BrowserLauncher}. |
| */ |
| private class DefaultBrowserLauncher extends LaunchMethod { |
| |
| public DefaultBrowserLauncher() { |
| super("Default browser"); |
| } |
| |
| @Override |
| public void launchUrl(URL url) { |
| Throwable caught = null; |
| try { |
| BrowserLauncher.browse(url.toExternalForm()); |
| return; |
| } catch (IOException e) { |
| caught = e; |
| } catch (URISyntaxException e) { |
| caught = e; |
| } |
| TreeLogger branch = getLogger().branch(TreeLogger.ERROR, |
| "Unable to launch default browser", caught); |
| if (branch.isLoggable(TreeLogger.INFO)) { |
| branch.log(TreeLogger.INFO, url.toExternalForm()); |
| } |
| } |
| } |
| |
| /** |
| * A class for implementing different methods of launching a URL. |
| * <p> |
| * Note that this is retained despite the UI change because we plan to support |
| * multiple launcher types in the future. |
| */ |
| private abstract static class LaunchMethod { |
| |
| private final String displayName; |
| |
| /** |
| * Construct the launch method. |
| * |
| * @param displayName the name that will display in the UI for this launch |
| * method |
| */ |
| public LaunchMethod(String displayName) { |
| this.displayName = displayName; |
| } |
| |
| /** |
| * Launch the specified URL. |
| * |
| * @param url |
| */ |
| public abstract void launchUrl(URL url); |
| |
| @Override |
| public String toString() { |
| return displayName; |
| } |
| } |
| |
| /** |
| * User-visible URL and complete URL for use in combo box. |
| */ |
| private static class UrlComboEntry { |
| |
| private final String urlFragment; |
| private final URL url; |
| |
| public UrlComboEntry(String urlFragment, URL url) { |
| this.urlFragment = urlFragment; |
| this.url = url; |
| } |
| |
| public URL getUrl() { |
| return url; |
| } |
| |
| @Override |
| public String toString() { |
| return urlFragment; |
| } |
| } |
| |
| private SwingLoggerPanel logWindow; |
| private JComboBox urlCombo; |
| private JButton defaultBrowserButton; |
| private JButton copyToClipboardButton; |
| private JLabel loadingMessage; |
| private JPanel launchPanel; |
| |
| /** |
| * Create the main window with the top-level logger and launch controls. |
| * <p> |
| * MUST BE CALLED FROM THE UI THREAD |
| * |
| * @param maxLevel |
| * @param logFile |
| */ |
| public ShellMainWindow(TreeLogger.Type maxLevel, File logFile) { |
| super(new BorderLayout()); |
| launchPanel = new JPanel(new WrapLayout()); |
| launchPanel.setBorder(BorderFactory.createTitledBorder( |
| "Launch GWT Module")); |
| launchPanel.add(new JLabel("Startup URL:")); |
| JPanel startupPanel = new JPanel(); |
| urlCombo = new JComboBox(); |
| urlCombo.addItem("Computing..."); |
| startupPanel.add(urlCombo); |
| launchPanel.add(startupPanel); |
| loadingMessage = new JLabel("Loading..."); |
| launchPanel.add(loadingMessage); |
| defaultBrowserButton = new JButton("Launch Default Browser"); |
| defaultBrowserButton.setMnemonic(KeyEvent.VK_L); |
| defaultBrowserButton.setEnabled(false); |
| defaultBrowserButton.setVisible(false); |
| defaultBrowserButton.addActionListener(new ActionListener() { |
| public void actionPerformed(ActionEvent e) { |
| launch(new DefaultBrowserLauncher()); |
| } |
| }); |
| launchPanel.add(defaultBrowserButton); |
| copyToClipboardButton = new JButton("Copy to Clipboard"); |
| copyToClipboardButton.setMnemonic(KeyEvent.VK_C); |
| copyToClipboardButton.setEnabled(false); |
| copyToClipboardButton.setVisible(false); |
| copyToClipboardButton.addActionListener(new ActionListener() { |
| public void actionPerformed(ActionEvent e) { |
| launch(new CopyToClipboardLauncher()); |
| } |
| }); |
| launchPanel.add(copyToClipboardButton); |
| add(launchPanel, BorderLayout.NORTH); |
| logWindow = new SwingLoggerPanel(maxLevel, logFile); |
| add(logWindow); |
| } |
| |
| /** |
| * @return TreeLogger instance |
| */ |
| public TreeLogger getLogger() { |
| return logWindow.getLogger(); |
| } |
| |
| /** |
| * Indicate that all modules have been loaded -- on success, URLs previously |
| * specified in {@link #setStartupUrls(Map)} may be launched. |
| * <p> |
| * MUST BE CALLED FROM THE UI THREAD |
| * |
| * @param successfulLoad true if all modules were successfully loaded |
| */ |
| public void moduleLoadComplete(boolean successfulLoad) { |
| if (!successfulLoad) { |
| loadingMessage.setText("Module Load Failure"); |
| loadingMessage.setForeground(Color.RED); |
| return; |
| } |
| if (urlCombo.getItemCount() == 0) { |
| loadingMessage.setText("No URLs to Launch"); |
| loadingMessage.setForeground(Color.RED); |
| urlCombo.addItem("No startup URLs"); |
| urlCombo.setEnabled(false); |
| return; |
| } |
| loadingMessage.setVisible(false); |
| defaultBrowserButton.setVisible(true); |
| defaultBrowserButton.setEnabled(true); |
| copyToClipboardButton.setVisible(true); |
| copyToClipboardButton.setEnabled(true); |
| launchPanel.revalidate(); |
| launchPanel.repaint(); |
| } |
| |
| /** |
| * Create the UI to show available startup URLs. These should not be |
| * launchable by the user until the {@link #moduleLoadComplete(boolean)} method is |
| * called. |
| * <p> |
| * MUST BE CALLED FROM THE UI THREAD |
| |
| * @param urls map of user-specified URL fragments to final URLs |
| */ |
| public void setStartupUrls(final Map<String, URL> urls) { |
| urlCombo.removeAllItems(); |
| ArrayList<String> keys = new ArrayList<String>(urls.keySet()); |
| Collections.sort(keys); |
| for (String url : keys) { |
| urlCombo.addItem(new UrlComboEntry(url, urls.get(url))); |
| } |
| urlCombo.revalidate(); |
| } |
| |
| /** |
| * Launch the selected URL with the selected launch method. |
| * <p> |
| * MUST BE CALLED FROM THE UI THREAD |
| * @param launcher |
| */ |
| protected void launch(LaunchMethod launcher) { |
| UrlComboEntry selectedUrl = (UrlComboEntry) urlCombo.getSelectedItem(); |
| if (launcher == null || selectedUrl == null) { |
| // Shouldn't happen - should we log anything? |
| return; |
| } |
| URL url = selectedUrl.getUrl(); |
| launcher.launchUrl(url); |
| } |
| } |