001/*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License").  You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
010 * or http://forgerock.org/license/CDDLv1.0.html.
011 * See the License for the specific language governing permissions
012 * and limitations under the License.
013 *
014 * When distributing Covered Code, include this CDDL HEADER in each
015 * file and include the License file at legal-notices/CDDLv1_0.txt.
016 * If applicable, add the following below this CDDL HEADER, with the
017 * fields enclosed by brackets "[]" replaced with your own identifying
018 * information:
019 *      Portions Copyright [yyyy] [name of copyright owner]
020 *
021 * CDDL HEADER END
022 *
023 *
024 *      Copyright 2006-2009 Sun Microsystems, Inc.
025 *      Portions Copyright 2014-2015 ForgeRock AS
026 */
027
028package org.opends.quicksetup.ui;
029
030import java.awt.GridBagConstraints;
031import java.awt.GridBagLayout;
032
033import java.util.HashMap;
034import java.util.LinkedHashSet;
035
036import javax.swing.Box;
037import javax.swing.JLabel;
038import javax.swing.JPanel;
039
040import org.opends.quicksetup.UserData;
041import org.opends.quicksetup.WizardStep;
042import org.forgerock.i18n.LocalizableMessage;
043
044/**
045 * This class displays the different steps of the wizard.  It appears on the
046 * left of the dialog.
047 *
048 * The current step is highlighted using a different label style and an icon.
049 * The current displayed step can be changed calling the method setCurrentStep.
050 *
051 */
052public class StepsPanel extends QuickSetupPanel
053{
054  private static final long serialVersionUID = -2003945907121690657L;
055
056  HashMap<WizardStep, JLabel> hmLabels = new HashMap<>();
057  HashMap<WizardStep, JLabel> hmIcons = new HashMap<>();
058  HashMap<WizardStep, JPanel> hmSubPanels = new HashMap<>();
059
060  /**
061   * Creates a StepsPanel.
062   * @param app Application whose steps this class represents
063   */
064  public StepsPanel(GuiApplication app)
065  {
066    super(app);
067    createLayout(app);
068  }
069
070  /**
071   * Updates the layout of the panel so that it corresponds to the Step passed
072   * as parameter.
073   *
074   * @param step the step in the wizard.
075   * @param userData the data provided by the user.
076   */
077  public void setDisplayedStep(WizardStep step, UserData userData)
078  {
079    for (WizardStep s : getApplication().getWizardSteps())
080    {
081      if (s.equals(step))
082      {
083        getIcon(s).setVisible(true);
084        UIFactory.setTextStyle(getLabel(s), UIFactory.TextStyle.CURRENT_STEP);
085      }
086      else
087      {
088        if (getIcon(s) != null)
089        {
090          getIcon(s).setVisible(false);
091        }
092        if (getLabel(s) != null)
093        {
094          UIFactory.setTextStyle(getLabel(s),
095              UIFactory.TextStyle.NOT_CURRENT_STEP);
096        }
097      }
098      setStepVisible(s, getApplication().isVisible(s, userData));
099    }
100  }
101
102  /**
103   * Updates the visibility of the steps depending on the current contents
104   * of the panels (uses the QuickSetup to know what is displayed in the
105   * panels).
106   *
107   * @param qs the QuickSetup object.
108   */
109  public void updateStepVisibility(QuickSetup qs)
110  {
111    for (WizardStep s : getApplication().getWizardSteps())
112    {
113      setStepVisible(s, getApplication().isVisible(s, qs));
114    }
115  }
116
117  /**
118   * Creates the layout of the panel.
119   * @param app Application whose steps this class represents
120   */
121  private void createLayout(GuiApplication app)
122  {
123    setLayout(new GridBagLayout());
124
125    JPanel mainPanel = new JPanel(new GridBagLayout());
126    mainPanel.setOpaque(false);
127
128    GridBagConstraints gbc = new GridBagConstraints();
129    gbc.weightx = 0.0;
130    gbc.weighty = 0.0;
131    gbc.fill = GridBagConstraints.HORIZONTAL;
132    gbc.anchor = GridBagConstraints.WEST;
133
134    HashMap<WizardStep, LocalizableMessage> hmText = new HashMap<>();
135    LinkedHashSet<WizardStep> orderedSteps = app.getOrderedSteps();
136    boolean first = true;
137    for (WizardStep s : orderedSteps)
138    {
139      hmText.put(s, s.getDisplayMessage());
140
141      JPanel subPanel = new JPanel(new GridBagLayout());
142      subPanel.setOpaque(false);
143      if (!first)
144      {
145        gbc.insets.top = UIFactory.TOP_INSET_STEP;
146      }
147
148      GridBagConstraints gbcAux = new GridBagConstraints();
149      gbcAux.gridwidth = GridBagConstraints.REMAINDER;
150      gbcAux.fill = GridBagConstraints.HORIZONTAL;
151      JPanel auxPanel = new JPanel(new GridBagLayout());
152      auxPanel.setOpaque(false);
153      JLabel iconLabel =
154          UIFactory.makeJLabel(UIFactory.IconType.CURRENT_STEP, null,
155              UIFactory.TextStyle.NO_STYLE);
156      gbcAux.insets.left = 0;
157
158      auxPanel.add(iconLabel, gbcAux);
159      int width = (int) iconLabel.getPreferredSize().getWidth();
160      if (getApplication().isSubStep(s))
161      {
162        width += UIFactory.LEFT_INSET_SUBSTEP;
163      }
164      gbcAux.insets.left = 0;
165      auxPanel.add(Box.createHorizontalStrut(width), gbcAux);
166
167      hmIcons.put(s, iconLabel);
168
169      gbc.gridwidth = 3;
170      gbc.weightx = 0.0;
171      subPanel.add(auxPanel, gbc);
172
173      JLabel stepLabel =
174              UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
175                      hmText.get(s),
176                      UIFactory.TextStyle.CURRENT_STEP);
177      hmLabels.put(s, stepLabel);
178      gbc.insets.left = UIFactory.LEFT_INSET_STEP;
179      gbc.gridwidth = GridBagConstraints.RELATIVE;
180      subPanel.add(stepLabel, gbc);
181      gbc.insets = UIFactory.getEmptyInsets();
182      gbc.gridwidth = GridBagConstraints.REMAINDER;
183      gbc.weightx = 1.0;
184      subPanel.add(Box.createHorizontalGlue(), gbc);
185
186      mainPanel.add(subPanel, gbc);
187      hmSubPanels.put(s, subPanel);
188
189      stepLabel.setLabelFor(this);
190      iconLabel.setLabelFor(stepLabel);
191
192      first = false;
193    }
194
195    gbc.insets.left = 0;
196    gbc.insets.top = 0;
197    gbc.weightx = 1.0;
198    gbc.weighty = 0.0;
199    gbc.fill = GridBagConstraints.NONE;
200    gbc.gridwidth = GridBagConstraints.REMAINDER;
201    gbc.anchor = GridBagConstraints.NORTHWEST;
202    add(mainPanel, gbc);
203    int mainWidth = (int) mainPanel.getPreferredSize().getWidth();
204
205    // We are creating all the labels with the style
206    // UIFactory.LabelStyle.CURRENT_STEP which is the one
207    // that takes more space. But once we display the dialog only one
208    // of the labels will have that style and the other will have
209    // UIFactory.LabelStyle.NOT_CURRENT_STEP. Adding the strut guarantees
210    // that the width of the panel will always be enough to display the
211    // longest label using UIFactory.LabelStyle.CURRENT_STEP.
212    add(Box.createHorizontalStrut(mainWidth), gbc);
213
214    gbc.fill = GridBagConstraints.VERTICAL;
215    gbc.weighty = 1.0;
216    add(Box.createVerticalGlue(), gbc);
217  }
218
219  /**
220   * Returns the label associated with the given step.
221   * @param step the step for which we want to retrieve the JLabel.
222   * @return the label associated with the given step.
223   */
224  private JLabel getLabel(WizardStep step)
225  {
226    return hmLabels.get(step);
227  }
228
229  /**
230   * Returns the icon associated with the given step.
231   * @param step the step for which we want to retrieve the Icon.
232   * @return the icon associated with the given step.
233   */
234  private JLabel getIcon(WizardStep step)
235  {
236    return hmIcons.get(step);
237  }
238
239  /**
240   * Returns the sub-panel associated with the given step.
241   * @param step the step for which we want to retrieve the sub-panel.
242   * @return the sub-panel associated with the given step.
243   */
244  private JPanel getSubPanel(WizardStep step)
245  {
246    return hmSubPanels.get(step);
247  }
248
249  private void setStepVisible(WizardStep step, boolean visible)
250  {
251    JPanel subPanel = getSubPanel(step);
252    // Check done to minimize possible flickering.
253    if (visible != subPanel.isVisible())
254    {
255      subPanel.setVisible(visible);
256    }
257  }
258}