04beaa0f370e2dfa269b339422caad36c11dd92f
[idea/community.git] / platform / platform-impl / src / com / intellij / ide / customize / CustomizeIDEWizardDialog.java
1 /*
2  * Copyright 2000-2014 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.ide.customize;
17
18 import com.intellij.ide.startup.StartupActionScriptManager;
19 import com.intellij.idea.Main;
20 import com.intellij.openapi.application.ApplicationNamesInfo;
21 import com.intellij.openapi.ui.DialogWrapper;
22 import com.intellij.openapi.util.SystemInfo;
23 import com.intellij.ui.JBCardLayout;
24 import com.intellij.util.PlatformUtils;
25 import org.jetbrains.annotations.Nullable;
26
27 import javax.swing.*;
28 import java.awt.*;
29 import java.awt.event.ActionEvent;
30 import java.awt.event.ActionListener;
31 import java.util.ArrayList;
32 import java.util.List;
33
34 public class CustomizeIDEWizardDialog extends DialogWrapper implements ActionListener {
35   private static final String BUTTONS = "BUTTONS";
36   private static final String NOBUTTONS = "NOBUTTONS";
37   private final JButton mySkipButton = new JButton("Skip All and Set Defaults");
38   private final JButton myBackButton = new JButton("Back");
39   private final JButton myNextButton = new JButton("Next");
40
41   private final JBCardLayout myCardLayout = new JBCardLayout();
42   protected final List<AbstractCustomizeWizardStep> mySteps = new ArrayList<AbstractCustomizeWizardStep>();
43   private int myIndex = 0;
44   private final JLabel myNavigationLabel = new JLabel();
45   private final JLabel myHeaderLabel = new JLabel();
46   private final JLabel myFooterLabel = new JLabel();
47   private final CardLayout myButtonWrapperLayout = new CardLayout();
48   private final JPanel myButtonWrapper = new JPanel(myButtonWrapperLayout);
49   private JPanel myContentPanel;
50
51   public CustomizeIDEWizardDialog() {
52     super(null, true, true);
53     setTitle("Customize " + ApplicationNamesInfo.getInstance().getProductName());
54     getPeer().setAppIcons();
55     initSteps();
56     mySkipButton.addActionListener(this);
57     myBackButton.addActionListener(this);
58     myNextButton.addActionListener(this);
59     myNavigationLabel.setEnabled(false);
60     myFooterLabel.setEnabled(false);
61     init();
62     initCurrentStep(true);
63     setSize(400, 300);
64     System.setProperty(StartupActionScriptManager.STARTUP_WIZARD_MODE, "true");
65   }
66
67   public static void showCustomSteps(String stepsProviderName) {
68     final CustomizeIDEWizardStepsProvider provider;
69
70     try {
71       Class<CustomizeIDEWizardStepsProvider> providerClass = (Class<CustomizeIDEWizardStepsProvider>)Class.forName(stepsProviderName);
72       provider = providerClass.newInstance();
73     }
74     catch (Throwable e) {
75       Main.showMessage("Start Failed", e);
76       return;
77     }
78
79     new CustomizeIDEWizardDialog() {
80       @Override
81       protected void initSteps() {
82         provider.initSteps(this, mySteps);
83       }
84     }.show();
85   }
86
87   @Override
88   protected void dispose() {
89     System.clearProperty(StartupActionScriptManager.STARTUP_WIZARD_MODE);
90     super.dispose();
91   }
92
93   protected void initSteps() {
94     mySteps.add(new CustomizeUIThemeStepPanel());
95     if (SystemInfo.isMac) {
96       mySteps.add(new CustomizeKeyboardSchemeStepPanel());
97     }
98
99     PluginGroups pluginGroups = new PluginGroups();
100     mySteps.add(new CustomizePluginsStepPanel(pluginGroups));
101     try {
102       mySteps.add(new CustomizeFeaturedPluginsStepPanel(pluginGroups));
103     }
104     catch (CustomizeFeaturedPluginsStepPanel.OfflineException e) {
105       //skip featured step if we're offline
106     }
107   }
108
109   @Override
110   protected JComponent createCenterPanel() {
111     JPanel result = new JPanel(new BorderLayout(5, 5));
112     myContentPanel = new JPanel(myCardLayout);
113     for (AbstractCustomizeWizardStep step : mySteps) {
114       myContentPanel.add(step, step.getTitle());
115     }
116     JPanel topPanel = new JPanel(new BorderLayout(5, 5));
117     topPanel.add(myNavigationLabel, BorderLayout.NORTH);
118     topPanel.add(myHeaderLabel, BorderLayout.CENTER);
119     result.add(topPanel, BorderLayout.NORTH);
120     result.add(myContentPanel, BorderLayout.CENTER);
121     result.add(myFooterLabel, BorderLayout.SOUTH);
122     result.setPreferredSize(new Dimension(700, 600));
123     result.setBorder(AbstractCustomizeWizardStep.createSmallEmptyBorder());
124     return result;
125   }
126
127   @Override
128   protected JComponent createSouthPanel() {
129     final JPanel buttonPanel = new JPanel(new GridBagLayout());
130     GridBagConstraints gbc = new GridBagConstraints();
131     gbc.insets.right = 5;
132     gbc.fill = GridBagConstraints.BOTH;
133     gbc.gridx = 0;
134     gbc.gridy = 0;
135     if (!PlatformUtils.isCLion()) {
136       buttonPanel.add(mySkipButton, gbc);
137       gbc.gridx++;
138     }
139     buttonPanel.add(myBackButton, gbc);
140     gbc.gridx++;
141     gbc.weightx = 1;
142     buttonPanel.add(Box.createHorizontalGlue(), gbc);
143     gbc.gridx++;
144     gbc.weightx = 0;
145     buttonPanel.add(myNextButton, gbc);
146     buttonPanel.setBorder(BorderFactory.createEmptyBorder(8, 0, 0, 0));
147     myButtonWrapper.add(buttonPanel, BUTTONS);
148     myButtonWrapper.add(new JLabel(), NOBUTTONS);
149     myButtonWrapperLayout.show(myButtonWrapper, BUTTONS);
150     return myButtonWrapper;
151   }
152
153   void setButtonsVisible(boolean visible) {
154     myButtonWrapperLayout.show(myButtonWrapper, visible ? BUTTONS : NOBUTTONS);
155   }
156
157   @Override
158   public void actionPerformed(ActionEvent e) {
159     if (e.getSource() == mySkipButton) {
160       doOKAction();
161       return;
162     }
163     if (e.getSource() == myBackButton) {
164       myIndex--;
165       initCurrentStep(false);
166       return;
167     }
168     if (e.getSource() == myNextButton) {
169       if (myIndex >= mySteps.size() - 1) {
170         doOKAction();
171         return;
172       }
173       myIndex++;
174       initCurrentStep(true);
175     }
176   }
177
178   @Nullable
179   @Override
180   protected ActionListener createCancelAction() {
181     return null;//Prevent closing by <Esc>
182   }
183
184   @Override
185   public void doCancelAction() {
186     doOKAction();
187   }
188
189   @Override
190   protected void doOKAction() {
191     for (AbstractCustomizeWizardStep step : mySteps) {
192       if (!step.beforeOkAction()) {
193         int index = mySteps.indexOf(step);
194         if (myIndex != index) {
195           myIndex = index;
196           initCurrentStep(true);
197         }
198         return;
199       }
200     }
201     super.doOKAction();
202   }
203
204   private void initCurrentStep(boolean forward) {
205     final AbstractCustomizeWizardStep myCurrentStep = mySteps.get(myIndex);
206     myCurrentStep.beforeShown(forward);
207     myCardLayout.swipe(myContentPanel, myCurrentStep.getTitle(), JBCardLayout.SwipeDirection.AUTO, new Runnable() {
208       @Override
209       public void run() {
210         Component component = myCurrentStep.getDefaultFocusedComponent();
211         if (component != null) {
212           component.requestFocus();
213         }
214       }
215     });
216
217     myBackButton.setVisible(myIndex > 0);
218     if (myIndex > 0) {
219       myBackButton.setText("Back to " + mySteps.get(myIndex - 1).getTitle());
220     }
221     mySkipButton.setText("Skip " + (myIndex > 0 ? "Remaining" : "All") + " and Set Defaults");
222
223     myNextButton.setText(myIndex < mySteps.size() - 1
224                          ? "Next: " + mySteps.get(myIndex + 1).getTitle()
225                          : "Start using " + ApplicationNamesInfo.getInstance().getFullProductName());
226     myHeaderLabel.setText(myCurrentStep.getHTMLHeader());
227     myFooterLabel.setText(myCurrentStep.getHTMLFooter());
228     StringBuilder navHTML = new StringBuilder("<html><body>");
229     for (int i = 0; i < mySteps.size(); i++) {
230       if (i > 0) navHTML.append("&nbsp;&#8594;&nbsp;");
231       if (i == myIndex) navHTML.append("<b>");
232       navHTML.append(mySteps.get(i).getTitle());
233       if (i == myIndex) navHTML.append("</b>");
234     }
235     myNavigationLabel.setText(navHTML.toString());
236   }
237 }