Revision: 1342
Author:   mathiasbr
Date:     2006-08-25 08:01:15 -0700 (Fri, 25 Aug 2006)
ViewCVS:  http://svn.sourceforge.net/spring-rich-c/?rev=1342&view=rev

Log Message:
-----------
allow subclasses to define custom conditional constraints for enabled and 
visible state.

Modified Paths:
--------------
    
trunk/spring-richclient/support/src/main/java/org/springframework/richclient/command/AbstractCommand.java

Added Paths:
-----------
    
trunk/spring-richclient/support/src/test/java/org/springframework/richclient/command/support/AdditionalStateTestCommand.java
    
trunk/spring-richclient/support/src/test/java/org/springframework/richclient/command/support/ButtonTests.java

Removed Paths:
-------------
    
trunk/spring-richclient/support/src/test/java/org/springframework/richclient/command/support/ButtonEnablingTests.java
Modified: 
trunk/spring-richclient/support/src/main/java/org/springframework/richclient/command/AbstractCommand.java
===================================================================
--- 
trunk/spring-richclient/support/src/main/java/org/springframework/richclient/command/AbstractCommand.java
   2006-08-25 08:28:12 UTC (rev 1341)
+++ 
trunk/spring-richclient/support/src/main/java/org/springframework/richclient/command/AbstractCommand.java
   2006-08-25 15:01:15 UTC (rev 1342)
@@ -32,9 +32,7 @@
 
 import org.springframework.beans.factory.BeanNameAware;
 import org.springframework.beans.factory.InitializingBean;
-import org.springframework.binding.value.ValueModel;
 import 
org.springframework.binding.value.support.AbstractPropertyChangePublisher;
-import org.springframework.binding.value.support.ValueHolder;
 import org.springframework.core.style.ToStringCreator;
 import org.springframework.richclient.application.ApplicationServicesLocator;
 import org.springframework.richclient.command.config.CommandButtonConfigurer;
@@ -47,6 +45,7 @@
 import org.springframework.richclient.factory.ButtonFactory;
 import org.springframework.richclient.factory.LabelInfoFactory;
 import org.springframework.richclient.factory.MenuFactory;
+import org.springframework.util.Assert;
 import org.springframework.util.CachingMapDecorator;
 import org.springframework.util.StringUtils;
 
@@ -63,14 +62,12 @@
 
     private String defaultFaceDescriptorId = DEFAULT_FACE_DESCRIPTOR_ID;
 
-    private ValueModel enabled = new ValueHolder(Boolean.TRUE);
+    private boolean enabled = true;
 
     private boolean visible = true;
     
     private boolean authorized = true;
     
-    private boolean maskedEnabledState = true;
-
     private String securityControllerId = null;
 
     private Map faceButtonManagers;
@@ -79,12 +76,19 @@
 
     private CommandFaceDescriptorRegistry faceDescriptorRegistry;
 
+    private boolean oldEnabledState = enabled;
+
+    private boolean oldVisibleState = visible;
+
     protected AbstractCommand() {
         this(null);
     }
 
     protected AbstractCommand(String id) {
-        this(id, (CommandFaceDescriptor)null);
+        super();
+        setId(id);
+        addEnabledListener(new ButtonEnablingListener()); // keep track of 
enable state for buttons
+        addPropertyChangeListener(VISIBLE_PROPERTY_NAME, new 
ButtonVisibleListener()); // keep track of visible state for buttons
     }
 
     protected AbstractCommand(String id, String encodedLabel) {
@@ -96,18 +100,14 @@
     }
 
     protected AbstractCommand(String id, CommandFaceDescriptor faceDescriptor) 
{
-        super();
-        setId(id);
-        addEnabledListener(new ButtonEnablingListener()); // keep track of 
enable state for buttons
+        this(id);
         if (faceDescriptor != null) {
             setFaceDescriptor(faceDescriptor);
         }
     }
 
     protected AbstractCommand(String id, Map faceDescriptors) {
-        super();
-        setId(id);
-        addEnabledListener(new ButtonEnablingListener()); // keep track of 
enable state for buttons
+        this(id);
         setFaceDescriptors(faceDescriptors);
     }
 
@@ -137,6 +137,7 @@
     }
 
     public void setFaceDescriptors(Map faceDescriptors) {
+        Assert.notNull(faceDescriptors);
         Iterator it = faceDescriptors.entrySet().iterator();
         while (it.hasNext()) {
             Map.Entry entry = (Map.Entry)it.next();
@@ -275,25 +276,12 @@
      * it can not be enabled.
      * @param authorized Pass <code>true</code> if the object is to be 
authorized
      */
-    public void setAuthorized( boolean authorized ) {
+    public void setAuthorized(boolean authorized) {
         boolean wasAuthorized = isAuthorized();
-
-        if( hasChanged(isAuthorized(), authorized)) {
-            
+        if (hasChanged(wasAuthorized, authorized)) {
             this.authorized = authorized;
-
-            // We need to apply a change to our enabled state depending on our
-            // new authorized state.
-            if( authorized ) {
-                // install the last requested enabled state
-                setEnabled(maskedEnabledState);
-            } else {
-                // Record the current enabled state and then disable
-                maskedEnabledState = isEnabled();
-                internalSetEnabled(false);
-            }
-            
-            firePropertyChange(AUTHORIZED_PROPERTY, !wasAuthorized, 
authorized);
+            firePropertyChange(AUTHORIZED_PROPERTY, wasAuthorized, authorized);
+            updatedEnabledState();
         }
     }
     
@@ -305,9 +293,29 @@
         return authorized;
     }
 
+    /**
+     * Get the enabled state
+     * @return if the command is enabled and [EMAIL PROTECTED] 
#isAuthorized()} returns true
+     * @see #isAuthorized()
+     */
     public boolean isEnabled() {
-        return ((Boolean)enabled.getValue()).booleanValue();
+        return enabled && isAuthorized();
     }
+    
+    /**
+     * This method is called when any predicate for enabled state has changed. 
This implemetation fires the enabled
+     * changed event if the return value of [EMAIL PROTECTED] #isEnabled()} 
has changed.
+     * <p>
+     * Sublcasses which have an additional predicate to enabled state must 
call this method if the state of the
+     * predicate changes.
+     */
+    protected void updatedEnabledState() {
+        boolean isEnabled = isEnabled();
+        if(hasChanged(oldEnabledState, isEnabled)) {
+            firePropertyChange(ENABLED_PROPERTY_NAME, oldEnabledState, 
isEnabled);
+        }
+        oldEnabledState = isEnabled;
+    }
 
     /**
      * Set the enabled state of this command.  Note that if we are currently 
not
@@ -316,25 +324,13 @@
      * @param enabled state
      */
     public void setEnabled(boolean enabled) {
-        maskedEnabledState = enabled;
-        if( isAuthorized() ) {
-            internalSetEnabled( enabled );
+        if( hasChanged(this.enabled, enabled)) {
+            this.enabled = enabled;
+            updatedEnabledState();
         }
     }
 
     /**
-     * Internal method to set the enabled state.  This is needed so that calls
-     * made to the public setEnabled and this method can be handled 
differently.
-     * @param enabled state
-     * @see #setAuthorized(boolean)
-     */
-    protected void internalSetEnabled( boolean enabled ) {
-        if (hasChanged(isEnabled(), enabled)) {
-            this.enabled.setValue(Boolean.valueOf(enabled));
-        }
-    }
-    
-    /**
      * Listener to keep track of enabled state. When enable on command changes,
      * each button has to be checked and set.
      */
@@ -350,17 +346,38 @@
             while (it.hasNext()) 
             {
                  AbstractButton button = (AbstractButton)it.next();
-                   button.setEnabled(enabled);
+                 button.setEnabled(enabled);
             }
         }
     }
 
+    /**
+     * Listener to keep track of visible state. When visible on command 
changes,
+     * each button has to be checked and set.
+     */
+    private class ButtonVisibleListener implements PropertyChangeListener
+    {
+        public void propertyChange(PropertyChangeEvent evt)
+        {
+            // We need to keep the buttons in sync with the command, so go 
through the buttons and set visible state.
+            // alternative is to add a listener to the visible value and 
change buttons in that listener 
+            // NOT redundant
+            boolean enabled = evt.getNewValue() == Boolean.TRUE ? true : false;
+            Iterator it = buttonIterator();
+            while (it.hasNext()) 
+            {
+                 AbstractButton button = (AbstractButton)it.next();
+                 button.setVisible(enabled);
+            }
+        }
+    }
+
     public void addEnabledListener(PropertyChangeListener listener) {
-        enabled.addValueChangeListener(listener);
+        addPropertyChangeListener(ENABLED_PROPERTY_NAME, listener);
     }
 
     public void removeEnabledListener(PropertyChangeListener listener) {
-        enabled.removeValueChangeListener(listener);
+        removePropertyChangeListener(ENABLED_PROPERTY_NAME, listener);
     }
 
     protected final Iterator defaultButtonIterator() {
@@ -442,13 +459,24 @@
     public void setVisible(boolean value) {
         if (visible != value) {
             this.visible = value;
-            for (Iterator it = buttonIterator(); it.hasNext();) {
-                AbstractButton button = (AbstractButton)it.next();
-                button.setVisible(visible);
-            }
-            firePropertyChange(VISIBLE_PROPERTY_NAME, !visible, visible);
+            updatedVisibleState();
         }
     }
+    
+    /**
+     * This method is called when any predicate for visible state has changed. 
This implemetation fires the visible
+     * changed event if the return value of [EMAIL PROTECTED] #isVisible()} 
has changed.
+     * <p>
+     * Sublcasses which have an additional predicate to visible state must 
call this method if the state of the
+     * predicate changes.
+     */
+    protected void updatedVisibleState() {
+        boolean isVisible = isVisible();
+        if(hasChanged(oldVisibleState, isVisible)) {
+            firePropertyChange(VISIBLE_PROPERTY_NAME, oldVisibleState, 
isVisible);
+        }
+        oldVisibleState = isVisible;
+    }
 
     public final AbstractButton createButton() {
         return createButton(getDefaultFaceDescriptorId(), getButtonFactory(), 
getDefaultButtonConfigurer());

Added: 
trunk/spring-richclient/support/src/test/java/org/springframework/richclient/command/support/AdditionalStateTestCommand.java
===================================================================
--- 
trunk/spring-richclient/support/src/test/java/org/springframework/richclient/command/support/AdditionalStateTestCommand.java
                                (rev 0)
+++ 
trunk/spring-richclient/support/src/test/java/org/springframework/richclient/command/support/AdditionalStateTestCommand.java
        2006-08-25 15:01:15 UTC (rev 1342)
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2002-2004 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 org.springframework.richclient.command.support;
+
+import org.springframework.richclient.command.ActionCommand;
+
+/**
+ * @author Peter De Bruycker
+ */
+public class AdditionalStateTestCommand extends ActionCommand {
+
+    private boolean myenabledState = true;
+    
+    private boolean myvisibleState = true;
+
+    public AdditionalStateTestCommand() {
+    }
+
+    public AdditionalStateTestCommand(String id) {
+        super(id);
+    }
+
+    /**
+     * @see 
org.springframework.richclient.command.ActionCommand#doExecuteCommand()
+     */
+    protected void doExecuteCommand() {
+    }
+
+    public boolean isMyenabledState() {
+        return myenabledState;
+    }
+
+    public boolean isEnabled() {
+        return super.isEnabled() && isMyenabledState();
+    }
+    
+    public void setMyenabledState(boolean myenabledState) {
+        if (hasChanged(myenabledState, isMyenabledState())) {
+            this.myenabledState = myenabledState;
+            updatedEnabledState();
+        }
+    }
+    
+    public boolean isVisible() {
+        return super.isVisible() && isMyvisibleState();
+    }
+
+    public boolean isMyvisibleState() {
+        return myvisibleState;
+    }
+
+    public void setMyvisibleState(boolean myvisibleState) {
+        if (hasChanged(myvisibleState, isMyvisibleState())) {
+            this.myvisibleState = myvisibleState;
+            updatedVisibleState();
+        }
+    }
+}
\ No newline at end of file


Property changes on: 
trunk/spring-richclient/support/src/test/java/org/springframework/richclient/command/support/AdditionalStateTestCommand.java
___________________________________________________________________
Name: svn:keywords
   + URL Author Revision Date
Name: svn:eol-style
   + native

Deleted: 
trunk/spring-richclient/support/src/test/java/org/springframework/richclient/command/support/ButtonEnablingTests.java
===================================================================
--- 
trunk/spring-richclient/support/src/test/java/org/springframework/richclient/command/support/ButtonEnablingTests.java
       2006-08-25 08:28:12 UTC (rev 1341)
+++ 
trunk/spring-richclient/support/src/test/java/org/springframework/richclient/command/support/ButtonEnablingTests.java
       2006-08-25 15:01:15 UTC (rev 1342)
@@ -1,86 +0,0 @@
-package org.springframework.richclient.command.support;
-
-import javax.swing.AbstractButton;
-
-import org.springframework.binding.value.support.EqualsValueChangeDetector;
-import org.springframework.richclient.application.ApplicationServicesLocator;
-import 
org.springframework.richclient.application.config.ApplicationObjectConfigurer;
-import 
org.springframework.richclient.application.support.DefaultApplicationServices;
-import org.springframework.richclient.command.AbstractCommand;
-import org.springframework.richclient.command.config.CommandFaceDescriptor;
-import org.springframework.richclient.test.SpringRichTestCase;
-
-
-public class ButtonEnablingTests extends SpringRichTestCase
-{
-    
-    /**
-     * May be implemented in subclasses that need to register services with 
the global
-     * application services instance.
-     */
-    protected void registerAdditionalServices( DefaultApplicationServices 
applicationServices ) {
-        applicationServices.setValueChangeDetector(new 
EqualsValueChangeDetector());
-    }
-
-    public void testButtonEnabling()
-    {
-        TestCommand testCommand = new TestCommand();
-        AbstractButton button = testCommand.createButton();
-        AbstractButton button2 = testCommand.createButton();
-        enableTests(testCommand, new Object[]{button, button2});
-    }
-    
-    public void enableTests(AbstractCommand command, Object[] buttons)
-    {
-        enableTest(command, buttons, false);
-        enableTest(command, buttons, true);
-    }
-    
-    public void enableTest(AbstractCommand command, Object[] buttons, boolean 
enable)
-    {
-        command.setEnabled(enable);
-        assertEquals(command.isEnabled(), enable);
-        for (int i = 0; i < buttons.length; ++i)
-        {
-            assertEquals(((AbstractButton)buttons[i]).isEnabled(), enable);    
-        }        
-    }
-    
-    // testing different sequences because error was in sequence of hashmap:
-    public void testMultipleFaceDescriptorsEnabling()
-    {
-        multipleFaceDescriptorSequence("face1", "face2", "face3");
-        multipleFaceDescriptorSequence("face1", "face3", "face2");
-
-        multipleFaceDescriptorSequence("face2", "face1", "face3");
-        multipleFaceDescriptorSequence("face2", "face3", "face1");
-
-        multipleFaceDescriptorSequence("face3", "face2", "face1");
-        multipleFaceDescriptorSequence("face3", "face1", "face2");
-    }
-
-    private void multipleFaceDescriptorSequence(String face1, String face2, 
String face3)
-    {
-        TestCommand testCommand = new TestCommand();
-        registerCommandFaceDescriptor(face1, testCommand);
-        registerCommandFaceDescriptor(face2, testCommand);
-        registerCommandFaceDescriptor(face3, testCommand);
-
-        AbstractButton face1button = testCommand.createButton(face1);
-        enableTests(testCommand, new Object[]{face1button});
-        
-        AbstractButton face2button = testCommand.createButton(face2);
-        enableTests(testCommand, new Object[]{face1button, face2button});
-        
-        AbstractButton face3button = testCommand.createButton(face3);
-        enableTests(testCommand, new Object[]{face1button, face2button, 
face3button});
-    }
-    
-    private void registerCommandFaceDescriptor(String faceId, AbstractCommand 
command)
-    {
-        CommandFaceDescriptor face = new CommandFaceDescriptor();
-        ApplicationObjectConfigurer configurer = 
(ApplicationObjectConfigurer)ApplicationServicesLocator.services().getService(ApplicationObjectConfigurer.class);
-        configurer.configure(face, faceId);
-        command.setFaceDescriptor(faceId, face);        
-    }
-}

Copied: 
trunk/spring-richclient/support/src/test/java/org/springframework/richclient/command/support/ButtonTests.java
 (from rev 1341, 
trunk/spring-richclient/support/src/test/java/org/springframework/richclient/command/support/ButtonEnablingTests.java)
===================================================================
--- 
trunk/spring-richclient/support/src/test/java/org/springframework/richclient/command/support/ButtonTests.java
                               (rev 0)
+++ 
trunk/spring-richclient/support/src/test/java/org/springframework/richclient/command/support/ButtonTests.java
       2006-08-25 15:01:15 UTC (rev 1342)
@@ -0,0 +1,142 @@
+package org.springframework.richclient.command.support;
+
+import javax.swing.AbstractButton;
+
+import org.springframework.binding.value.support.EqualsValueChangeDetector;
+import org.springframework.richclient.application.ApplicationServicesLocator;
+import 
org.springframework.richclient.application.config.ApplicationObjectConfigurer;
+import 
org.springframework.richclient.application.support.DefaultApplicationServices;
+import org.springframework.richclient.command.AbstractCommand;
+import org.springframework.richclient.command.config.CommandFaceDescriptor;
+import org.springframework.richclient.test.SpringRichTestCase;
+
+
+public class ButtonTests extends SpringRichTestCase
+{
+    
+    /**
+     * May be implemented in subclasses that need to register services with 
the global
+     * application services instance.
+     */
+    protected void registerAdditionalServices( DefaultApplicationServices 
applicationServices ) {
+        applicationServices.setValueChangeDetector(new 
EqualsValueChangeDetector());
+    }
+
+    public void testButtonEnabling()
+    {
+        TestCommand testCommand = new TestCommand();
+        AbstractButton button = testCommand.createButton();
+        AbstractButton button2 = testCommand.createButton();
+        enableTests(testCommand, new Object[]{button, button2});
+    }
+    
+    public void enableTests(AbstractCommand command, Object[] buttons)
+    {
+        enableTest(command, buttons, false);
+        enableTest(command, buttons, true);
+    }
+    
+    public void enableTest(AbstractCommand command, Object[] buttons, boolean 
enable)
+    {
+        command.setEnabled(enable);
+        assertEquals(command.isEnabled(), enable);
+        for (int i = 0; i < buttons.length; ++i)
+        {
+            assertEquals(enable, ((AbstractButton)buttons[i]).isEnabled());    
+        }        
+    }
+    
+    public void testButtonVisible()
+    {
+        TestCommand testCommand = new TestCommand();
+        AbstractButton button = testCommand.createButton();
+        AbstractButton button2 = testCommand.createButton();
+        visibleTests(testCommand, new Object[]{button, button2});
+    }
+    
+    public void visibleTests(AbstractCommand command, Object[] buttons)
+    {
+        enableTest(command, buttons, false);
+        enableTest(command, buttons, true);
+    }
+    
+    public void visibleTest(AbstractCommand command, Object[] buttons, boolean 
visible)
+    {
+        command.setVisible(visible);
+        assertEquals(command.isVisible(), visible);
+        for (int i = 0; i < buttons.length; ++i)
+        {
+            assertEquals(visible, ((AbstractButton)buttons[i]).isVisible());   
 
+        }        
+    }
+
+    // testing different sequences because error was in sequence of hashmap:
+    public void testMultipleFaceDescriptorsEnabling()
+    {
+        multipleFaceDescriptorSequence("face1", "face2", "face3");
+        multipleFaceDescriptorSequence("face1", "face3", "face2");
+
+        multipleFaceDescriptorSequence("face2", "face1", "face3");
+        multipleFaceDescriptorSequence("face2", "face3", "face1");
+
+        multipleFaceDescriptorSequence("face3", "face2", "face1");
+        multipleFaceDescriptorSequence("face3", "face1", "face2");
+    }
+
+    private void multipleFaceDescriptorSequence(String face1, String face2, 
String face3)
+    {
+        TestCommand testCommand = new TestCommand();
+        registerCommandFaceDescriptor(face1, testCommand);
+        registerCommandFaceDescriptor(face2, testCommand);
+        registerCommandFaceDescriptor(face3, testCommand);
+
+        AbstractButton face1button = testCommand.createButton(face1);
+        enableTests(testCommand, new Object[]{face1button});
+        
+        AbstractButton face2button = testCommand.createButton(face2);
+        enableTests(testCommand, new Object[]{face1button, face2button});
+        
+        AbstractButton face3button = testCommand.createButton(face3);
+        enableTests(testCommand, new Object[]{face1button, face2button, 
face3button});
+    }
+    
+    private void registerCommandFaceDescriptor(String faceId, AbstractCommand 
command)
+    {
+        CommandFaceDescriptor face = new CommandFaceDescriptor();
+        ApplicationObjectConfigurer configurer = 
(ApplicationObjectConfigurer)ApplicationServicesLocator.services().getService(ApplicationObjectConfigurer.class);
+        configurer.configure(face, faceId);
+        command.setFaceDescriptor(faceId, face);        
+    }
+    
+    /**
+     * Tests if a command subclass can use an additional condition when enable 
is enabled or not
+     * @throws Exception
+     */
+    public void testAdditionalConditionToEnable() throws Exception {
+        AdditionalStateTestCommand testCommand = new 
AdditionalStateTestCommand();
+        AbstractButton button = testCommand.createButton();
+        assertEquals(testCommand.isEnabled(), button.isEnabled());
+        testCommand.setMyenabledState(false);
+        assertEquals(false, testCommand.isEnabled());
+        assertEquals(testCommand.isEnabled(), button.isEnabled());
+        testCommand.setMyenabledState(true);
+        assertEquals(true, testCommand.isEnabled());
+        assertEquals(testCommand.isEnabled(), button.isEnabled());
+    }
+
+    /**
+     * Tests if a command subclass can use an additional condition when 
visible is enabled or not
+     * @throws Exception
+     */
+    public void testAdditionalConditionToVisible() throws Exception {
+        AdditionalStateTestCommand testCommand = new 
AdditionalStateTestCommand();
+        AbstractButton button = testCommand.createButton();
+        assertEquals(testCommand.isVisible(), button.isVisible());
+        testCommand.setMyvisibleState(false);
+        assertEquals(false, testCommand.isVisible());
+        assertEquals(testCommand.isVisible(), button.isVisible());
+        testCommand.setMyvisibleState(true);
+        assertEquals(true, testCommand.isVisible());
+        assertEquals(testCommand.isVisible(), button.isVisible());
+    }
+}


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
spring-rich-c-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/spring-rich-c-cvs

Reply via email to