com.izforge.izpack.panels.userinput.gui.GUIField Maven / Gradle / Ivy
/*
* IzPack - Copyright 2001-2012 Julien Ponge, All Rights Reserved.
*
* http://izpack.org/
* http://izpack.codehaus.org/
*
* Copyright 2012 Tim Anderson
*
* 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.panels.userinput.gui;
import com.izforge.izpack.api.data.InstallData;
import com.izforge.izpack.api.handler.Prompt;
import com.izforge.izpack.api.resource.Messages;
import com.izforge.izpack.gui.TwoColumnConstraints;
import com.izforge.izpack.panels.userinput.field.AbstractFieldView;
import com.izforge.izpack.panels.userinput.field.Field;
import com.izforge.izpack.util.HyperlinkHandler;
import com.izforge.izpack.panels.userinput.gui.rule.RuleInputField;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* GUI presentation of a field.
*
* @author Tim Anderson
*/
public abstract class GUIField extends AbstractFieldView
{
/**
* The components that are the view of the field.
*/
private List components = new ArrayList();
/**
* The listener to notify of field updates.
*/
private UpdateListener listener;
/**
* Holds static label text with variable references which must not be overridden,
* because the variables might change during the installation; for always showing the actual value after resolving.
*/
private final Map untranslatedItems;
/**
* Holds static tooltip text with variable references which must not be overridden,
* because the variables might change during the installation; for always showing the actual value after resolving.
*/
private final Map untranslatedTooltips;
/**
* Constructs a {@code GUIField}.
*
* @param field the field
*/
public GUIField(Field field)
{
super(field);
untranslatedItems = new HashMap();
untranslatedTooltips = new HashMap();
}
/**
* Updates the field from the view.
*
* This implementation simply returns {@code true}.
*
* @param prompt the prompt to display messages
* @return {@code true} if the field was updated, {@code false} if the view is invalid
*/
public boolean updateField(Prompt prompt)
{
return updateField(prompt, false);
}
/**
* Updates the field from the view.
*
* This implementation simply returns {@code true}.
*
* @param prompt the prompt to display messages
* @return {@code true} if the field was updated, {@code false} if the view is invalid
*/
public boolean updateField(Prompt prompt, boolean skipValidation)
{
return true;
}
/**
* Updates the view from the field.
*
* This implementation simply returns {@code false}.
*
* @return {@code true} if the view was updated
*/
public boolean updateView()
{
return translateStaticText();
}
/**
* Returns the components that make up the view.
*
* @return the components
*/
public List getComponents()
{
return components;
}
/**
* Return a {@link JComponent} of this field which is the primary candidate to gain focus.
*
* @return the primary {@link JComponent} to gain focus
*/
public abstract JComponent getFirstFocusableComponent();
/**
* Registers a listener to be notified of field updates.
*
* @param listener the listener to notify
*/
public void setUpdateListener(UpdateListener listener)
{
this.listener = listener;
}
/**
* Adds the field.
*
* This adds the field description (if any), the field label, and field component.
*
* @param component the component
*/
protected void addField(JComponent component)
{
addDescription();
addLabel();
addComponent(component);
}
/**
* Adds the label for the field.
*/
protected void addLabel()
{
addLabel(getField().getLabel());
}
/**
* Adds a label.
*
* @param label the label
*/
protected void addLabel(String label)
{
addComponent(new JLabel(label), new TwoColumnConstraints(TwoColumnConstraints.WEST));
}
/**
* Adds a component.
*
* @param component the component
* @param constraints the component constraints
*/
protected void addComponent(JComponent component, Object constraints)
{
if (component instanceof JTextPane)
{
JTextPane pane = (JTextPane)component;
String oldText = pane.getText();
if (oldText != null)
{
untranslatedItems.put(Integer.valueOf(pane.hashCode()), oldText);
}
}
else if (component instanceof JLabel)
{
JLabel label = (JLabel)component;
String oldText = label.getText();
if (oldText != null)
{
untranslatedItems.put(Integer.valueOf(label.hashCode()), oldText);
}
}
components.add(new Component(component, constraints));
}
/**
* Refresh not editable texts to replace variables
*
* @return whether the text changed
*/
public final boolean translateStaticText()
{
boolean updated = false;
for (Component c : components)
{
JComponent jc = c.getComponent();
if (jc instanceof JTextPane)
{
JTextPane pane = (JTextPane)jc;
pane.setOpaque(false);
String oldText = untranslatedItems.get(Integer.valueOf(jc.hashCode()));
if (oldText != null)
{
String newText = replaceVariables(oldText);
if (!oldText.equals(newText))
{
updated = true;
pane.setText(newText);
}
}
}
else if (jc instanceof JLabel)
{
JLabel label = (JLabel)jc;
String oldText = untranslatedItems.get(Integer.valueOf(label.hashCode()));
if (oldText != null)
{
String newText = replaceVariables(oldText);
if (!oldText.equals(newText))
{
updated = true;
label.setText(newText);
}
}
}
String tooltip = untranslatedTooltips.get(Integer.valueOf(jc.hashCode()));
if (tooltip != null)
{
String newText = replaceVariables(tooltip);
if (!tooltip.equals(newText))
{
jc.setToolTipText(newText);
updated = true;
}
}
}
return updated;
}
/**
* Adds the tooltip to each component in this view.
*/
protected void addTooltip()
{
String tooltipId = getField().getTooltip();
if (tooltipId != null)
{
String tooltip = getInstallData().getMessages().get(tooltipId);
if (tooltip != null)
{
for (Component component : components)
{
untranslatedTooltips.put(Integer.valueOf(component.getComponent().hashCode()), tooltip);
component.getComponent().setToolTipText(tooltip);
JComponent jc = component.getComponent();
if (jc instanceof RuleInputField)
{
RuleInputField rif = (RuleInputField)jc;
for (JTextField input : rif.getInputFields())
{
input.setToolTipText(tooltip);
}
}
}
}
}
}
/**
* Adds a field description to the list of UI elements.
*
* The description spans both columns.
*/
protected void addDescription()
{
addText(getField().getDescription());
}
/**
* Adds a static text field.
*
* The text spans both columns and may include html.
*
* @param text the text. May be {@code null}
*/
protected void addText(String text)
{
if (text != null)
{
TwoColumnConstraints constraints = new TwoColumnConstraints(TwoColumnConstraints.BOTH);
constraints.stretch = true;
JTextPane label = new JTextPane();
// Not editable, but still selectable.
label.setEditable(false);
label.setFocusable(false);
// If html tags are present enable html rendering, otherwise the JTextPane
// looks exactly like MultiLineLabel.
if (text.startsWith("") && text.endsWith(""))
{
label.setContentType("text/html");
label.addHyperlinkListener(new HyperlinkHandler());
}
label.setText(text);
// Background color and font to match the label's.
label.setBackground(UIManager.getColor("label.background"));
label.setMargin(new Insets(3, 0, 3, 0));
// workaround to cut out layout problems
label.getPreferredSize();
// end of workaround.
addComponent(label, constraints);
}
}
/**
* Notifies any registered listener that the view has updated.
*/
protected void notifyUpdateListener()
{
if (listener != null)
{
listener.updated();
}
}
/**
* Returns the installation data.
*
* @return the installation data
*/
protected InstallData getInstallData()
{
return getField().getInstallData();
}
/**
* Helper to replace variables in a string.
*
* @param value the string to perform variable replacement on. May be {@code null}
* @return the string with any variables replaced with their values
*/
protected String replaceVariables(String value)
{
return getInstallData().getVariables().replace(value);
}
/**
* Show localized warning message dialog basing on given parameters.
*
* @param message the message to print out in dialog box.
* @param prompt the prompt to use
*/
protected void warning(String message, Prompt prompt)
{
Messages messages = getInstallData().getMessages();
prompt.warn(messages.get("UserInputPanel.error.caption"), message);
}
/**
* Adds a component.
*
* @param component the component
*/
private void addComponent(JComponent component)
{
addComponent(component, new TwoColumnConstraints(TwoColumnConstraints.EAST));
}
}