1   /*
2    * Copyright 2002-2006 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5    * use this file except in compliance with the License. You may obtain a copy of
6    * the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations under
14   * the License.
15   */
16  package org.springframework.richclient.form.builder.support;
17  
18  import java.awt.GraphicsEnvironment;
19  import java.util.Locale;
20  
21  import javax.swing.JComponent;
22  import javax.swing.JFrame;
23  import javax.swing.JLayeredPane;
24  import javax.swing.JTextField;
25  
26  import org.springframework.binding.form.FormModel;
27  import org.springframework.binding.form.support.DefaultFormModel;
28  import org.springframework.binding.value.ValueModel;
29  import org.springframework.context.support.StaticMessageSource;
30  import org.springframework.richclient.application.support.DefaultApplicationServices;
31  import org.springframework.richclient.form.binding.Binding;
32  import org.springframework.richclient.form.binding.swing.SwingBindingFactory;
33  import org.springframework.richclient.form.builder.TestBean;
34  import org.springframework.richclient.test.SpringRichTestCase;
35  
36  /**
37   * Tests for <code>DirtyIndicatorInterceptor</code>.
38   *
39   * @author Peter De Bruycker
40   */
41  public class DirtyIndicatorInterceptorTests extends SpringRichTestCase {
42  	/**
43  	 * FIXME: this test will not run in a headless environment
44  	 */
45      public void testProcessComponent() throws InterruptedException {
46      	if (GraphicsEnvironment.isHeadless()) {
47  			return;
48  		}
49          TestBean bean = new TestBean();
50          bean.setProperty("original value");
51  
52          FormModel formModel = new DefaultFormModel(bean);
53  
54          DirtyIndicatorInterceptor interceptor = new DirtyIndicatorInterceptor(formModel);
55          assertEquals(formModel, interceptor.getFormModel());
56  
57          Binding binding = new SwingBindingFactory(formModel).createBinding("property");
58          JTextField field = (JTextField)binding.getControl();
59          field.setColumns(25);
60          assertNotNull("sanity check: binding defines no component", field);
61  
62          interceptor.processComponent("property", field);
63  
64          // start a frame to trigger visual updates
65          JFrame frame = new JFrame("test");
66          frame.getContentPane().add(field);
67          frame.pack();
68          frame.setVisible(true);
69  
70          // trigger a show of the overlay, so we can get a reference to it
71          ValueModel valueModel = formModel.getValueModel("property");
72          valueModel.setValue("dirty");
73  
74          // sleep for a while so the gui can update itself
75          Thread.sleep(500);
76          formModel.revert();
77  
78          // find a reference to the overlay component
79          JLayeredPane layeredPane = frame.getRootPane().getLayeredPane();
80          assertEquals("sanity check: assume the layered pane only has one component, and that it is a panel and the overlay", 
81                       2, layeredPane.getComponentCount());
82          // the overlay is the first component
83          JComponent overlay = (JComponent)layeredPane.getComponent(0);
84          // the overlay is now put into another panel for clipping.
85          if(!"dirtyOverlay".equals(overlay.getName())) {
86              assertEquals("Unable to locate overlay", "dirtyOverlay", overlay.getComponent(0).getName());
87              overlay = (JComponent) overlay.getComponent(0);
88          }
89  
90          assertFalse("Overlay must be hidden", overlay.isVisible());
91  
92          // mimic user editing
93          valueModel.setValue("ttt");
94          assertTrue("Value is dirty, so overlay must be visible", overlay.isVisible());
95  
96          // user reverts the edit
97          valueModel.setValue("original value");
98          assertFalse("value is not dirty, so overlay must be hidden", overlay.isVisible());
99  
100         // dispose of the frame
101         frame.dispose();
102     }
103 
104     protected void registerBasicServices(DefaultApplicationServices applicationServices) {
105         super.registerBasicServices(applicationServices);
106 
107         StaticMessageSource messageSource = new StaticMessageSource();
108         messageSource.addMessage("dirty.message", Locale.getDefault(), "{0} has changed, original value was {1}.");
109         messageSource.addMessage("revert.message", Locale.getDefault(), "Revert value to {0}.");
110 
111         messageSource.addMessage("property.label", Locale.getDefault(), "Property");
112 
113         applicationServices.setMessageSource(messageSource);
114     }
115 }