--- a/components/visual-panels/core/src/java/vpanels/panel/com/oracle/solaris/vp/panel/swing/control/SwingControl.java Tue Dec 16 05:53:51 2014 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,571 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
- */
-
-package com.oracle.solaris.vp.panel.swing.control;
-
-import java.awt.*;
-import java.beans.*;
-import java.util.Map;
-import javax.swing.*;
-import com.oracle.solaris.vp.panel.common.ClientContext;
-import com.oracle.solaris.vp.panel.common.action.*;
-import com.oracle.solaris.vp.panel.common.control.*;
-import com.oracle.solaris.vp.panel.common.model.*;
-import com.oracle.solaris.vp.panel.swing.action.SwingStructuredAction;
-import com.oracle.solaris.vp.util.misc.*;
-import com.oracle.solaris.vp.util.misc.finder.Finder;
-import com.oracle.solaris.vp.util.swing.*;
-
-public class SwingControl<P extends PanelDescriptor, C extends Component>
- extends DefaultControl<P> implements HasComponent<C>,
- PropertyChangeListener {
-
- //
- // Instance data
- //
-
- private ManagedObject propSource;
- private String[] propNames;
- private boolean ignorePropChange;
-
- private C comp;
- private Stackable<Component> stack;
-
- private SwingStructuredAction<Object, Object, Object> resetAction =
- new SwingStructuredAction<Object, Object, Object>(null, null, null,
- this) {
-
- @Override
- public Object workBusy(Object pInput, Object rtInput)
- throws ActionAbortedException, ActionFailedException,
- ActionUnauthorizedException {
-
- resetAll();
- return null;
- }
- };
-
- private SwingStructuredAction<Object, Object, Object> saveAction =
- new SwingStructuredAction<Object, Object, Object>(null, null, null,
- this) {
-
- @Override
- public Object workBusy(Object pInput, Object rtInput)
- throws ActionAbortedException, ActionFailedException,
- ActionUnauthorizedException {
-
- saveAll();
- return null;
- }
- };
-
- //
- // Constructors
- //
-
- public SwingControl(String id, String name, ClientContext context) {
- super(id, name, context);
- }
-
- public SwingControl(String id, String name, P descriptor) {
- super(id, name, descriptor);
- }
-
- //
- // HasComponent methods
- //
-
- /**
- * Gets the {@code Component} for this {@code SwingControl}.
- *
- * @return a {@code Component}, or {@code null} if this {@code
- * SwingControl} has no {@code Component}.
- *
- * @see #setComponent
- */
- @Override
- public C getComponent() {
- return comp;
- }
-
- //
- // PropertyChangeListener methods
- //
-
- /**
- * Convenience implementation that calls {@link #initComponentOnEventThread}
- * if property changes are not temporarilty being {@link
- * #getPropertyChangeIgnore ignored}. If this {@link SwingControl}'s
- * component displayed the properties of a {@link ManagedObject}, for
- * example, it may make sense to add this {@code SwingControl} as a {@code
- * PropertyListener} to that object.
- */
- @Override
- public void propertyChange(PropertyChangeEvent event) {
- if (!ignorePropChange && getComponent() != null) {
- initComponentOnEventThread();
- }
- }
-
- //
- // Control methods
- //
-
- /**
- * If a) this {@code SwingControl} defines a {@link #getComponentStack
- * Component stack}, b) the just-started {@link Control} implements {@link
- * HasComponent}, and c) its {@code Component} does not yet have a parent,
- * this method adds that {@code Component} to the stack.
- */
- @Override
- public void descendantStarted(Control[] path) {
- super.descendantStarted(path);
-
- final Stackable<Component> stack = getComponentStack();
- if (stack != null) {
- Control control = path[path.length - 1];
- if (control instanceof HasComponent) {
- final Component comp = ((HasComponent)control).getComponent();
- if (comp != null && !(comp instanceof Window) &&
- comp.getParent() == null) {
-
- GUIUtil.invokeAndWait(
- new Runnable() {
- @Override
- public void run() {
- stack.push(comp);
- }
- });
- }
- }
- }
- }
-
- /**
- * If a) this {@code SwingControl} defines a {@link #getComponentStack
- * Component stack}, b) the just-stopped {@link Control} implements {@link
- * HasComponent}, and c) its {@code Component} is at the top of the stack,
- * this method removes that {@code Component} from the stack.
- */
- @Override
- public void descendantStopped(Control[] path) {
- super.descendantStopped(path);
-
- final Stackable<Component> stack = getComponentStack();
- if (stack != null) {
- Control control = path[path.length - 1];
- if (control instanceof HasComponent) {
- final Component comp = ((HasComponent)control).getComponent();
- if (comp != null && !(comp instanceof Window)) {
- GUIUtil.invokeAndWait(
- new Runnable() {
- @Override
- public void run() {
- StackUtil.popIfAtTop(stack, comp);
- }
- });
- }
- }
- }
- }
-
- /**
- * Gets a {@link SwingStructuredAction} that invokes {@link #resetAll},
- * displaying errors.
- */
- @Override
- public SwingStructuredAction<?, ?, ?> getResetAction() {
- return resetAction;
- }
-
- /**
- * Gets a {@link SwingStructuredAction} that invokes {@link #saveAll},
- * displaying errors and prompting for login on {@code
- * ActionUnauthorizedException}s.
- */
- @Override
- public SwingStructuredAction<?, ?, ?> getSaveAction() {
- return saveAction;
- }
-
- /**
- * Prompts the user to save changes, discard changes, or cancel navigation,
- * when navigating away from a {@code Control} with unsaved changes.
- *
- * @see #getUnsavedChangesMessage
- */
- @Override
- protected UnsavedChangesAction getUnsavedChangesAction() {
- String message = getUnsavedChangesMessage();
- if (message == null) {
- message = Finder.getString("settings.unsavedchanges.message");
- }
-
- String title = Finder.getString("settings.unsavedchanges.title");
- int messageType = JOptionPane.WARNING_MESSAGE;
- int optionType = JOptionPane.DEFAULT_OPTION;
- Icon icon = GUIUtil.getIcon(JOptionPane.WARNING_MESSAGE);
-
- Object[] options = {
- Finder.getString("settings.unsavedchanges.button.cancel"),
- Finder.getString("settings.unsavedchanges.button.discard"),
- Finder.getString("settings.unsavedchanges.button.save"),
- };
-
- Object defaultOption = options[0];
-
- int result = JOptionPane.showOptionDialog(getComponent(), message,
- title, optionType, messageType, icon, options, defaultOption);
-
- switch (result) {
- default:
- case 0: return UnsavedChangesAction.CANCEL;
- case 1: return UnsavedChangesAction.DISCARD;
- case 2: return UnsavedChangesAction.SAVE;
- }
- }
-
- /**
- * If this {@code SwingControl} has a {@link #getChangeableAggregator
- * ChangeableAggregator}, returns the value from the aggregator's {@link
- * ChangeableAggregator#isChanged isChanged} method. Otherwise, returns
- * {@code false}.
- */
- @Override
- protected boolean isChanged() {
- ChangeableAggregator aggregator = getChangeableAggregator();
- if (aggregator != null) {
- return aggregator.isChanged();
- }
- return false;
- }
-
- /**
- * If this {@code SwingControl} has a {@link #getChangeableAggregator
- * ChangeableAggregator}, calls its {@link ChangeableAggregator#reset}
- * method on the AWT event thread and waits for its completion.
- */
- @Override
- protected void reset() throws ActionAbortedException, ActionFailedException
- {
- final ChangeableAggregator aggregator = getChangeableAggregator();
- if (aggregator != null) {
- GUIUtil.invokeAndWait(
- new Runnable() {
- @Override
- public void run() {
- aggregator.reset();
- }
- });
- }
- }
-
- /**
- * If this {@code SwingControl} has a {@link #getChangeableAggregator
- * ChangeableAggregator}, calls its {@link ChangeableAggregator#save}
- * method on the AWT event thread and waits for its completion.
- */
- @Override
- protected void save() throws ActionAbortedException, ActionFailedException,
- ActionUnauthorizedException {
-
- final ChangeableAggregator aggregator = getChangeableAggregator();
- if (aggregator != null) {
- GUIUtil.invokeAndWait(
- new Runnable() {
- @Override
- public void run() {
- aggregator.save();
- }
- });
- }
- }
-
- /**
- * Calls the superclass implementation, {@link #getComponentCreate creates}
- * this {@code SwingControl}'s {@code Component} if necessary, then
- * {@link #initComponentOnEventThread initializes} it.
- */
- @Override
- public void start(Navigator navigator, Map<String, String> parameters)
- throws NavigationAbortedException, InvalidParameterException,
- NavigationFailedException {
-
- super.start(navigator, parameters);
-
- if (propSource != null) {
- if (propNames == null) {
- propSource.addPropertyChangeListener(this);
- } else {
- for (String propName : propNames) {
- propSource.addPropertyChangeListener(propName, this);
- }
- }
- }
-
- Component comp = getComponentCreate();
- if (comp != null) {
- initComponentOnEventThread();
- }
- }
-
- /**
- * Calls the superclass implementation, then {@link
- * #deinitComponentOnEventThread deinitializes} this {@code SwingControl}'s
- * {@code Component}.
- *
- * @exception NavigationAbortedException
- * if the navigation is cancelled, or a save fails
- */
- @Override
- public void stop(boolean isCancel) throws NavigationAbortedException {
- super.stop(isCancel);
-
- Component comp = getComponent();
- if (comp != null) {
- deinitComponentOnEventThread();
- }
-
- if (propSource != null) {
- propSource.removePropertyChangeListener(this);
- propSource = null;
- propNames = null;
- }
- }
-
- //
- // SwingControl methods
- //
-
- /**
- * Configures the just-{@code #createComponent created} {@code Component}
- * for this {@code SwingControl}. This method is called automatically just
- * after {@code createComponent}.
- * <p/>
- * Most subclasses can do all configuration in {@link #createComponent}.
- * Only implementors that wish to provide a common configuration for all
- * {@code Component}s created by their subclasses need to implement this
- * method.
- * <p/>
- * Subclasses that override this method should call {@code
- * super.configComponent(comp)} to ensure that any present or future
- * functionality in any superclass implementation is executed.
- * <p/>
- * This default implementation does nothing.
- *
- * @param comp
- * the newly-created {@code Component}
- */
- protected void configComponent(C comp) {
- }
-
- /**
- * Creates the {@code Component} for this {@code SwingControl}.
- * <p/>
- * This default implementation does nothing and returns {@code null}.
- *
- * @return the newly-created {@code Component}
- */
- protected C createComponent() {
- return null;
- }
-
- /**
- * De-initializes the {@code Component} for this {@code SwingControl}. This
- * method is called automatically when this {@code Control} is stopped.
- * <p/>
- * This default implementation does nothing.
- */
- protected void deinitComponent() {
- }
-
- /**
- * Calls {@link #deinitComponent} on the event queue thread and waits until
- * it has completed. This method is called automatically when this {@code
- * Control} is stopped.
- */
- protected void deinitComponentOnEventThread() {
- GUIUtil.invokeAndWait(
- new Runnable() {
- @Override
- public void run() {
- deinitComponent();
- }
- });
- }
-
- /**
- * Gets the {@link ChangeableAggregator}, if any, for this class. This is
- * used in the default implementation of some {@link Control} methods to
- * track changes to this {@code Control}.
- * <p/>
- * This default implementation returns {@code null}.
- *
- * @return a {@link ChangeableAggregator}, or {@code null} if this
- * {@code SwingControl} has none
- */
- public ChangeableAggregator getChangeableAggregator() {
- return null;
- }
-
- /**
- * Gets the {@code Component} for this {@code SwingControl}, {@link
- * #createComponent creating} it, {@code #configComponent configuring} it,
- * and {@code #setComponent setting} it first if necessary.
- * <p/>
- * This method is not thread-safe; external locking may be necessary to
- * ensure that {@link #createComponent} is not called by multiple threads.
- *
- * @return a {@code Component}, or {@code null} if this {@code
- * SwingControl} has no {@code Component}.
- */
- public C getComponentCreate() {
- C comp = getComponent();
- if (comp == null) {
- comp = createComponent();
- if (comp != null) {
- setComponent(comp);
- configComponent(comp);
- }
- }
- return comp;
- }
-
- /**
- * Gets the {@code {@link Stackable}<Component>} to which {@code Component}s
- * of descendant {@code SwingControl}s may be added.
- *
- * @return a {@code {@link Stackable}<Component>}, or {@code null} to
- * defer to {@code SwingControl}s higher in the navigation
- * stack
- */
- public Stackable<Component> getComponentStack() {
- return stack;
- }
-
- /**
- * Gets whether property changes to the {@link #setPropertyChangeSource
- * property change source} are temporarily ignored.
- *
- * @see #setPropertyChangeIgnore
- */
- public boolean getPropertyChangeIgnore() {
- return ignorePropChange;
- }
-
- /**
- * Gets a custom message to display in the dialog that prompts the user to
- * {@link #getUnsavedChangesAction handle unsaved changes}.
- * <p/>
- * This default implementation returns {@code null}.
- *
- * @return a {@code String}, or {@code null} to use the default message
- */
- protected String getUnsavedChangesMessage() {
- return null;
- }
-
- /**
- * Initializes the {@code Component} for this {@code SwingControl}. This
- * method is called automatically when this {@code Control} is started.
- * <p/>
- * This default implementation does nothing.
- */
- protected void initComponent() {
- }
-
- /**
- * Calls {@link #initComponent} on the event queue thread and waits until it
- * has completed. This method is called automatically when this {@code
- * Control} is started.
- */
- protected void initComponentOnEventThread() {
- GUIUtil.invokeAndWait(
- new Runnable() {
- @Override
- public void run() {
- initComponent();
- }
- });
- }
-
- /**
- * Gets the {@code Component} for this {@code SwingControl}.
- *
- * @param comp
- * a {@code Component}, or {@code null} if this {@code
- * SwingControl} has no {@code Component}.
- *
- * @see #getComponent
- */
- protected void setComponent(C comp) {
- this.comp = comp;
- }
-
- /**
- * Sets the {@code {@link Stackable}<Component>} to which {@code Component}s
- * of descendant {@code SwingControl}s may be added.
- *
- * @param stack
- * a {@code {@link Stackable}<Component>} or {@code null} to
- * defer to {@code SwingControl}s higher in the navigation
- * stack
- */
- protected void setComponentStack(Stackable<Component> stack) {
- this.stack = stack;
- }
-
- /**
- * Sets whether property changes to the {@link #setPropertyChangeSource
- * property change source} are temporarily ignored.
- *
- * @see #getPropertyChangeIgnore
- */
- public void setPropertyChangeIgnore(boolean ignorePropChange) {
- this.ignorePropChange = ignorePropChange;
- }
-
- /**
- * Sets a {@link ManagedObject} to which this control should listen
- * for {@code PropertyChangeEvent}s once it is started. Should not
- * be called while the control is started.
- *
- * @param propSource
- * the {@link ManagedObject} to listen to
- *
- * @param propNames
- * the names of the properties in which to listen for changes,
- * or an empty array to listen for changes in all properties on
- * {@code propSource}
- */
- protected void setPropertyChangeSource(ManagedObject propSource,
- String... propNames) {
-
- assert !isStarted();
- this.propSource = propSource;
- this.propNames = propNames == null || propNames.length == 0 ? null :
- propNames;
- }
-}