blob: e4c8c6852727473c9bbfa428554c28b19f936824 [file] [log] [blame]
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* 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.intellij.openapi.ui;
import com.intellij.CommonBundle;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.help.HelpManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.containers.ContainerUtil;
import org.intellij.lang.annotations.MagicConstant;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
/**
* The DialogBuilder is a simpler alternative to {@link DialogWrapper}.
* There is no need to create a subclass (which is needed in the DialogWrapper), which can be nice for simple dialogs.
*/
public class DialogBuilder implements Disposable {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.ui.DialogBuilder");
@NonNls public static final String REQUEST_FOCUS_ENABLED = "requestFocusEnabled";
private JComponent myCenterPanel;
private JComponent myNorthPanel;
private String myTitle;
private JComponent myPreferedFocusComponent;
private String myDimensionServiceKey;
private ArrayList<ActionDescriptor> myActions = null;
private final MyDialogWrapper myDialogWrapper;
private Runnable myCancelOperation = null;
private Runnable myOkOperation = null;
public int show() {
return showImpl(true).getExitCode();
}
public boolean showAndGet() {
return showImpl(true).isOK();
}
public void showNotModal() {
showImpl(false);
}
public DialogBuilder(@Nullable Project project) {
myDialogWrapper = new MyDialogWrapper(project, true);
Disposer.register(myDialogWrapper.getDisposable(), this);
}
public DialogBuilder(@Nullable Component parent) {
myDialogWrapper = new MyDialogWrapper(parent, true);
Disposer.register(myDialogWrapper.getDisposable(), this);
}
public DialogBuilder() {
this(((Project)null));
}
@Override
public void dispose() {
}
private MyDialogWrapper showImpl(boolean isModal) {
LOG.assertTrue(!StringUtil.isEmptyOrSpaces(myTitle),
String.format("Dialog title shouldn't be empty or null: [%s]", myTitle));
myDialogWrapper.setTitle(myTitle);
myDialogWrapper.init();
myDialogWrapper.setModal(isModal);
myDialogWrapper.show();
if (isModal) {
myDialogWrapper.dispose();
}
return myDialogWrapper;
}
public void setCenterPanel(JComponent centerPanel) {
myCenterPanel = centerPanel;
}
@NotNull
public DialogBuilder centerPanel(@NotNull JComponent centerPanel) {
myCenterPanel = centerPanel;
return this;
}
@NotNull
public DialogBuilder setNorthPanel(@NotNull JComponent northPanel) {
myNorthPanel = northPanel;
return this;
}
public void setTitle(String title) {
myTitle = title;
}
@NotNull
public DialogBuilder title(@NotNull String title) {
myTitle = title;
return this;
}
public void setPreferredFocusComponent(JComponent component) {
myPreferedFocusComponent = component;
}
public void setDimensionServiceKey(@NonNls String dimensionServiceKey) {
myDimensionServiceKey = dimensionServiceKey;
}
public DialogBuilder dimensionKey(@NotNull String dimensionServiceKey) {
myDimensionServiceKey = dimensionServiceKey;
return this;
}
public void addAction(Action action) {
addActionDescriptor(new CustomActionDescriptor(action));
}
public <T extends ActionDescriptor> T addActionDescriptor(T actionDescriptor) {
getActionDescriptors().add(actionDescriptor);
return actionDescriptor;
}
private ArrayList<ActionDescriptor> getActionDescriptors() {
if (myActions == null) removeAllActions();
return myActions;
}
public void setActionDescriptors(ActionDescriptor[] descriptors) {
removeAllActions();
ContainerUtil.addAll(myActions, descriptors);
}
public void removeAllActions() {
myActions = new ArrayList<ActionDescriptor>();
}
public Window getWindow() {
return myDialogWrapper.getWindow();
}
public CustomizableAction addOkAction() {
return addActionDescriptor(new OkActionDescriptor());
}
public CustomizableAction addCancelAction() {
return addActionDescriptor(new CancelActionDescriptor());
}
public CustomizableAction addCloseButton() {
CustomizableAction closeAction = addOkAction();
closeAction.setText(CommonBundle.getCloseButtonText());
return closeAction;
}
public void addDisposable(@NotNull Disposable disposable) {
Disposer.register(this, disposable);
}
public void setButtonsAlignment(@MagicConstant(intValues = {SwingConstants.CENTER, SwingConstants.RIGHT}) int alignment) {
myDialogWrapper.setButtonsAlignment(alignment);
}
public DialogWrapper getDialogWrapper() {
return myDialogWrapper;
}
public void showModal(boolean modal) {
if (modal) {
show();
}
else {
showNotModal();
}
}
public void setHelpId(@NonNls String helpId) {
myDialogWrapper.setHelpId(helpId);
}
public void setCancelOperation(Runnable runnable) {
myCancelOperation = runnable;
}
public void setOkOperation(Runnable runnable) {
myOkOperation = runnable;
}
public void setOkActionEnabled(final boolean isEnabled) {
myDialogWrapper.setOKActionEnabled(isEnabled);
}
@NotNull
public DialogBuilder okActionEnabled(boolean isEnabled) {
myDialogWrapper.setOKActionEnabled(isEnabled);
return this;
}
@NotNull
public DialogBuilder resizable(boolean resizable) {
myDialogWrapper.setResizable(resizable);
return this;
}
public CustomizableAction getOkAction() {
return get(getActionDescriptors(), OkActionDescriptor.class);
}
private static CustomizableAction get(final ArrayList<ActionDescriptor> actionDescriptors, final Class aClass) {
for (ActionDescriptor actionDescriptor : actionDescriptors) {
if (actionDescriptor.getClass().isAssignableFrom(aClass)) return (CustomizableAction)actionDescriptor;
}
return null;
}
public CustomizableAction getCancelAction() {
return get(getActionDescriptors(), CancelActionDescriptor.class);
}
public Component getCenterPanel() {
return myCenterPanel;
}
public interface ActionDescriptor {
Action getAction(DialogWrapper dialogWrapper);
}
public abstract static class DialogActionDescriptor implements ActionDescriptor {
private final String myName;
private final Object myMnemonicChar;
private boolean myIsDefault = false;
protected DialogActionDescriptor(String name, int mnemonicChar) {
myName = name;
myMnemonicChar = mnemonicChar == -1 ? null : Integer.valueOf(mnemonicChar);
}
@Override
public Action getAction(DialogWrapper dialogWrapper) {
Action action = createAction(dialogWrapper);
action.putValue(Action.NAME, myName);
if (myMnemonicChar != null) action.putValue(Action.MNEMONIC_KEY, myMnemonicChar);
if (myIsDefault) action.putValue(Action.DEFAULT, Boolean.TRUE);
return action;
}
public void setDefault(boolean isDefault) {
myIsDefault = isDefault;
}
protected abstract Action createAction(DialogWrapper dialogWrapper);
}
public static class CloseDialogAction extends DialogActionDescriptor {
private final int myExitCode;
public CloseDialogAction() {
this(CommonBundle.getCloseButtonText(), -1, DialogWrapper.CLOSE_EXIT_CODE);
}
public CloseDialogAction(String name, int mnemonicChar, int exitCode) {
super(name, mnemonicChar);
myExitCode = exitCode;
}
public static CloseDialogAction createDefault(String name, int mnemonicChar, int exitCode) {
CloseDialogAction closeDialogAction = new CloseDialogAction(name, mnemonicChar, exitCode);
closeDialogAction.setDefault(true);
return closeDialogAction;
}
@Override
protected Action createAction(final DialogWrapper dialogWrapper) {
return new AbstractAction(){
@Override
public void actionPerformed(@NotNull ActionEvent e) {
dialogWrapper.close(myExitCode);
}
};
}
}
public interface CustomizableAction {
void setText(String text);
}
public static class CustomActionDescriptor implements ActionDescriptor {
private final Action myAction;
public CustomActionDescriptor(Action action) {
myAction = action;
}
@Override
public Action getAction(DialogWrapper dialogWrapper) {
return myAction;
}
}
private abstract static class BuiltinAction implements ActionDescriptor, CustomizableAction {
protected String myText = null;
@Override
public void setText(String text) {
myText = text;
}
@Override
public Action getAction(DialogWrapper dialogWrapper) {
Action builtinAction = getBuiltinAction((MyDialogWrapper)dialogWrapper);
if (myText != null) builtinAction.putValue(Action.NAME, myText);
return builtinAction;
}
protected abstract Action getBuiltinAction(MyDialogWrapper dialogWrapper);
}
public static class OkActionDescriptor extends BuiltinAction {
@Override
protected Action getBuiltinAction(MyDialogWrapper dialogWrapper) {
return dialogWrapper.getOKAction();
}
}
public static class CancelActionDescriptor extends BuiltinAction {
@Override
protected Action getBuiltinAction(MyDialogWrapper dialogWrapper) {
return dialogWrapper.getCancelAction();
}
}
private class MyDialogWrapper extends DialogWrapper {
private String myHelpId = null;
private MyDialogWrapper(@Nullable Project project, boolean canBeParent) {
super(project, canBeParent);
}
private MyDialogWrapper(Component parent, boolean canBeParent) {
super(parent, canBeParent);
}
public void setHelpId(String helpId) {
myHelpId = helpId;
}
@Nullable
@Override
protected String getHelpId() {
return myHelpId;
}
@Override
public void init() { super.init(); }
@Override
@NotNull
public Action getOKAction() { return super.getOKAction(); } // Make it public
@Override
@NotNull
public Action getCancelAction() { return super.getCancelAction(); } // Make it public
@Override
protected JComponent createCenterPanel() { return myCenterPanel; }
@Override
protected JComponent createNorthPanel() { return myNorthPanel; }
@Override
public void dispose() {
myPreferedFocusComponent = null;
super.dispose();
}
@Override
public JComponent getPreferredFocusedComponent() {
if (myPreferedFocusComponent != null) return myPreferedFocusComponent;
FocusTraversalPolicy focusTraversalPolicy = null;
Container container = myCenterPanel;
while (container != null && (focusTraversalPolicy = container.getFocusTraversalPolicy()) == null && !(container instanceof Window)) {
container = container.getParent();
}
if (focusTraversalPolicy == null) return null;
Component component = focusTraversalPolicy.getDefaultComponent(myCenterPanel);
while (!(component instanceof JComponent) && component != null) {
component = focusTraversalPolicy.getComponentAfter(myCenterPanel, component);
}
return (JComponent)component;
}
@Override
protected String getDimensionServiceKey() {
return myDimensionServiceKey;
}
@Override
protected JButton createJButtonForAction(Action action) {
JButton button = super.createJButtonForAction(action);
Object value = action.getValue(REQUEST_FOCUS_ENABLED);
if (value instanceof Boolean) button.setRequestFocusEnabled(((Boolean)value).booleanValue());
return button;
}
@Override
public void doCancelAction() {
if (!getCancelAction().isEnabled()) return;
if (myCancelOperation != null) {
myCancelOperation.run();
}
else {
super.doCancelAction();
}
}
@Override
protected void doOKAction() {
if (myOkOperation != null) {
myOkOperation.run();
}
else {
super.doOKAction();
}
}
@Override
protected void doHelpAction() {
if (myHelpId == null) {
super.doHelpAction();
return;
}
HelpManager.getInstance().invokeHelp(myHelpId);
}
@Override
@NotNull
protected Action[] createActions() {
if (myActions == null) return super.createActions();
ArrayList<Action> actions = new ArrayList<Action>(myActions.size());
for (ActionDescriptor actionDescriptor : myActions) {
actions.add(actionDescriptor.getAction(this));
}
if (myHelpId != null) actions.add(getHelpAction());
return actions.toArray(new Action[actions.size()]);
}
}
}