/* * Copyright (C) 2014 The Android Open Source Project * * 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.android.tools.idea.wizard; import com.google.common.collect.Maps; import com.intellij.ide.IdeBundle; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogEarthquakeShaker; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.SystemInfo; import com.intellij.ui.components.panels.OpaquePanel; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.border.EmptyBorder; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.image.BufferedImage; import java.util.Map; /** * Uses {@link com.intellij.openapi.ui.DialogWrapper} to display a wizard in a dialog */ public final class DialogWrapperHost extends DialogWrapper implements DynamicWizardHost { // Action References. myCancelAction and myHelpAction are inherited private Action myPreviousAction = new PreviousAction(); private Action myNextAction = new NextAction(); private Action myFinishAction = new FinishAction(); private DynamicWizard myWizard; private TallImageComponent myIcon = new TallImageComponent(null); private JPanel myCenterPanel; // UI references private Map<Action, JButton> myActionToButtonMap = Maps.newHashMapWithExpectedSize(5); public DialogWrapperHost(@Nullable Project project) { super(project); Window window = getWindow(); if (window == null) { assert ApplicationManager.getApplication().isUnitTestMode(); } else { window.setPreferredSize(WizardConstants.DEFAULT_WIZARD_WINDOW_SIZE); } } @Override public void init(@NotNull DynamicWizard wizard) { myWizard = wizard; super.init(); // Clear out the large border Container centerRootPanel = myCenterPanel.getParent(); if (centerRootPanel != null) { Container rootPanel = centerRootPanel.getParent(); if (rootPanel instanceof JPanel) { // Clear out default borders, we'll set our own later ((JPanel)rootPanel).setBorder(new EmptyBorder(0, 0, 0, 0)); } } } @Override public void close(boolean canceled) { if (!canceled) { doOKAction(); } else { doCancelAction(); } } @Nullable @Override public JComponent getPreferredFocusedComponent() { JComponent focusedComponent = myWizard.getPreferredFocusedComponent(); return focusedComponent == null ? getNextButton() : focusedComponent; } @Override public void shakeWindow() { if (!ApplicationManager.getApplication().isUnitTestMode()) { DialogEarthquakeShaker.shake((JDialog)getPeer().getWindow()); } } /** * ACTIONS */ @NotNull @Override protected final Action[] createActions() { if (getHelpId() == null) { if (SystemInfo.isMac) { return new Action[]{getCancelAction(), myPreviousAction, myNextAction, myFinishAction}; } return new Action[]{myPreviousAction, myNextAction, getCancelAction(), myFinishAction}; } else { if (SystemInfo.isMac) { return new Action[]{getHelpAction(), getCancelAction(), myPreviousAction, myNextAction, myFinishAction}; } return new Action[]{myPreviousAction, myNextAction, getCancelAction(), myFinishAction, getHelpAction()}; } } @Override public void setIcon(@Nullable Icon icon) { myIcon.setIcon(icon); myIcon.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 8)); } @Override protected final JButton createJButtonForAction(Action action) { // Save a reference to the created button so that we can access them // later to enable/disable JButton button = super.createJButtonForAction(action); myActionToButtonMap.put(action, button); return button; } @Override protected void doHelpAction() { // TODO: Implement } /** * Create the south panel that serves as the container for the wizard buttons. * The base class does all the heavy lifting already, we just adjust the margins here. */ @Nullable @Override protected JComponent createSouthPanel() { JPanel southPanel = (JPanel)super.createSouthPanel(); assert southPanel != null; southPanel.setBorder(new EmptyBorder(WizardConstants.STUDIO_WIZARD_INSETS)); return southPanel; } /** * Update the buttons for the wizard * * @param canGoPrev whether the previous button is enabled * @param canGoNext whether the next button is enabled * @param canFinish if this is set to true and the current path is the last non-optional path, the canFinish * button will be enabled. */ @Override public void updateButtons(boolean canGoPrev, boolean canGoNext, boolean canFinish) { getPreviousButton().setEnabled(canGoPrev); getNextButton().setEnabled(canGoNext); getFinishButton().setEnabled(canFinish); if (!ApplicationManager.getApplication().isUnitTestMode()) { getRootPane().setDefaultButton(canFinish ? getFinishButton() : getNextButton()); } } /** * Create the center panel that will serve as a container for the UI components of each step. */ @Override @Nullable protected final JComponent createCenterPanel() { myCenterPanel = new JPanel(new BorderLayout()); myCenterPanel.add(myWizard.getContentPane(), BorderLayout.CENTER); myCenterPanel.add(myIcon, BorderLayout.WEST); return myCenterPanel; } @NotNull private JButton getNextButton() { return myActionToButtonMap.get(myNextAction); } @NotNull private JButton getPreviousButton() { return myActionToButtonMap.get(myPreviousAction); } @NotNull private JButton getFinishButton() { return myActionToButtonMap.get(myFinishAction); } @Override public void setTitle(String title) { super.setTitle(title); } @Override public void setPreferredWindowSize(Dimension dimension) { getContentPanel().setPreferredSize(dimension); } /** * Taken from {@link com.intellij.ide.wizard.AbstractWizard} */ public static class TallImageComponent extends OpaquePanel { @Nullable private Icon myIcon; public TallImageComponent(@Nullable Icon icon) { myIcon = icon; } @Override protected void paintChildren(Graphics g) { if (myIcon == null) return; paintIcon(g); } public void paintIcon(Graphics g) { if (myIcon == null) { return; } final BufferedImage image = UIUtil.createImage(myIcon.getIconWidth(), myIcon.getIconHeight(), BufferedImage.TYPE_INT_ARGB); final Graphics2D gg = image.createGraphics(); myIcon.paintIcon(this, gg, 0, 0); final Rectangle bounds = g.getClipBounds(); int y = myIcon.getIconHeight() - 1; while (y < bounds.y + bounds.height) { g.drawImage(image, bounds.x, y, bounds.x + bounds.width, y + 1, 0, myIcon.getIconHeight() - 1, bounds.width, myIcon.getIconHeight(), this); y++; } g.drawImage(image, 0, 0, this); } public void setIcon(@Nullable Icon icon) { myIcon = icon; revalidate(); repaint(); } @Override public Dimension getPreferredSize() { return new Dimension(myIcon != null ? myIcon.getIconWidth() : 0, 0); } @Override public Dimension getMinimumSize() { return new Dimension(myIcon != null ? myIcon.getIconWidth() : 0, 0); } } protected class NextAction extends DialogWrapperAction { protected NextAction() { super(IdeBundle.message("button.wizard.next")); putValue(DEFAULT_ACTION, Boolean.TRUE); } @Override protected void doAction(ActionEvent e) { myWizard.doNextAction(); } } protected class PreviousAction extends DialogWrapperAction { protected PreviousAction() { super(IdeBundle.message("button.wizard.previous")); } @Override protected void doAction(ActionEvent e) { myWizard.doPreviousAction(); } } protected class FinishAction extends DialogWrapperAction { protected FinishAction() { super(IdeBundle.message("button.finish")); } @Override protected void doAction(ActionEvent e) { myWizard.doFinishAction(); } } }