All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.guise.framework.component.NotificationOptionDialogFrame Maven / Gradle / Ivy

There is a newer version: 0.5.3
Show newest version
/*
 * Copyright © 2005-2008 GlobalMentor, Inc. 
 *
 * 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 io.guise.framework.component;

import java.beans.PropertyVetoException;

import com.globalmentor.net.MediaType;
import com.globalmentor.text.Text;

import io.guise.framework.event.*;
import io.guise.framework.input.*;
import io.guise.framework.model.*;
import io.guise.framework.model.Notification.Option;

import com.globalmentor.beans.*;

/**
 * Default implementation of a frame for communication of an option such as "OK" or "Cancel". An option frame defaults to a single composite child panel with a
 * row of options along the bottom. The contents of an option dialog frame should be accessed by {@link #getOptionContent()} and
 * {@link #setOptionContent(Component)}.
 * 

* This class binds the command {@link ProcessCommand#CONTINUE} to the button for the first non-fatal option. *

* @author Garret Wilson */ public class NotificationOptionDialogFrame extends AbstractOptionDialogFrame { /** * Our input strategy for mapping the "continue" command to the first non-fatal option. As the options are created in the parent constructor, we'll have to * lazily create this instance. */ private BindingInputStrategy bindingInputStrategy = null; /** * Options constructor. Duplicate options are ignored. * @param options The available options. * @throws NullPointerException if the given options is null. */ public NotificationOptionDialogFrame(final Notification.Option... options) { this(new DefaultValueModel(Notification.Option.class), options); //use a default value model } /** * Notification constructor. Duplicate options are ignored. * @param notification The notification that specifies the message and options. * @throws NullPointerException if the given notification is null. #see {@link TextBox} */ public NotificationOptionDialogFrame(final Notification notification) { this(notification.getMessage(), notification.getMessageContentType(), notification.getOptions().toArray(new Notification.Option[notification.getOptions().size()])); //create a dialog from the contents of the notification } /** * Text constructor with a default {@link Text#PLAIN_MEDIA_TYPE} content type. Duplicate options are ignored. * @param text The text, which may include a resource reference, or null if there is no text. * @param options The available options. * @throws NullPointerException if the given options is null. #see {@link TextBox} */ public NotificationOptionDialogFrame(final String text, final Notification.Option... options) { this(text, Text.PLAIN_MEDIA_TYPE, options); //construct the class with a plain text content type } /** * Text and content type constructor Duplicate options are ignored. * @param text The text, which may include a resource reference, or null if there is no text. * @param textContentType The content type of the text. * @param options The available options. * @throws NullPointerException if the given content type and/or options is null. * @throws IllegalArgumentException if the given content type is not a text content type. #see {@link TextBox} */ public NotificationOptionDialogFrame(final String text, final MediaType textContentType, final Notification.Option... options) { this(new TextBox(text, textContentType), options); //create a dialog using a Text component created from the given text and content type } /** * Component and options constructor. Duplicate options are ignored. * @param component The single child component, or null if this frame should have no child component. * @param options The available options. * @throws NullPointerException if the given options is null. */ public NotificationOptionDialogFrame(final Component component, final Notification.Option... options) { this(new DefaultValueModel(Notification.Option.class), component, options); //use a default value model } /** * Value model, and options constructor. Duplicate options are ignored. * @param valueModel The frame value model. * @param options The available options. * @throws NullPointerException if the given value model and or options is null. */ public NotificationOptionDialogFrame(final ValueModel valueModel, final Notification.Option... options) { this(valueModel, null, options); //default to no component } /** * Value model, component, and options constructor. Duplicate options are ignored. * @param valueModel The frame value model. * @param component The component representing the content of the option dialog frame, or null if there is no content component. * @param options The available options. * @throws NullPointerException if the given value model and/or options is null. */ public NotificationOptionDialogFrame(final ValueModel valueModel, final Component component, final Notification.Option... options) { super(valueModel, component, options); //construct the parent class } /** * Opens the frame as modal with a {@link Runnable} to be performed after modality ends successfully. When the frame closes, if a non-fatal option was chosen * the given runnable is executed. This is a convenience method that delegates to {@link Frame#open(com.globalmentor.beans.GenericPropertyChangeListener)}. If * the selected option to any notification is fatal, the specified logic, if any, will not be performed. The absence of an option selection is considered * fatal only if a fatal option was presented for a given notification. * @param afterNotify The code that executes after notification has taken place, or null if no action should be taken after notification. * @see Frame#open(com.globalmentor.beans.GenericPropertyChangeListener) * @see Option#isFatal() */ public void open(final Runnable afterNotify) { open(new AbstractGenericPropertyChangeListener() { //open modally @Override public void propertyChange(final GenericPropertyChangeEvent genericPropertyChangeEvent) { //if the frame modal state changes if(genericPropertyChangeEvent.getNewValue() == null && afterNotify != null) { //if the dialog is now nonmodal and there is logic that should take place after notification final Notification.Option selectedOption = getValue(); //get the selected option, if any //we'll determine if the user selection is fatal and therefore we should not perform the given logic if(selectedOption != null) { //if an option was selected if(selectedOption.isFatal()) { //if a fatal option was selected return; //don't perform the given logic } } else { //if no option was selected, determine if this should be considered fatal for(final Notification.Option option : getOptions()) { //look at the given options; if there is a fatal option available, consider the absence of an option selected to be fatal if(option.isFatal()) { //if a fatal option is available return; //don't perform the given logic } } } afterNotify.run(); //run the code that takes place after notification } } }); } /** * {@inheritDoc} *

* This implementation creates a button for the given option. *

*/ @Override protected Component createOptionComponent(final Notification.Option option) { if(bindingInputStrategy == null) { //if we haven't yet created our input strategy (we have to use lazy creation because this method is called from the parent constructor) bindingInputStrategy = new BindingInputStrategy(getInputStrategy()); //create a new input strategy based upon the current input strategy (if any) setInputStrategy(bindingInputStrategy); //switch to our new input strategy; we'll add bindings later } final Button button = new Button(); //create a new button button.setLabel(option.getLabel()); //set the option action label button.setGlyphURI(option.getGlyph()); //set the option action icon button.addActionListener(new ActionListener() { //listen for the action being performed @Override public void actionPerformed(final ActionEvent actionEvent) { //if the action is performed try { if(option.isFatal() || validate()) { //if this is not a fatal option, first see if the frame validates NotificationOptionDialogFrame.this.setValue(option); //chose this option close(); //close the frame } } catch(final PropertyVetoException propertyVetoException) { //we don't expect a validation exception //TODO fix throw new AssertionError(validationException); } } }); final CommandInput continueCommandInput = new CommandInput(ProcessCommand.CONTINUE); //create a command for continue if(!bindingInputStrategy.isBound(continueCommandInput)) { //if the continue command isn't yet bound to anything if(!option.isFatal()) { //if this is not a fatal option bindingInputStrategy.bind(continueCommandInput, button); //map the "continue" command to the option button } } return button; //return the created button } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy