/*
* Copyright 2008-2017 the original author or authors.
*
* 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 griffon.swing.support;
import griffon.core.CallableWithArgs;
import griffon.core.RunnableWithArgs;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.KeyStroke;
import java.awt.event.ActionEvent;
import static griffon.util.GriffonNameUtils.isBlank;
import static java.util.Objects.requireNonNull;
/**
* An action implementation that relies on a closure to handle events.
*
* @author Andres Almiray
* @since 2.0.0
*/
public class SwingAction extends AbstractAction {
private static final long serialVersionUID = 4493562556110760713L;
private static final String ERROR_CALLABLE_NULL = "Argument 'callable' must not be null";
private static final String ERROR_RUNNABLE_NULL = "Argument 'runnable' must not be null";
private RunnableWithArgs runnable;
@Deprecated
public SwingAction(@Nonnull final CallableWithArgs<?> callable) {
requireNonNull(callable, ERROR_CALLABLE_NULL);
this.runnable = new RunnableWithArgs() {
@Override
public void run(@Nullable Object... args) {
callable.call(args);
}
};
}
public SwingAction(@Nonnull RunnableWithArgs runnable) {
this.runnable = requireNonNull(runnable, ERROR_RUNNABLE_NULL);
}
@Nonnull
public static ActionBuilder action() {
return new ActionBuilder();
}
@Nonnull
public static ActionBuilder action(@Nullable Action action) {
return new ActionBuilder(action);
}
@Nonnull
public static ActionBuilder action(@Nullable String name) {
return new ActionBuilder().withName(name);
}
public final void actionPerformed(ActionEvent evt) {
runnable.run(evt);
}
/**
* A builder for actions.
*
* @author Andres Almiray
* @since 2.0.0
*/
public static class ActionBuilder {
private String name;
private int mnemonic;
private KeyStroke accelerator;
private String shortDescription;
private String longDescription;
private String command;
private Icon smallIcon;
private Icon largeIcon;
private RunnableWithArgs runnable;
private boolean enabled = true;
private boolean selected = false;
private Action action;
private boolean mnemonicSet = false;
private boolean enabledSet = false;
private boolean selectedSet = false;
public ActionBuilder() {
this(null);
}
@Nonnull
public ActionBuilder(@Nullable Action action) {
this.action = action;
}
@Nonnull
public ActionBuilder withName(@Nullable String name) {
this.name = name;
return this;
}
@Nonnull
public ActionBuilder withShortDescription(@Nullable String shortDescription) {
this.shortDescription = shortDescription;
return this;
}
@Nonnull
public ActionBuilder withLongDescription(@Nullable String longDescription) {
this.longDescription = longDescription;
return this;
}
@Nonnull
public ActionBuilder withCommand(@Nullable String command) {
this.command = command;
return this;
}
@Nonnull
public ActionBuilder withMnemonic(@Nullable String mnemonic) {
if (!isBlank(mnemonic)) {
this.mnemonic = KeyStroke.getKeyStroke(mnemonic).getKeyCode();
}
mnemonicSet = true;
return this;
}
@Nonnull
public ActionBuilder withMnemonic(int mnemonic) {
this.mnemonic = mnemonic;
mnemonicSet = true;
return this;
}
@Nonnull
public ActionBuilder withAccelerator(@Nullable String accelerator) {
if (!isBlank(accelerator)) {
this.accelerator = KeyStroke.getKeyStroke(accelerator);
}
return this;
}
@Nonnull
public ActionBuilder withAccelerator(@Nullable KeyStroke accelerator) {
this.accelerator = accelerator;
return this;
}
@Nonnull
public ActionBuilder withSmallIcon(@Nullable Icon smallIcon) {
this.smallIcon = smallIcon;
return this;
}
@Nonnull
public ActionBuilder withLargeIcon(@Nullable Icon largeIcon) {
this.largeIcon = largeIcon;
return this;
}
@Nonnull
@Deprecated
public ActionBuilder withRunnable(@Nullable final CallableWithArgs<?> callable) {
requireNonNull(callable, ERROR_CALLABLE_NULL);
this.runnable = new RunnableWithArgs() {
@Override
public void run(@Nullable Object... args) {
callable.call(args);
}
};
return this;
}
@Nonnull
public ActionBuilder withRunnable(@Nullable RunnableWithArgs runnable) {
this.runnable = runnable;
return this;
}
@Nonnull
public ActionBuilder withEnabled(boolean enabled) {
this.enabled = enabled;
this.enabledSet = true;
return this;
}
@Nonnull
public ActionBuilder withSelected(boolean selected) {
this.selected = selected;
this.enabledSet = true;
return this;
}
@Nonnull
public Action build() {
if (runnable == null && action == null) {
throw new IllegalArgumentException("Either runnable, callable, or action must have a value.");
}
if (action == null) {
action = new SwingAction(runnable);
}
if (!isBlank(command)) {
action.putValue(Action.ACTION_COMMAND_KEY, command);
}
if (!isBlank(name)) {
action.putValue(Action.NAME, name);
}
if (mnemonicSet) {
action.putValue(Action.MNEMONIC_KEY, mnemonic);
}
if (accelerator != null) {
action.putValue(Action.ACCELERATOR_KEY, accelerator);
}
if (largeIcon != null) {
action.putValue(Action.LARGE_ICON_KEY, largeIcon);
}
if (smallIcon != null) {
action.putValue(Action.SMALL_ICON, smallIcon);
}
if (!isBlank(longDescription)) {
action.putValue(Action.LONG_DESCRIPTION, longDescription);
}
if (!isBlank(shortDescription)) {
action.putValue(Action.SHORT_DESCRIPTION, shortDescription);
}
if (enabledSet) {
action.setEnabled(enabled);
}
if (selectedSet) {
action.putValue(Action.SELECTED_KEY, selected);
}
return action;
}
}
}