001 /* 002 * Copyright 2002-2008 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 005 * use this file except in compliance with the License. You may obtain a copy of 006 * the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 013 * License for the specific language governing permissions and limitations under 014 * the License. 015 */ 016 package org.springframework.richclient.selection.binding.support; 017 018 import java.awt.BorderLayout; 019 import java.awt.FlowLayout; 020 import java.beans.PropertyChangeListener; 021 022 import javax.swing.JComponent; 023 import javax.swing.JPanel; 024 025 import org.springframework.binding.value.PropertyChangePublisher; 026 import org.springframework.binding.value.support.PropertyChangeSupport; 027 import org.springframework.richclient.application.ApplicationServicesLocator; 028 import org.springframework.richclient.command.ActionCommand; 029 import org.springframework.richclient.command.config.CommandConfigurer; 030 import org.springframework.richclient.dialog.ApplicationDialog; 031 import org.springframework.richclient.factory.AbstractControlFactory; 032 033 /** 034 * <tt>SelectField</tt> base class. Allows for customization of the renderer component. 035 * <p> 036 * A <tt>SelectField</tt> provides a renderer component (provided by subclasses), a select button and a clear button. 037 * The renderer component shows the current value, the select button opens the selection dialog, and the clear button 038 * sets the value to <code>null</code>. 039 * </p> 040 * 041 * @author Peter De Bruycker 042 */ 043 public abstract class SelectField extends AbstractControlFactory implements PropertyChangePublisher { 044 045 private JComponent renderer; 046 private SelectCommand selectCommand = new SelectCommand(); 047 private ClearCommand clearCommand = new ClearCommand(); 048 private boolean editable; 049 private Object value; 050 private ApplicationDialog dialog; 051 private LabelProvider labelProvider; 052 private JPanel control; 053 private boolean nullable = true; 054 055 private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); 056 057 protected JComponent createControl() { 058 control = new JPanel(new BorderLayout()); 059 060 renderer = createRenderer(); 061 control.add(renderer); 062 063 // configure commands 064 CommandConfigurer configurer = (CommandConfigurer) ApplicationServicesLocator.services().getService( 065 CommandConfigurer.class); 066 configurer.configure(selectCommand); 067 configurer.configure(clearCommand); 068 069 JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0)); 070 071 buttonPanel.add(selectCommand.createButton()); 072 if (nullable) { 073 buttonPanel.add(clearCommand.createButton()); 074 } 075 076 control.add(buttonPanel, BorderLayout.LINE_END); 077 078 return control; 079 } 080 081 /** 082 * Create the component that will do the rendering. Cannot return <code>null</code>. 083 * 084 * @return the renderer component 085 */ 086 protected abstract JComponent createRenderer(); 087 088 public void setEnabled(boolean enabled) { 089 control.setEnabled(enabled); 090 091 renderer.setEnabled(enabled); 092 selectCommand.setEnabled(enabled); 093 clearCommand.setEnabled(enabled); 094 } 095 096 public void setEditable(boolean editable) { 097 this.editable = editable; 098 099 selectCommand.setEnabled(control.isEnabled() && editable); 100 clearCommand.setEnabled(control.isEnabled() && editable); 101 } 102 103 public boolean isEditable() { 104 return editable; 105 } 106 107 public void setValue(Object value) { 108 Object oldValue = this.value; 109 this.value = value; 110 111 render(value); 112 113 propertyChangeSupport.firePropertyChange("value", oldValue, value); 114 } 115 116 /** 117 * Convenience method, calls <code>setValue(null)</code>. 118 */ 119 public void clear() { 120 setValue(null); 121 } 122 123 /** 124 * Render the given value. Warning: the value can be <code>null</code>. 125 * 126 * @param value 127 * the value 128 */ 129 protected abstract void render(Object value); 130 131 public Object getValue() { 132 return value; 133 } 134 135 public void setSelectionDialog(ApplicationDialog dialog) { 136 this.dialog = dialog; 137 } 138 139 public void setLabelProvider(LabelProvider labelProvider) { 140 this.labelProvider = labelProvider; 141 } 142 143 public LabelProvider getLabelProvider() { 144 return labelProvider; 145 } 146 147 /** 148 * Returns whether the property is nullable. If set to true, the "clear" button is shown. 149 * 150 * @return whether the property is nullable 151 */ 152 public boolean isNullable() { 153 return nullable; 154 } 155 156 /** 157 * Sets whether the clear button is shown 158 * 159 * @param nullable 160 * whether the clear button is shown 161 */ 162 public void setNullable(boolean nullable) { 163 this.nullable = nullable; 164 } 165 166 private class ClearCommand extends ActionCommand { 167 168 public ClearCommand() { 169 super("selectField.clearCommand"); 170 } 171 172 protected void doExecuteCommand() { 173 clear(); 174 } 175 176 } 177 178 private class SelectCommand extends ActionCommand { 179 180 public SelectCommand() { 181 super("selectField.selectCommand"); 182 } 183 184 protected void doExecuteCommand() { 185 dialog.showDialog(); 186 } 187 } 188 189 public void addPropertyChangeListener(PropertyChangeListener listener) { 190 propertyChangeSupport.addPropertyChangeListener(listener); 191 } 192 193 public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { 194 propertyChangeSupport.addPropertyChangeListener(propertyName, listener); 195 } 196 197 public void removePropertyChangeListener(PropertyChangeListener listener) { 198 propertyChangeSupport.removePropertyChangeListener(listener); 199 } 200 201 public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { 202 propertyChangeSupport.removePropertyChangeListener(propertyName, listener); 203 } 204 }