blob: 9af55b15aaa367f8fdffcfc1f3d59ce7a15796a7 [file] [log] [blame]
/*
* Copyright (C) 2014 The Android Open Source Project
*
* 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.android.tools.idea.wizard.dynamic;
import com.android.tools.idea.ui.ImageComponent;
import com.android.tools.idea.wizard.WizardConstants;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.JBColor;
import com.intellij.uiDesigner.core.GridConstraints;
import com.intellij.uiDesigner.core.GridLayoutManager;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
/**
* Wizard header component
*/
public class WizardStepHeaderPanel extends JPanel {
@NotNull String myTitle = "Title Label";
@Nullable String myDescription;
@Nullable Icon myWizardIcon;
@Nullable Icon myStepIcon;
@Nullable private JLabel myTitleLabel;
@NotNull private ComponentHolder<String, JLabel> myDescriptionLabel = new LabelHolder();
@NotNull private ComponentHolder<Icon, ImageComponent> myWizardIconComponent = new ImageComponentHolder();
@NotNull private ComponentHolder<Icon, ImageComponent> myStepIconComponent = new ImageComponentHolder();
public WizardStepHeaderPanel() {
setBorder(new EmptyBorder(WizardConstants.STUDIO_WIZARD_INSETS));
//noinspection UseJBColor
setForeground(Color.WHITE);
setBackground(WizardConstants.ANDROID_NPW_HEADER_COLOR);
updateHeader();
}
private static GridConstraints createHeaderLabelGridConstraints(int row, int column, int anchor) {
return new GridConstraints(row, column, 1, 1, anchor, GridConstraints.FILL_HORIZONTAL,
GridConstraints.SIZEPOLICY_CAN_GROW | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED,
null, null, null);
}
public static WizardStepHeaderPanel create(@NotNull final JBColor headerColor, @Nullable Icon wizardIcon, @Nullable Icon stepIcon,
@NotNull String title, @Nullable String description) {
final WizardStepHeaderPanel panel = new WizardStepHeaderPanel();
panel.setBackground(headerColor);
panel.setTitle(title);
panel.setDescription(description);
panel.setStepIcon(stepIcon);
panel.setWizardIcon(wizardIcon);
UIManager.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent propertyChangeEvent) {
// Force an update of static JBColor.DARK. This is required to show the correct color after a LookAndFeel change.
JBColor.setDark(UIUtil.isUnderDarcula());
panel.setBackground(headerColor);
// The font size was not set correctly after a LookAndFeel change from Darcula to Standard.
Font font = UIManager.getFont("Label.font");
panel.myTitleLabel.setFont(new Font(font.getFontName(), font.getStyle(), 24));
}
});
return panel;
}
public void setTitle(@Nullable String title) {
myTitle = StringUtil.notNullize(title, "Title Label");
updateHeader();
}
public void setDescription(@Nullable String description) {
myDescription = description;
updateHeader();
}
public void setStepIcon(@Nullable Icon stepIcon) {
myStepIcon = stepIcon;
updateHeader();
}
public void setWizardIcon(@Nullable Icon wizardIcon) {
myWizardIcon = wizardIcon;
updateHeader();
}
private void updateHeader() {
boolean updateLayout = false;
if (myTitleLabel == null) {
myTitleLabel = new JLabel(myTitle);
updateLayout = true;
}
myTitleLabel.setText(myTitle);
updateLayout |= myDescriptionLabel.updateValue(StringUtil.nullize(myDescription, true)) ||
myWizardIconComponent.updateValue(myWizardIcon) ||
myStepIconComponent.updateValue(myStepIcon);
if (updateLayout) {
final int rows = myDescriptionLabel.getComponent() == null ? 1 : 2;
final int columns = 1 + (myWizardIconComponent.getComponent() == null ? 0 : 1) + (myStepIconComponent.getComponent() == null ? 0 : 1);
for (Component component : getComponents()) {
remove(component);
}
setLayout(new GridLayoutManager(rows, columns, new Insets(18, 0, 12, 0), 2, 2));
int currentColumn = addIconIfExists(myWizardIconComponent.getComponent(), 0, rows) ? 1 : 0;
addLabels(myTitleLabel, myDescriptionLabel.getComponent(), currentColumn);
addIconIfExists(myStepIconComponent.getComponent(), currentColumn + 1, rows);
}
}
private void addLabels(@NotNull JLabel titleLabel, @Nullable JLabel descriptionLabel, int column) {
boolean hasDescription = descriptionLabel != null;
int anchor = hasDescription ? GridConstraints.ANCHOR_SOUTHWEST : GridConstraints.ANCHOR_WEST;
titleLabel.setForeground(getForeground());
titleLabel.setFont(titleLabel.getFont().deriveFont(24f));
add(titleLabel, createHeaderLabelGridConstraints(0, column, anchor));
if (hasDescription) {
descriptionLabel.setForeground(getForeground());
add(descriptionLabel, createHeaderLabelGridConstraints(1, column, GridConstraints.ANCHOR_NORTHWEST));
}
}
private boolean addIconIfExists(@Nullable ImageComponent iconComponent, int column, int spanningRows) {
if (iconComponent != null) {
GridConstraints imageConstraints =
new GridConstraints(0, column, spanningRows, 1, GridConstraints.ANCHOR_NORTHWEST, GridConstraints.FILL_NONE,
GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(60, 60), null);
add(iconComponent, imageConstraints);
return true;
}
else {
return false;
}
}
private static abstract class ComponentHolder<V, C extends JComponent> {
@Nullable private C myComponent;
public final boolean updateValue(@Nullable V value) {
boolean updateLayout;
if (value == null) {
updateLayout = myComponent != null;
myComponent = null;
}
else {
if (myComponent == null) {
updateLayout = true;
myComponent = createComponent();
}
else {
updateLayout = false;
}
setValue(myComponent, value);
}
return updateLayout;
}
protected abstract void setValue(@NotNull C component, @NotNull V value);
@NotNull
protected abstract C createComponent();
@Nullable
public final C getComponent() {
return myComponent;
}
}
private static class ImageComponentHolder extends ComponentHolder<Icon, ImageComponent> {
@Override
protected void setValue(@NotNull ImageComponent component, @NotNull Icon value) {
component.setIcon(value);
}
@NotNull
@Override
protected ImageComponent createComponent() {
return new ImageComponent();
}
}
private static class LabelHolder extends ComponentHolder<String, JLabel> {
@Override
protected void setValue(@NotNull JLabel component, @NotNull String value) {
component.setText(value);
}
@NotNull
@Override
protected JLabel createComponent() {
return new JLabel();
}
}
}