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}