Revision: 1129
Author:   peterdb
Date:     2006-05-10 12:30:40 -0700 (Wed, 10 May 2006)
ViewCVS:  http://svn.sourceforge.net/spring-rich-c/?rev=1129&view=rev

Log Message:
-----------
initial version of DirtyIndicatorInterceptor + small refactoring of 
OverlayValidationInterceptor

Modified Paths:
--------------
    
trunk/spring-richclient/support/src/main/java/org/springframework/richclient/form/builder/support/OverlayValidationInterceptorFactory.java

Added Paths:
-----------
    
trunk/spring-richclient/support/src/main/java/org/springframework/richclient/form/builder/support/DirtyIndicatorInterceptorFactory.java
    
trunk/spring-richclient/support/src/main/java/org/springframework/richclient/form/builder/support/InterceptorOverlayHelper.java
Added: 
trunk/spring-richclient/support/src/main/java/org/springframework/richclient/form/builder/support/DirtyIndicatorInterceptorFactory.java
===================================================================
--- 
trunk/spring-richclient/support/src/main/java/org/springframework/richclient/form/builder/support/DirtyIndicatorInterceptorFactory.java
                             (rev 0)
+++ 
trunk/spring-richclient/support/src/main/java/org/springframework/richclient/form/builder/support/DirtyIndicatorInterceptorFactory.java
     2006-05-10 19:30:40 UTC (rev 1129)
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2002-2006 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.form.builder.support;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.Locale;
+
+import javax.swing.Icon;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+
+import org.springframework.binding.form.FormModel;
+import org.springframework.binding.value.support.ValueHolder;
+import org.springframework.richclient.application.Application;
+import org.springframework.richclient.form.builder.FormComponentInterceptor;
+import 
org.springframework.richclient.form.builder.FormComponentInterceptorFactory;
+import org.springframework.richclient.util.OverlayHelper;
+import org.springframework.util.ObjectUtils;
+
+/**
+ * Adds a "dirty overlay" to a component that is triggered by user editing. 
The overlaid
+ * image is retrieved by the image key "dirty.overlay". The image is placed at 
the
+ * top-left corner of the component, and the image's tooltip is set to a 
message
+ * (retrieved with key "dirty.message") such as "{field} has changed, original 
value was
+ * {value}.".
+ * 
+ * @author Peter De Bruycker
+ */
+public class DirtyIndicatorInterceptorFactory implements 
FormComponentInterceptorFactory {
+    private static final String DEFAULT_ICON_KEY = "dirty.overlay";
+    private static final String DEFAULT_MESSAGE_KEY = "dirty.message";
+
+    private String iconKey = DEFAULT_ICON_KEY;
+
+    public FormComponentInterceptor getInterceptor( FormModel formModel ) {
+        return new DirtyIndicatorInterceptor( formModel, 
Application.instance().getServices().getIcon( iconKey ) );
+    }
+
+    public void setIconKey( String iconKey ) {
+        this.iconKey = iconKey;
+    }
+
+    public String getIconKey() {
+        return iconKey;
+    }
+
+    private static class DirtyIndicatorInterceptor extends 
AbstractFormComponentInterceptor {
+        private Icon icon;
+
+        private DirtyIndicatorInterceptor( FormModel formModel, Icon icon ) {
+            super( formModel );
+            this.icon = icon;
+        }
+
+        public void processComponent( final String propertyName, final 
JComponent component ) {
+            final JLabel overlay = new JLabel( icon );
+
+            final OriginalValueHolder originalValueHolder = new 
OriginalValueHolder();
+            final ValueHolder reset = new ValueHolder( Boolean.FALSE );
+            getFormModel().getValueModel( propertyName 
).addValueChangeListener( new PropertyChangeListener() {
+                public void propertyChange( PropertyChangeEvent evt ) {
+                    if( reset.getValue() == Boolean.TRUE ) {
+                        originalValueHolder.reset();
+                        reset.setValue( Boolean.FALSE );
+
+                        overlay.setVisible( false );
+
+                        return;
+                    }
+
+                    if( !originalValueHolder.isInitialized() ) {
+                        originalValueHolder.setOriginalValue( 
evt.getOldValue() );
+                    }
+
+                    if( isDirty(originalValueHolder.getValue(), 
evt.getNewValue()) ) {
+                        String tooltip = Application.services().getMessage(
+                                DEFAULT_MESSAGE_KEY,
+                                new Object[] {
+                                        Application.services().getMessage( 
propertyName + ".label", null,
+                                                Locale.getDefault() ), 
originalValueHolder.getValue() }, null );
+                        overlay.setToolTipText( tooltip );
+                        overlay.setVisible( true );
+                    } else {
+                        overlay.setVisible( false );
+                    }
+                }
+            } );
+            getFormModel().getFormObjectHolder().addValueChangeListener( new 
PropertyChangeListener() {
+                public void propertyChange( PropertyChangeEvent evt ) {
+                    // reset original value, new "original" value is in the 
form model as
+                    // the form object has changed
+                    reset.setValue( Boolean.TRUE );
+                }
+            } );
+
+            InterceptorOverlayHelper.attachOverlay( overlay, component, 
OverlayHelper.NORTH_WEST, 0, 0 );
+            overlay.setVisible( false );
+        }
+
+        private boolean isDirty( Object oldValue, Object newValue ) {
+            if( oldValue == null && newValue instanceof String ) {
+                // hack for string comparison: null equals empty string
+                return !ObjectUtils.nullSafeEquals( "", newValue );
+            } else {
+                return !ObjectUtils.nullSafeEquals( oldValue, newValue );
+            }
+        }
+    }
+
+    private static class OriginalValueHolder {
+        private boolean initialized;
+        private Object originalValue;
+
+        public void setOriginalValue( Object value ) {
+            initialized = true;
+            originalValue = value;
+        }
+
+        public void reset() {
+            initialized = false;
+            originalValue = null;
+        }
+
+        public Object getValue() {
+            return originalValue;
+        }
+
+        public boolean isInitialized() {
+            return initialized;
+        }
+    }
+}

Added: 
trunk/spring-richclient/support/src/main/java/org/springframework/richclient/form/builder/support/InterceptorOverlayHelper.java
===================================================================
--- 
trunk/spring-richclient/support/src/main/java/org/springframework/richclient/form/builder/support/InterceptorOverlayHelper.java
                             (rev 0)
+++ 
trunk/spring-richclient/support/src/main/java/org/springframework/richclient/form/builder/support/InterceptorOverlayHelper.java
     2006-05-10 19:30:40 UTC (rev 1129)
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2002-2006 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.form.builder.support;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+import javax.swing.JComponent;
+import javax.swing.JScrollPane;
+import javax.swing.JViewport;
+
+import org.springframework.richclient.util.OverlayHelper;
+
+/**
+ * Helper class to attach overlay components to form components. This is 
needed as some
+ * form components are placed inside a scrollpane, and in that case the 
overlay should be
+ * added to the scrollpane and not to the form component itself.
+ */
+public class InterceptorOverlayHelper {
+    private InterceptorOverlayHelper() {
+        // static class only
+    }
+
+    public static void attachOverlay( final JComponent overlay, final 
JComponent component, final int center,
+            final int xOffset, final int yOffset ) {
+        if( component.getParent() == null ) {
+            PropertyChangeListener waitUntilHasParentListener = new 
PropertyChangeListener() {
+                public void propertyChange( PropertyChangeEvent e ) {
+                    if( component.getParent() != null ) {
+                        component.removePropertyChangeListener( "ancestor", 
this );
+                        doAttachOverlay( overlay, component, center, xOffset, 
yOffset );
+                    }
+                }
+            };
+            component.addPropertyChangeListener( "ancestor", 
waitUntilHasParentListener );
+        } else {
+            doAttachOverlay( overlay, component, center, xOffset, yOffset );
+        }
+    }
+
+    private static void doAttachOverlay( JComponent overlay, JComponent 
component, int center, int xOffset, int yOffset ) {
+        JComponent componentToOverlay = hasParentScrollPane( component ) ? 
getParentScrollPane( component ) : component;
+        OverlayHelper.attachOverlay( overlay, componentToOverlay, center, 
xOffset, yOffset );
+    }
+
+    private static JScrollPane getParentScrollPane( JComponent component ) {
+        return (JScrollPane) component.getParent().getParent();
+    }
+
+    private static boolean hasParentScrollPane( JComponent component ) {
+        return component.getParent() != null && component.getParent() 
instanceof JViewport
+                && component.getParent().getParent() instanceof JScrollPane;
+    }
+}

Modified: 
trunk/spring-richclient/support/src/main/java/org/springframework/richclient/form/builder/support/OverlayValidationInterceptorFactory.java
===================================================================
--- 
trunk/spring-richclient/support/src/main/java/org/springframework/richclient/form/builder/support/OverlayValidationInterceptorFactory.java
  2006-05-10 19:25:06 UTC (rev 1128)
+++ 
trunk/spring-richclient/support/src/main/java/org/springframework/richclient/form/builder/support/OverlayValidationInterceptorFactory.java
  2006-05-10 19:30:40 UTC (rev 1129)
@@ -20,9 +20,7 @@
 
 import javax.swing.JComponent;
 import javax.swing.JLabel;
-import javax.swing.JScrollPane;
 import javax.swing.JTextField;
-import javax.swing.JViewport;
 
 import org.springframework.binding.form.FormModel;
 import org.springframework.binding.validation.Severity;
@@ -36,12 +34,11 @@
 import org.springframework.richclient.util.OverlayHelper;
 
 /**
- * Adds an "overlay" to a component that is triggered by a validation event. 
The
- * overlaid image is retrieved by the image key
- * "severity.{severityShortCode}.overlay", where {severityShortCode} is the
- * number returned by [EMAIL PROTECTED] Severity#getShortCode()}. The image is 
placed at
- * the bottom-left corner of the component, and the image's tooltip is set to
- * the validation message.
+ * Adds an "overlay" to a component that is triggered by a validation event. 
The overlaid
+ * image is retrieved by the image key "severity.{severityShortCode}.overlay", 
where
+ * {severityShortCode} is the number returned by [EMAIL PROTECTED] 
Severity#getShortCode()}. The
+ * image is placed at the bottom-left corner of the component, and the image's 
tooltip is
+ * set to the validation message.
  * 
  * @author Oliver Hutchison
  * @see OverlayHelper#attachOverlay
@@ -54,77 +51,66 @@
         textCompHeight = new JTextField().getPreferredSize().height;
     }
 
-    public FormComponentInterceptor getInterceptor(FormModel formModel) {
-        return new OverlayValidationInterceptor(formModel);
+    public FormComponentInterceptor getInterceptor( FormModel formModel ) {
+        return new OverlayValidationInterceptor( formModel );
     }
 
     public class OverlayValidationInterceptor extends ValidationInterceptor {
 
-        public OverlayValidationInterceptor(FormModel formModel) {
-            super(formModel);
+        public OverlayValidationInterceptor( FormModel formModel ) {
+            super( formModel );
         }
 
-        public void processComponent(String propertyName, final JComponent 
component) {
+        public void processComponent( String propertyName, final JComponent 
component ) {
             final ErrorReportingOverlay overlay = new ErrorReportingOverlay();
 
-            registerGuarded(propertyName, overlay);
-            registerMessageReceiver(propertyName, overlay);
+            registerGuarded( propertyName, overlay );
+            registerMessageReceiver( propertyName, overlay );
 
-            if (component.getParent() == null) {
+            if( component.getParent() == null ) {
                 PropertyChangeListener waitUntilHasParentListener = new 
PropertyChangeListener() {
-                    public void propertyChange(PropertyChangeEvent e) {
-                        if (component.getParent() != null) {
-                            component.removePropertyChangeListener("ancestor", 
this);
-                            attachOverlay(overlay, component);
+                    public void propertyChange( PropertyChangeEvent e ) {
+                        if( component.getParent() != null ) {
+                            component.removePropertyChangeListener( 
"ancestor", this );
+                            attachOverlay( overlay, component );
                         }
                     }
                 };
-                component.addPropertyChangeListener("ancestor", 
waitUntilHasParentListener);
+                component.addPropertyChangeListener( "ancestor", 
waitUntilHasParentListener );
+            } else {
+                attachOverlay( overlay, component );
             }
-            else {
-                attachOverlay(overlay, component);
-            }
         }
 
-        private void attachOverlay(ErrorReportingOverlay overlay, JComponent 
component) {
-            JComponent componentToOverlay = hasParentScrollPane(component) ? 
getParentScrollPane(component) : component;
-            int yOffset = componentToOverlay.getPreferredSize().height;
-            OverlayHelper.attachOverlay(overlay, componentToOverlay, 
OverlayHelper.NORTH_WEST, 0, Math.min(yOffset,
-                    textCompHeight));
+        private void attachOverlay( ErrorReportingOverlay overlay, JComponent 
component ) {
+            int yOffset = component.getPreferredSize().height;
+            InterceptorOverlayHelper.attachOverlay( overlay, component, 
OverlayHelper.NORTH_WEST, 0, Math.min( yOffset,
+                    textCompHeight ) );
         }
-
-        private JScrollPane getParentScrollPane(JComponent component) {
-            return (JScrollPane)component.getParent().getParent();
-        }
-
-        private boolean hasParentScrollPane(JComponent component) {
-            return component.getParent() != null && component.getParent() 
instanceof JViewport
-                    && component.getParent().getParent() instanceof 
JScrollPane;
-        }
     }
 
     private class ErrorReportingOverlay extends JLabel implements Messagable, 
Guarded {
-        private DefaultMessageAreaModel messageBuffer = new 
DefaultMessageAreaModel(this);
+        private DefaultMessageAreaModel messageBuffer = new 
DefaultMessageAreaModel( this );
 
         public boolean isEnabled() {
             return true;
         }
 
-        public void setEnabled(boolean enabled) {
-            setVisible(!enabled);
+        public void setEnabled( boolean enabled ) {
+            setVisible( !enabled );
         }
 
-        public void setMessage(Message message) {
-            messageBuffer.setMessage(message);
+        public void setMessage( Message message ) {
+            messageBuffer.setMessage( message );
             message = messageBuffer.getMessage();
-            setToolTipText(message.getText());
+            setToolTipText( message.getText() );
             Severity severity = message.getSeverity();
-            if (severity != null) {
-                
setIcon(Application.services().getIconSource().getIcon("severity." + 
severity.getLabel() + ".overlay"));
+            if( severity != null ) {
+                setIcon( Application.services().getIconSource()
+                        .getIcon( "severity." + severity.getLabel() + 
".overlay" ) );
+            } else {
+                setIcon( null );
             }
-            else {
-                setIcon(null);
-            }
         }
     }
-}
\ No newline at end of file
+}


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