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