/* * $Id$ * IzPack - Copyright 2001-2008 Julien Ponge, All Rights Reserved. * * http://izpack.org/ * http://izpack.codehaus.org/ * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.izforge.izpack.installer; import java.awt.*; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.LookAndFeel; import javax.swing.SwingConstants; import javax.swing.UIManager; import javax.swing.plaf.metal.MetalLookAndFeel; import com.izforge.izpack.Panel; import com.izforge.izpack.gui.LabelFactory; import com.izforge.izpack.gui.LayoutConstants; import com.izforge.izpack.panels.HelpWindow; import com.izforge.izpack.util.AbstractUIHandler; import com.izforge.izpack.util.Debug; import com.izforge.izpack.util.MultiLineLabel; import com.izforge.izpack.util.VariableSubstitutor; import com.izforge.izpack.adaptator.IXMLElement; /** * Defines the base class for the IzPack panels. Any panel should be a subclass of it and should * belong to the <code>com.izforge.izpack.panels</code> package. Since IzPack version 3.9 the * layout handling will be delegated to the class LayoutHelper which can be accessed by * <code>getLayoutHelper</code>. There are some layout helper methods in this class which will be * exist some time longer, but they are deprecated. At a redesign or new panel use the layout * helper. There is a special layout manager for IzPanels. This layout manager will be supported by * the layout helper. There are some points which should be observed at layouting. One point e.g. is * the anchor. All IzPanels have to be able to use different anchors, as minimum CENTER and * NORTHWEST. To use a consistent appearance use this special layout manger and not others. * * @author Julien Ponge * @author Klaus Bartz */ public class IzPanel extends JPanel implements AbstractUIHandler, LayoutConstants { private static final long serialVersionUID = 3256442495255786038L; /** * The helper object which handles layout */ protected LayoutHelper layoutHelper; /** * The component which should get the focus at activation */ protected Component initialFocus = null; /** * The installer internal data (actually a melting-pot class with all-public fields. */ protected InstallData idata; /** * The parent IzPack installer frame. */ protected InstallerFrame parent; /** * i.e. "com.izforge.izpack.panels.HelloPanel" */ protected String myFullClassname; /** * myClassname=i.e "FinishPanel" */ protected String myClassname; /** * i.e. "FinishPanel." useFull for getString() */ protected String myPrefix; /** * internal headline string */ protected String headline; /** * internal headline Label */ protected JLabel headLineLabel; /** * Is this panel general hidden or not */ protected boolean hidden; /** * HEADLINE = "headline" */ public final static String HEADLINE = "headline"; private DataValidator validationService = null; private java.util.List<PanelAction> preActivateActions = null; private java.util.List<PanelAction> preValidateActions = null; private java.util.List<PanelAction> postValidateActions = null; /** * X_ORIGIN = 0 */ public final static int X_ORIGIN = 0; /** * Y_ORIGIN = 0 */ public final static int Y_ORIGIN = 0; /** * D = "." ( dot ) */ public final static String D = "."; /** * d = D */ public final static String d = D; /** * COLS_1 = 1 */ public final static int COLS_1 = 1; /** * ROWS_1 = 1 */ public final static int ROWS_1 = 1; /** * Information about the panel */ public Panel metadata; /** * The constructor. * * @param parent The parent IzPack installer frame. * @param idata The installer internal data. */ public IzPanel(InstallerFrame parent, InstallData idata) { this(parent, idata, (LayoutManager2) null); } /** * Creates a new IzPanel object with the given layout manager. Valid layout manager are the * IzPanelLayout and the GridBagLayout. New panels should be use the IzPanelLaout. If lm is * null, no layout manager will be created or initialized. * * @param parent The parent IzPack installer frame. * @param idata The installer internal data. * @param lm layout manager to be used with this IzPanel */ public IzPanel(InstallerFrame parent, InstallData idata, LayoutManager2 lm) { super(); init(parent, idata); if (lm != null) { getLayoutHelper().startLayout(lm); } } /** * Creates a new IzPanel object. * * @param parent the Parent Frame * @param idata Installers Runtime Data Set * @param iconName The Headline IconName */ public IzPanel(InstallerFrame parent, InstallData idata, String iconName) { this(parent, idata, iconName, -1); } /** * The constructor with Icon. * * @param parent The parent IzPack installer frame. * @param idata The installer internal data. * @param iconName A iconname to show as left oriented headline-leading Icon. * @param instance An instance counter */ public IzPanel(InstallerFrame parent, InstallData idata, String iconName, int instance) { this(parent, idata); buildHeadline(iconName, instance); } /** * Build the IzPanel internal Headline. If an external headline# is used, this method returns * immediately with false. Allows also to display a leading Icon for the PanelHeadline. This * Icon can also be different if the panel has more than one Instances. The UserInputPanel is * one of these Candidates. <p/> by marc.eppelmann@gmx.de * * @param imageIconName an Iconname * @param instanceNumber an panel instance * @return true if successful build */ protected boolean buildHeadline(String imageIconName, int instanceNumber) { boolean result = false; if (parent.isHeading(this)) { return (false); } // TODO: proteced instancenumber // TODO: is to be validated // TODO: // TODO: first Test if a Resource for your protected Instance exists. String headline; String headlineSearchBaseKey = myClassname + d + "headline"; // Results for example in // "ShortcutPanel.headline" // : if (instanceNumber > -1) // Search for Results for example in "ShortcutPanel.headline.1, // 2, 3 etc." : { String instanceSearchKey = headlineSearchBaseKey + d + Integer.toString(instanceNumber); String instanceHeadline = getString(instanceSearchKey); if (Debug.isLOG()) { System.out.println("found headline: " + instanceHeadline + d + " for instance # " + instanceNumber); } if (!instanceSearchKey.equals(instanceHeadline)) { headline = instanceHeadline; } else { headline = getString(headlineSearchBaseKey); } } else { headline = getString(headlineSearchBaseKey); } if (headline != null) { if ((imageIconName != null) && !"".equals(imageIconName)) { headLineLabel = new JLabel(headline, getImageIcon(imageIconName), SwingConstants.LEADING); } else { headLineLabel = new JLabel(headline); } Font font = headLineLabel.getFont(); float size = font.getSize(); int style = 0; font = font.deriveFont(style, (size * 1.5f)); headLineLabel.setFont(font); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.gridwidth = 1; gbc.gridheight = 1; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.anchor = GridBagConstraints.WEST; gbc.insets = new Insets(0, 0, 0, 0); headLineLabel.setName(HEADLINE); ((GridBagLayout) getLayout()).addLayoutComponent(headLineLabel, gbc); add(headLineLabel); } return result; } /** * Gets a language Resource String from the parent, which holds these global resource. * * @param key The Search key * @return The Languageresource or the key if not found. */ public String getString(String key) { return parent.langpack.getString(key); } /** * Gets a named image icon * * @param iconName a valid image icon * @return the icon */ public ImageIcon getImageIcon(String iconName) { return parent.icons.getImageIcon(iconName); } /** * Inits and sets the internal layout helper object. */ protected void initLayoutHelper() { layoutHelper = new LayoutHelper(this); } /** * Gets and fills the classname fields */ protected void getClassName() { myFullClassname = getClass().getName(); myClassname = myFullClassname.substring(myFullClassname.lastIndexOf(".") + 1); myPrefix = myClassname + "."; } /** * Internal init method * * @param parent the parent frame * @param idata installers runtime dataset */ protected void init(InstallerFrame parent, InstallData idata) { getClassName(); this.idata = idata; this.parent = parent; // To get the Panel object via idata is a hack because InstallData will // be hold global data, not panel specific data. But the Panel object will // be needed in the constructor of some derived classes. And to expand the // constructor is also not a good way because all derived classes have to // change then the signature. Also the custem IzPanels elswhere. Therefore // this hack... // Problems with this hack will be exist if more than one threads calls the // constructors of derived clases. This is not the case. this.metadata = idata.currentPanel; idata.currentPanel = null; initLayoutHelper(); } /** * Indicates wether the panel has been validated or not. The installer won't let the user go * further through the installation process until the panel is validated. Default behaviour is * to return <code>true</code>. * * @return A boolean stating whether the panel has been validated or not. */ protected boolean isValidated() { return true; } public boolean panelValidated() { return isValidated() && validatePanel(); } /** * This method is called when the panel becomes active. Default is to do nothing : feel free to * implement what you need in your subclasses. A panel becomes active when the user reaches it * during the installation process. */ public void panelActivate() { } /** * This method is called when the panel gets desactivated, when the user switches to the next * panel. By default it doesn't do anything. */ public void panelDeactivate() { } /** * Asks the panel to set its own XML data that can be brought back for an automated installation * process. Use it as a blackbox if your panel needs to do something even in automated mode. * * @param panelRoot The XML root element of the panels blackbox tree. */ public void makeXMLData(IXMLElement panelRoot) { } /** * Ask the user a question. * * @param title Message title. * @param question The question. * @param choices The set of choices to present. * @return The user's choice. * @see AbstractUIHandler#askQuestion(String, String, int) */ public int askQuestion(String title, String question, int choices) { return askQuestion(title, question, choices, -1); } /** * Ask the user a question. * * @param title Message title. * @param question The question. * @param choices The set of choices to present. * @param default_choice The default choice. (-1 = no default choice) * @return The user's choice. * @see AbstractUIHandler#askQuestion(String, String, int, int) */ public int askQuestion(String title, String question, int choices, int default_choice) { int jo_choices = 0; if (choices == AbstractUIHandler.CHOICES_YES_NO) { jo_choices = JOptionPane.YES_NO_OPTION; } else if (choices == AbstractUIHandler.CHOICES_YES_NO_CANCEL) { jo_choices = JOptionPane.YES_NO_CANCEL_OPTION; } int user_choice = JOptionPane.showConfirmDialog(this, question, title, jo_choices, JOptionPane.QUESTION_MESSAGE); if (user_choice == JOptionPane.CANCEL_OPTION) { return AbstractUIHandler.ANSWER_CANCEL; } if (user_choice == JOptionPane.YES_OPTION) { return AbstractUIHandler.ANSWER_YES; } if (user_choice == JOptionPane.CLOSED_OPTION) { return AbstractUIHandler.ANSWER_NO; } if (user_choice == JOptionPane.NO_OPTION) { return AbstractUIHandler.ANSWER_NO; } return default_choice; } public boolean emitNotificationFeedback(String message) { return (JOptionPane.showConfirmDialog(this, message, idata.langpack .getString("installer.Message"), JOptionPane.WARNING_MESSAGE, JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION); } /** * Notify the user about something. * * @param message The notification. */ public void emitNotification(String message) { JOptionPane.showMessageDialog(this, message); } /** * Warn the user about something. * * @param message The warning message. */ public boolean emitWarning(String title, String message) { return (JOptionPane.showConfirmDialog(this, message, title, JOptionPane.WARNING_MESSAGE, JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION); } /** * Notify the user of some error. * * @param message The error message. */ public void emitError(String title, String message) { JOptionPane.showMessageDialog(this, message, title, JOptionPane.ERROR_MESSAGE); } /** * Returns the component which should be get the focus at activation of this panel. * * @return the component which should be get the focus at activation of this panel */ public Component getInitialFocus() { return initialFocus; } /** * Sets the component which should be get the focus at activation of this panel. * * @param component which should be get the focus at activation of this panel */ public void setInitialFocus(Component component) { initialFocus = component; } /** * Calls the langpack of parent InstallerFrame for the String <tt>RuntimeClassName.subkey</tt>. * Do not add a point infront of subkey, it is always added in this method. If * <tt>RuntimeClassName.subkey</tt> is not found, the super class name will be used until it * is <tt>IzPanel</tt>. If no key will be found, null returns. * * @param subkey the subkey for the string which should be returned * @return the founded string */ public String getI18nStringForClass(String subkey) { String retval = null; Class clazz = this.getClass(); while (retval == null && !clazz.getName().endsWith(".IzPanel")) { retval = getI18nStringForClass(clazz.getName(), subkey, null); clazz = clazz.getSuperclass(); } return (retval); } /** * Calls the langpack of parent InstallerFrame for the String <tt>RuntimeClassName.subkey</tt>. * Do not add a point infront of subkey, it is always added in this method. If no key will be * found the key or - if alternate class is null - null returns. * * @param subkey the subkey for the string which should be returned * @param alternateClass the short name of the class which should be used if no string is * present with the runtime class name * @return the founded string */ public String getI18nStringForClass(String subkey, String alternateClass) { return (getI18nStringForClass(getClass().getName(), subkey, alternateClass)); } private String getI18nStringForClass(String curClassName, String subkey, String alternateClass) { int nameStart = curClassName.lastIndexOf('.') + 1; curClassName = curClassName.substring(nameStart, curClassName.length()); StringBuffer buf = new StringBuffer(); buf.append(curClassName).append(".").append(subkey); String fullkey = buf.toString(); String panelid = null; if (getMetadata() != null) { panelid = getMetadata().getPanelid(); } String retval = null; if (panelid != null) { buf.append("."); buf.append(panelid); retval = parent.langpack.getString(buf.toString()); } if (retval == null || retval.startsWith(fullkey)) { retval = parent.langpack.getString(fullkey); } if (retval == null || retval.startsWith(fullkey)) { if (alternateClass == null) { return (null); } buf.delete(0, buf.length()); buf.append(alternateClass).append(".").append(subkey); retval = parent.langpack.getString(buf.toString()); } if (retval != null && retval.indexOf('$') > -1) { VariableSubstitutor substitutor = new VariableSubstitutor(idata.getVariables()); retval = substitutor.substitute(retval, null); } return (retval); } /** * Returns the parent of this IzPanel (which is a InstallerFrame). * * @return the parent of this IzPanel */ public InstallerFrame getInstallerFrame() { return (parent); } // ------------- Helper for common used components ----- START --- /** * Creates a label via LabelFactory using iconId, pos and method getI18nStringForClass for * resolving the text to be used. If the icon id is null, the label will be created also. * * @param subkey the subkey which should be used for resolving the text * @param alternateClass the short name of the class which should be used if no string is * present with the runtime class name * @param iconId id string for the icon * @param pos horizontal alignment * @return the newly created label */ public JLabel createLabel(String subkey, String alternateClass, String iconId, int pos) { ImageIcon ii = (iconId != null) ? parent.icons.getImageIcon(iconId) : null; String msg = getI18nStringForClass(subkey, alternateClass); JLabel label = LabelFactory.create(msg, ii, pos); if (label != null) { label.setFont(getControlTextFont()); } return (label); } /** * Creates a label via LabelFactory using iconId, pos and method getI18nStringForClass for * resolving the text to be used. If the icon id is null, the label will be created also. If * isFullLine true a LabelFactory.FullLineLabel will be created instead of a JLabel. The * difference between both classes are a different layout handling. * * @param subkey the subkey which should be used for resolving the text * @param alternateClass the short name of the class which should be used if no string is * present with the runtime class name * @param iconId id string for the icon * @param pos horizontal alignment * @param isFullLine determines whether a FullLineLabel or a JLabel should be created * @return the newly created label */ public JLabel createLabel(String subkey, String alternateClass, String iconId, int pos, boolean isFullLine) { ImageIcon ii = (iconId != null) ? parent.icons.getImageIcon(iconId) : null; String msg = getI18nStringForClass(subkey, alternateClass); JLabel label = LabelFactory.create(msg, ii, pos, isFullLine); if (label != null) { label.setFont(getControlTextFont()); } return (label); } /** * Creates a label via LabelFactory with the given ids and the given horizontal alignment. If * the icon id is null, the label will be created also. The strings are the ids for the text in * langpack and the icon in icons of the installer frame. * * @param textId id string for the text * @param iconId id string for the icon * @param pos horizontal alignment * @return the newly created label */ public JLabel createLabel(String textId, String iconId, int pos) { return (createLabel(textId, iconId, pos, false)); } /** * Creates a label via LabelFactory with the given ids and the given horizontal alignment. If * the icon id is null, the label will be created also. The strings are the ids for the text in * langpack and the icon in icons of the installer frame. If isFullLine true a * LabelFactory.FullLineLabel will be created instead of a JLabel. The difference between both * classes are a different layout handling. * * @param textId id string for the text * @param iconId id string for the icon * @param pos horizontal alignment * @param isFullLine determines whether a FullLineLabel or a JLabel should be created * @return the newly created label */ public JLabel createLabel(String textId, String iconId, int pos, boolean isFullLine) { ImageIcon ii = (iconId != null) ? parent.icons.getImageIcon(iconId) : null; JLabel label = LabelFactory.create(parent.langpack.getString(textId), ii, pos, isFullLine); if (label != null) { label.setFont(getControlTextFont()); } return (label); } /** * Creates a multi line label with the language dependent text given by the text id. The strings * is the id for the text in langpack of the installer frame. The horizontal alignment will be * LEFT. * * @param textId id string for the text * @return the newly created multi line label */ public MultiLineLabel createMultiLineLabelLang(String textId) { return (createMultiLineLabel(parent.langpack.getString(textId))); } /** * Creates a multi line label with the given text. The horizontal alignment will be LEFT. * * @param text text to be used in the label * @return the newly created multi line label */ public MultiLineLabel createMultiLineLabel(String text) { return (createMultiLineLabel(text, null, SwingConstants.LEFT)); } /** * Creates a label via LabelFactory with the given text, the given icon id and the given * horizontal alignment. If the icon id is null, the label will be created also. The strings are * the ids for the text in langpack and the icon in icons of the installer frame. * * @param text text to be used in the label * @param iconId id string for the icon * @param pos horizontal alignment * @return the created multi line label */ public MultiLineLabel createMultiLineLabel(String text, String iconId, int pos) { MultiLineLabel mll = null; mll = new MultiLineLabel(text, 0, 0); if (mll != null) { mll.setFont(getControlTextFont()); } return (mll); } /** * The Font of Labels in many cases */ public Font getControlTextFont() { Font fontObj = (getLAF() != null) ? MetalLookAndFeel.getControlTextFont() : getFont(); //if guiprefs 'labelFontSize' multiplier value // has been setup then apply it to the font: final float val; if ((val=LabelFactory.getLabelFontSize()) != 1.0f) fontObj = fontObj.deriveFont(fontObj.getSize2D()*val); return fontObj; } protected static MetalLookAndFeel getLAF() { LookAndFeel laf = UIManager.getLookAndFeel(); if (laf instanceof MetalLookAndFeel) { return ((MetalLookAndFeel) laf); } return (null); } // ------------- Helper for common used components ----- END --- // ------------------- Layout stuff -------------------- START --- /** * Returns the default GridBagConstraints of this panel. * * @return the default GridBagConstraints of this panel * @deprecated use <code>getLayoutHelper().getDefaulConstraints</code> instead */ public GridBagConstraints getDefaultGridBagConstraints() { return (GridBagConstraints) (layoutHelper.getDefaultConstraints()); } /** * Sets the default GridBagConstraints of this panel to the given object. * * @param constraints which should be set as default for this object * @deprecated use <code>getLayoutHelper().setDefaultConstraints</code> instead */ public void setDefaultGridBagConstraints(GridBagConstraints constraints) { layoutHelper.setDefaultConstraints(constraints); } /** * Resets the grid counters which are used at getNextXGridBagConstraints and * getNextYGridBagConstraints. * * @deprecated use <code>getLayoutHelper().resetGridCounter</code> instead */ public void resetGridCounter() { layoutHelper.resetGridCounter(); } /** * Returns a newly created GridBagConstraints with the given values and the values from the * defaultGridBagConstraints for the other parameters. * * @param gridx value to be used for the new constraint * @param gridy value to be used for the new constraint * @return newly created GridBagConstraints with the given values and the values from the * defaultGridBagConstraints for the other parameters * @deprecated use <code>getLayoutHelper().getNewConstraints</code> instead */ public GridBagConstraints getNewGridBagConstraints(int gridx, int gridy) { return (GridBagConstraints) (layoutHelper.getNewConstraints(gridx, gridy)); } /** * Returns a newly created GridBagConstraints with the given values and the values from the * defaultGridBagConstraints for the other parameters. * * @param gridx value to be used for the new constraint * @param gridy value to be used for the new constraint * @param gridwidth value to be used for the new constraint * @param gridheight value to be used for the new constraint * @return newly created GridBagConstraints with the given values and the values from the * defaultGridBagConstraints for the other parameters * @deprecated use <code>getLayoutHelper().getNewConstraints</code> instead */ public GridBagConstraints getNewGridBagConstraints(int gridx, int gridy, int gridwidth, int gridheight) { return (GridBagConstraints) (layoutHelper.getNewConstraints(gridx, gridy, gridwidth, gridheight)); } /** * Returns a newly created GridBagConstraints for the next column of the current layout row. * * @return a newly created GridBagConstraints for the next column of the current layout row * @deprecated use <code>getLayoutHelper().getNextXConstraints</code> instead */ public GridBagConstraints getNextXGridBagConstraints() { return (GridBagConstraints) (layoutHelper.getNextXConstraints()); } /** * Returns a newly created GridBagConstraints with column 0 for the next row. * * @return a newly created GridBagConstraints with column 0 for the next row * @deprecated use <code>getLayoutHelper().getNextYConstraints</code> instead */ public GridBagConstraints getNextYGridBagConstraints() { return (GridBagConstraints) (layoutHelper.getNextYConstraints()); } /** * Returns a newly created GridBagConstraints with column 0 for the next row using the given * parameters. * * @param gridwidth width for this constraint * @param gridheight height for this constraint * @return a newly created GridBagConstraints with column 0 for the next row using the given * parameters * @deprecated use <code>getLayoutHelper().getNextYConstraints</code> instead */ public GridBagConstraints getNextYGridBagConstraints(int gridwidth, int gridheight) { return (GridBagConstraints) (layoutHelper.getNextYConstraints(gridwidth, gridheight)); } /** * Start layout determining. If it is needed, a dummy component will be created as first row. * This will be done, if the IzPack guiprefs modifier with the key "layoutAnchor" has the value * "SOUTH" or "SOUTHWEST". The earlier used value "BOTTOM" and the declaration via the IzPack * variable <code>IzPanel.LayoutType</code> are also supported. * * @deprecated use <code>getLayoutHelper().startLayout</code> instead */ public void startGridBagLayout() { layoutHelper.startLayout(new GridBagLayout()); } /** * Complete layout determining. If it is needed, a dummy component will be created as last row. * This will be done, if the IzPack guiprefs modifier with the key "layoutAnchor" has the value * "NORTH" or "NORTHWEST". The earlier used value "TOP" and the declaration via the IzPack * variable <code>IzPanel.LayoutType</code> are also supported. * * @deprecated use <code>getLayoutHelper().completeLayout</code> instead */ public void completeGridBagLayout() { layoutHelper.completeLayout(); } // ------------------- Layout stuff -------------------- END --- // ------------------- Summary stuff -------------------- START --- /** * This method will be called from the SummaryPanel to get the summary of this class which * should be placed in the SummaryPanel. The returned text should not contain a caption of this * item. The caption will be requested from the method getCaption. If <code>null</code> * returns, no summary for this panel will be generated. Default behaviour is to return * <code>null</code>. * * @return the summary for this class */ public String getSummaryBody() { return null; } /** * This method will be called from the SummaryPanel to get the caption for this class which * should be placed in the SummaryPanel. If <code>null</code> returns, no summary for this * panel will be generated. Default behaviour is to return the string given by langpack for the * key <code><current class name>.summaryCaption></code> if exist, else the string * "summaryCaption.<ClassName>". * * @return the caption for this class */ public String getSummaryCaption() { String caption; if (parent.isHeading(this) && idata.guiPrefs.modifier.containsKey("useHeadingForSummary") && (idata.guiPrefs.modifier.get("useHeadingForSummary")).equalsIgnoreCase("yes")) { caption = getI18nStringForClass("headline", this.getClass().getName()); } else { caption = getI18nStringForClass("summaryCaption", this.getClass().getName()); } return (caption); } // ------------------- Summary stuff -------------------- END --- // ------------------- Inner classes ------------------- START --- public static class Filler extends JComponent { private static final long serialVersionUID = 3258416144414095153L; } // ------------------- Inner classes ------------------- END --- /** * Returns whether this panel will be hidden general or not. A hidden panel will be not counted * in the step counter and for panel icons. * * @return whether this panel will be hidden general or not */ public boolean isHidden() { return hidden; } /** * Set whether this panel should be hidden or not. A hidden panel will be not counted in the * step counter and for panel icons. * * @param hidden flag to be set */ public void setHidden(boolean hidden) { this.hidden = hidden; } /** * Returns the used layout helper. Can be used in a derived class to create custom layout. * * @return the used layout helper */ public LayoutHelper getLayoutHelper() { return layoutHelper; } /** * @return the metadata */ public Panel getMetadata() { return this.metadata; } /** * @param p the metadata to set */ public void setMetadata(Panel p) { this.metadata = p; } public DataValidator getValidationService() { return validationService; } public void setValidationService(DataValidator validationService) { this.validationService = validationService; } /*--------------------------------------------------------------------------*/ /** * This method validates the field content. Validating is performed through a user supplied * service class that provides the validation rules. * * @return <code>true</code> if the validation passes or no implementation of a validation * rule exists. Otherwise <code>false</code> is returned. */ /*--------------------------------------------------------------------------*/ private final boolean validatePanel() { boolean returnValue = false; if (this.validationService != null) { Component guiComponent = getTopLevelAncestor(); Cursor originalCursor = guiComponent.getCursor(); Cursor newCursor = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR); try { guiComponent.setCursor(newCursor); // validating the data DataValidator.Status returnStatus = this.validationService.validateData(this.idata); if (returnStatus == DataValidator.Status.OK) { returnValue = true; } else { Debug.trace("Validation did not pass!"); // try to parse the text, and substitute any variable it finds VariableSubstitutor vs = new VariableSubstitutor(idata.getVariables()); if (this.validationService.getWarningMessageId() != null && returnStatus == DataValidator.Status.WARNING) { String warningMessage = parent.langpack.getString(this.validationService .getWarningMessageId()); if (this.emitWarning(getString("data.validation.warning.title"), vs .substitute(warningMessage, null))) { returnValue = true; Debug.trace("... but user decided to go on!"); } } else { String errorMessage = parent.langpack.getString(this.validationService .getErrorMessageId()); this.emitError(getString("data.validation.error.title"), vs.substitute( errorMessage, null)); } } } finally { guiComponent.setCursor(originalCursor); } } else { returnValue = true; } return returnValue; } /** * Parses the text for special variables. */ protected String parseText(String string_to_parse) { try { // Initialize the variable substitutor VariableSubstitutor vs = new VariableSubstitutor(idata.getVariables()); // Parses the info text string_to_parse = vs.substitute(string_to_parse, null); } catch (Exception err) { err.printStackTrace(); } return string_to_parse; } private HashMap<String, String> helps = null; public void setHelps(HashMap helps) { this.helps = helps; } public String getHelpUrl(String isoCode) { String url = null; if (this.helps != null) { url = helps.get(isoCode); } return url; } /** * Indicates wether the panel can display help. The installer will hide Help button if current * panel does not support help functions. Default behaviour is to return <code>false</code>. * * @return A boolean stating wether the panel supports Help function. */ public boolean canShowHelp() { return getHelpUrl(this.idata.localeISO3) != null; } /** * This method is called when Help button has been clicked. By default it doesn't do anything. */ public void showHelp() { String helpName = getHelpUrl(this.idata.localeISO3); // System.out.println("Help function called, helpName: " + helpName); if (helpName != null) { URL helpUrl = getClass().getResource("/res/" + helpName); getHelpWindow().showHelp(getString("installer.help"), helpUrl); } } private HelpWindow helpWindow = null; private HelpWindow getHelpWindow() { if (this.helpWindow != null) { return this.helpWindow; } this.helpWindow = new HelpWindow(parent, getString("installer.prev")); return this.helpWindow; } public void addPreActivationAction(PanelAction preActivateAction) { if (preActivateActions == null) { preActivateActions = new ArrayList<PanelAction>(); } this.preActivateActions.add(preActivateAction); } public void addPreValidationAction(PanelAction preValidateAction) { if (preValidateActions == null) { preValidateActions = new ArrayList<PanelAction>(); } this.preValidateActions.add(preValidateAction); } public void addPostValidationAction(PanelAction postValidateAction) { if (postValidateActions == null) { postValidateActions = new ArrayList<PanelAction>(); } this.postValidateActions.add(postValidateAction); } protected final void executePreActivationActions() { if (preActivateActions != null) { for (int actionIndex = 0; actionIndex < preActivateActions.size(); actionIndex++) { preActivateActions.get(actionIndex).executeAction(idata, this); } } } protected final void executePreValidationActions() { if (preValidateActions != null) { for (int actionIndex = 0; actionIndex < preValidateActions.size(); actionIndex++) { preValidateActions.get(actionIndex).executeAction(idata, this); } } } protected final void executePostValidationActions() { if (postValidateActions != null) { for (int actionIndex = 0; actionIndex < postValidateActions.size(); actionIndex++) { postValidateActions.get(actionIndex).executeAction(idata, this); } } } }