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}