001    /*
002     * Copyright 2002-2004 the original author or authors.
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of 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,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.springframework.richclient.command.config;
017    
018    import java.awt.Color;
019    import java.awt.Image;
020    
021    import javax.swing.AbstractButton;
022    import javax.swing.Action;
023    import javax.swing.Icon;
024    import javax.swing.KeyStroke;
025    
026    import org.springframework.binding.value.support.AbstractPropertyChangePublisher;
027    import org.springframework.core.style.ToStringCreator;
028    import org.springframework.richclient.command.AbstractCommand;
029    import org.springframework.richclient.core.ColorConfigurable;
030    import org.springframework.richclient.core.DescribedElement;
031    import org.springframework.richclient.core.DescriptionConfigurable;
032    import org.springframework.richclient.core.VisualizedElement;
033    import org.springframework.richclient.util.Assert;
034    
035    /**
036     * A parameter object that contains the information to describe the visual representation of a 
037     * command object.
038     * 
039     * 
040     * @author Keith Donald
041     */
042    public class CommandFaceDescriptor extends AbstractPropertyChangePublisher implements DescribedElement,
043            VisualizedElement, CommandLabelConfigurable, DescriptionConfigurable, CommandIconConfigurable, ColorConfigurable {
044    
045        /** The property name used when firing events for the {@code labelInfo} property. */
046        public static final String LABEL_INFO_PROPERTY = "labelInfo";
047    
048        /** The property name used when firing events for the {@code icon} property. */
049        public static final String ICON_PROPERTY = "icon";
050    
051        /** The property name used when firing events for the {@code largeIcon} property. */
052        public static final String LARGE_ICON_PROPERTY = "largeIcon";
053    
054        /** The property name used when firing events for the {@code iconInfo} property. */
055        public static final String ICON_INFO_PROPERTY = "iconInfo";
056    
057        /** The property name used when firing events for the {@code largeIconInfo} property. */
058        public static final String LARGE_ICON_INFO_PROPERTY = "largeIconInfo";
059        
060        /** The property name used when firing events for the {@code background} property. */
061        public static final String BACKGROUND_PROPERTY = "background";
062        
063        /** The property name used when firing events for the {@code foreground} property. */
064        public static final String FOREGROUND_PROPERTY = "foreground";
065    
066        private String caption;
067    
068        private String description;
069        
070        private Color background;
071        
072        private Color foreground;
073    
074        private CommandButtonLabelInfo labelInfo;
075    
076        private CommandButtonIconInfo iconInfo = CommandButtonIconInfo.BLANK_ICON_INFO;
077    
078        private CommandButtonIconInfo largeIconInfo = CommandButtonIconInfo.BLANK_ICON_INFO;
079    
080        /**
081         * Creates a new {@code CommandFaceDescriptor} that uses the given encoded label descriptor
082         * to provide the label properties. 
083         *
084         * @param encodedLabel The encoded label descriptor. May be null or empty to define a blank label.
085         * 
086         * @see CommandButtonLabelInfo#valueOf(String)
087         */
088        public CommandFaceDescriptor(String encodedLabel) {
089            this(encodedLabel, null, null);
090        }
091    
092        /**
093         * Creates a new {@code CommandFaceDescriptor} that uses the given encoded label descriptor
094         * to provide the label properties, along with the given icon and caption.
095         *
096         * @param encodedLabel The encoded label descriptor. May be null or empty.
097         * @param icon The main default icon to be displayed by the command. May be null.
098         * @param caption The caption to be displayed on rollover of the command. May be null or empty.
099         * 
100         * @see CommandButtonLabelInfo#valueOf(String)
101         */
102        public CommandFaceDescriptor(String encodedLabel, Icon icon, String caption) {
103            this.labelInfo = CommandButtonLabelInfo.valueOf(encodedLabel);
104            if (icon != null) {
105                this.iconInfo = new CommandButtonIconInfo(icon);
106            }
107            this.caption = caption;
108        }
109    
110        /**
111         * Creates a new {@code CommandFaceDescriptor} with a blank label and no icon or caption.
112         */
113        public CommandFaceDescriptor() {
114            this(CommandButtonLabelInfo.BLANK_BUTTON_LABEL);
115        }
116    
117        /**
118         * Creates a new {@code CommandFaceDescriptor} whose label information is provided by the 
119         * given {@link CommandButtonLabelInfo} instance.
120         *
121         * @param labelInfo The label information for the command.
122         */
123        public CommandFaceDescriptor(CommandButtonLabelInfo labelInfo) {
124            Assert.notNull(labelInfo, "The labelInfo property is required");
125            this.labelInfo = labelInfo;
126        }
127    
128        /**
129         * Returns true if no command label information is provided by this descriptor. 
130         *
131         * @return true if there is no label information, false otherwise.
132         */
133        public boolean isBlank() {
134            return labelInfo == CommandButtonLabelInfo.BLANK_BUTTON_LABEL;
135        }
136    
137        /**
138         * Returns the label text specified by this descriptor.
139         *
140         * @return The label text. May be null or empty.
141         */
142        public String getText() {
143            return labelInfo.getText();
144        }
145    
146        /**
147         * {@inheritDoc}
148         */
149        public String getDisplayName() {
150            return getText();
151        }
152    
153        /**
154         * {@inheritDoc}
155         */
156        public String getCaption() {
157            return caption;
158        }
159    
160        /**
161         * {@inheritDoc}
162         */
163        public String getDescription() {
164            return description;
165        }
166    
167        /**
168         * Returns the mnemonic to be associated with the command.
169         *
170         * @return The command mnemonic.
171         */
172        public int getMnemonic() {
173            return labelInfo.getMnemonic();
174        }
175    
176        /**
177         * Returns the zero-based index of the mnemonic character within the label text associated with
178         * the command. 
179         *
180         * @return The mnemonic index, or -1 if no mnemonic index is associated with the command.
181         */
182        public int getMnemonicIndex() {
183            return labelInfo.getMnemonicIndex();
184        }
185    
186        /**
187         * {@inheritDoc}
188         */
189        public Image getImage() {
190            
191            if (this.iconInfo == null) {
192                return null;
193            }
194            else {
195                return iconInfo.getImage();
196            }
197            
198        }
199    
200        /**
201         * {@inheritDoc}
202         */
203        public Icon getIcon() {
204            
205            if (this.iconInfo == null) {
206                return null;
207            }
208            else {
209                return iconInfo.getIcon();
210            }
211            
212        }
213    
214        /**
215         * Returns the main default large icon associated with the command. 
216         *
217         * @return The large icon, or null.
218         */
219        public Icon getLargeIcon() {
220            
221            if (this.largeIconInfo == null) {
222                return null;
223            }
224            else {
225                return largeIconInfo.getIcon();
226            }
227            
228        }
229    
230        /**
231         * Returns the keystroke accelerator associated with the command.
232         *
233         * @return The keystroke accelerator, or null.
234         */
235        public KeyStroke getAccelerator() {
236            return labelInfo.getAccelerator();
237        }
238    
239        /**
240         * Returns the command button label info object.
241         *
242         * @return The command button label info, or null.
243         */
244        protected CommandButtonLabelInfo getLabelInfo() {
245            return labelInfo;
246        }
247    
248        /**
249         * Returns the label information for the command.
250         *
251         * @return The label information, never null.
252         */
253        protected CommandButtonIconInfo getIconInfo() {
254            return iconInfo;
255        }
256    
257        /**
258         * Returns the large icon information object for the command.
259         *
260         * @return The large icon information, or null.
261         */
262        protected CommandButtonIconInfo getLargeIconInfo() {
263            return largeIconInfo;
264        }
265    
266        /**
267         * {@inheritDoc}
268         */
269        public void setCaption(String shortDescription) {
270            String old = this.caption;
271            this.caption = shortDescription;
272            firePropertyChange(DescribedElement.CAPTION_PROPERTY, old, this.caption);
273        }
274    
275        /**
276         * {@inheritDoc}
277         */
278        public void setDescription(String longDescription) {
279            String old = this.description;
280            this.description = longDescription;
281            firePropertyChange(DescribedElement.DESCRIPTION_PROPERTY, old, this.description);
282        }
283    
284        /**
285         * {@inheritDoc}
286         */
287            public void setBackground(Color background) {
288                    Color old = this.background;
289                    this.background = background;
290                    firePropertyChange(BACKGROUND_PROPERTY, old, this.background);
291            }
292    
293        /**
294         * {@inheritDoc}
295         */
296            public void setForeground(Color foreground) {
297                    Color old = this.foreground;
298                    this.foreground = foreground;
299                    firePropertyChange(FOREGROUND_PROPERTY, old, this.foreground);          
300            }
301    
302        /**
303         * Sets the label information for the command using the given encoded label descriptor.
304         *
305         * @param encodedLabelInfo The encoded label descriptor. May be null or empty.
306         * 
307         * @see CommandButtonLabelInfo#valueOf(String)
308         */
309        public void setButtonLabelInfo(String encodedLabelInfo) {
310            CommandButtonLabelInfo newLabelInfo = CommandButtonLabelInfo.valueOf(encodedLabelInfo);
311            setLabelInfo(newLabelInfo);
312        }
313    
314        /**
315         * {@inheritDoc}
316         */
317        public void setLabelInfo(CommandButtonLabelInfo labelInfo) {
318            if (labelInfo == null) {
319                labelInfo = CommandButtonLabelInfo.BLANK_BUTTON_LABEL;
320            }
321            CommandButtonLabelInfo old = this.labelInfo;
322            this.labelInfo = labelInfo;
323            firePropertyChange(LABEL_INFO_PROPERTY, old, this.labelInfo);
324        }
325    
326        /**
327         * {@inheritDoc}
328         */
329        public void setIconInfo(CommandButtonIconInfo iconInfo) {
330            if (iconInfo == null) {
331                iconInfo = CommandButtonIconInfo.BLANK_ICON_INFO;
332            }
333            CommandButtonIconInfo old = this.iconInfo;
334            this.iconInfo = iconInfo;
335            firePropertyChange(ICON_INFO_PROPERTY, old, this.iconInfo);
336        }
337    
338        /**
339         * {@inheritDoc}
340         */
341        public void setLargeIconInfo(CommandButtonIconInfo largeIconInfo) {
342            if (largeIconInfo == null) {
343                largeIconInfo = CommandButtonIconInfo.BLANK_ICON_INFO;
344            }
345            CommandButtonIconInfo old = this.largeIconInfo;
346            this.largeIconInfo = largeIconInfo;
347            firePropertyChange(LARGE_ICON_INFO_PROPERTY, old, this.largeIconInfo);
348        }
349    
350        /**
351         * Set the main default icon to be associated with the command.
352         *
353         * @param icon The main default icon. May be null.
354         */
355        public void setIcon(Icon icon) {
356            Icon old = null;
357            if (iconInfo == CommandButtonIconInfo.BLANK_ICON_INFO) {
358                if (icon != null) {
359                    // New IconInfo fires event
360                    setIconInfo(new CommandButtonIconInfo(icon));
361                }
362            }
363            else {
364                old = iconInfo.getIcon();
365                this.iconInfo.setIcon(icon);
366            }
367            firePropertyChange(ICON_PROPERTY, old, icon);
368        }
369    
370        /**
371         * Sets the main default large icon for the command.
372         *
373         * @param icon The large icon. May be null.
374         */
375        public void setLargeIcon(Icon icon) {
376            Icon old = null;
377            if (largeIconInfo == CommandButtonIconInfo.BLANK_ICON_INFO) {
378                if (icon != null) {
379                    // new IconInfo fires event
380                    setLargeIconInfo(new CommandButtonIconInfo(icon));
381                }
382            }
383            else {
384                old = largeIconInfo.getIcon();
385                this.largeIconInfo.setIcon(icon);
386            }
387            firePropertyChange(LARGE_ICON_PROPERTY, old, icon);
388        }
389    
390        /**
391         * Configures the given button with the label information contained in this descriptor.
392         *
393         * @param button The button to be configured. Must not be null.
394         * 
395         * @throws IllegalArgumentException if {@code button} is null.
396         */
397        public void configureLabel(AbstractButton button) {
398            Assert.required(button, "button");
399            labelInfo.configure(button);
400        }
401    
402        /**
403         * Configures the given button with the icon information contained in this descriptor.
404         *
405         * @param button The button to be configured. Must not be null.
406         * 
407         * @throws IllegalArgumentException if {@code button} is null.
408         */
409        public void configureIcon(AbstractButton button) {
410            Assert.required(button, "button");
411            configureIconInfo(button, false);
412        }
413    
414        /**
415         * Configures the given button with the icon information contained in this descriptor.
416         *
417         * @param button The button to be configured. Must not be null.
418         * @param useLargeIcons Set to true to configure the button with large icons. False will use
419         * default size icons.
420         * 
421         * @throws IllegalArgumentException if {@code button} is null.
422         */
423        public void configureIconInfo(AbstractButton button, boolean useLargeIcons) {
424            
425            Assert.required(button, "button");
426            
427            if (useLargeIcons) {
428                largeIconInfo.configure(button);
429            }
430            else {
431                iconInfo.configure(button);
432            }
433        }
434        
435        /**
436         * Configures the given button with colours for background and foreground if available.
437         * 
438         * @param button The button to be configured. Must not be null.
439         */
440        public void configureColor(AbstractButton button) {
441            Assert.required(button, "button");
442            if (foreground != null) {
443                    button.setForeground(foreground);
444            }
445            if (background != null) {
446                    button.setBackground(background);
447            }
448        }
449    
450        /**
451         * Configures the given button and command using the given configurer and the information 
452         * contained in this instance.
453         *
454         * @param button The button to be configured. Must not be null.
455         * @param command The command to be configured. May be null.
456         * @param configurer The configurer. Must not be null.
457         * 
458         * @throws IllegalArgumentException if {@code button} or {@code configurer} are null.
459         */
460        public void configure(AbstractButton button, AbstractCommand command, CommandButtonConfigurer configurer) {
461            Assert.required(button, "button");
462            Assert.required(configurer, "configurer");
463            configurer.configure(button, command, this);
464        }
465    
466        /**
467         * Configures the given action with the information contained in this descriptor.
468         *
469         * @param action The action to be configured. Must not be null.
470         * 
471         * @throws IllegalArgumentException if {@code action} is null.
472         */
473        public void configure(Action action) {
474            Assert.notNull(action, "The swing action to configure is required");
475            action.putValue(Action.NAME, getText());
476            action.putValue(Action.MNEMONIC_KEY, new Integer(getMnemonic()));
477            action.putValue(Action.SMALL_ICON, getIcon());
478            action.putValue("LargeIcon", getLargeIcon());
479            action.putValue(Action.ACCELERATOR_KEY, getAccelerator());
480            action.putValue(Action.SHORT_DESCRIPTION, caption);
481            action.putValue(Action.LONG_DESCRIPTION, description);
482        }
483    
484        /**
485         * {@inheritDoc}
486         */
487        public String toString() {
488            return new ToStringCreator(this).append("caption", caption).append("description", description).append(
489                    "buttonLabelInfo", labelInfo).append("buttonIconInfo", iconInfo).toString();
490        }
491    }