001 /*
002 * Copyright 2002-2004 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.form.binding.swing;
017
018 import java.util.Map;
019
020 import javax.swing.JComponent;
021 import javax.swing.JScrollPane;
022
023 import org.springframework.binding.form.FormModel;
024 import org.springframework.richclient.form.binding.BinderSelectionStrategy;
025 import org.springframework.richclient.form.binding.Binding;
026 import org.springframework.richclient.form.binding.support.AbstractBinder;
027 import org.springframework.util.Assert;
028
029 /**
030 * A binder that binds a scroll pane and the scroll pane's view. If the
031 * scroll pane does not have a view a default binding will be created and
032 * set as the scroll pane's view.
033 *
034 * @author Oliver Hutchison
035 */
036 public class ScrollPaneBinder extends AbstractBinder {
037
038 private final BinderSelectionStrategy viewBinderSelectionStrategy;
039
040 private final Class defaultViewType;
041
042 /**
043 * Constructs a new ScrollPaneBinder
044 *
045 * @param viewBinderSelectionStrategy the {@link BinderSelectionStrategy} which will be used
046 * to select a Binder for the scrollpane's view component.
047 * @param defaultViewType the type of the component that will be created and bound if the
048 * scroll pane does not already have a view
049 */
050 public ScrollPaneBinder(BinderSelectionStrategy viewBinderSelectionStrategy, Class defaultViewType) {
051 super(null);
052 this.viewBinderSelectionStrategy = viewBinderSelectionStrategy;
053 this.defaultViewType = defaultViewType;
054 }
055
056 protected JComponent createControl(Map context) {
057 return getComponentFactory().createScrollPane();
058 }
059
060 protected Binding doBind(JComponent control, FormModel formModel, String formPropertyPath, Map context) {
061 Assert.isTrue(control instanceof JScrollPane, "Control must be an instance of JScrollPane.");
062 JScrollPane scrollPane = (JScrollPane)control;
063 Binding viewBinding = getViewBinding(scrollPane, formModel, formPropertyPath, context);
064 return new ScrollPaneDecoratedBinding(viewBinding, scrollPane);
065 }
066
067 protected Binding getViewBinding(JScrollPane scrollPane, FormModel formModel, String formPropertyPath, Map context) {
068 JComponent view = (JComponent)scrollPane.getViewport().getView();
069 if (view == null) {
070 Binding viewBinding = viewBinderSelectionStrategy.selectBinder(defaultViewType, formModel, formPropertyPath)
071 .bind(formModel, formPropertyPath, context);
072 scrollPane.setViewportView(viewBinding.getControl());
073 return viewBinding;
074 }
075 Binding existingBinding = (Binding)view.getClientProperty(BINDING_CLIENT_PROPERTY_KEY);
076 if (existingBinding != null) {
077 return existingBinding;
078 }
079 return viewBinderSelectionStrategy.selectBinder(view.getClass(), formModel, formPropertyPath).bind(
080 view, formModel, formPropertyPath, context);
081 }
082
083 protected void validateContextKeys(Map context) {
084 // do nothing as we pass the context on to
085 // the scroll pane's view binder
086 }
087 }