001 package org.springframework.richclient.form;
002
003 import org.springframework.richclient.application.config.ApplicationObjectConfigurer;
004 import org.springframework.richclient.components.Focussable;
005 import org.springframework.richclient.widget.AbstractWidgetForm;
006 import org.springframework.richclient.util.RcpSupport;
007 import org.springframework.binding.form.FormModel;
008 import org.springframework.binding.form.HierarchicalFormModel;
009 import org.springframework.binding.value.ValueModel;
010
011 import javax.swing.*;
012 import java.awt.*;
013
014 /**
015 * Form implementation for the Focussable interface.
016 *
017 * @author Jan Hoskens
018 *
019 */
020 public abstract class AbstractFocussableForm extends AbstractWidgetForm implements Focussable//, SecurityControllable
021 {
022
023 public static final String UNSAVEDCHANGES_WARNING_ID = "unsavedchanges.warning";
024
025 public static final String UNSAVEDCHANGES_HASERRORS_WARNING_ID = "unsavedchanges.haserrors.warning";
026
027 private JComponent focusControl;
028
029 private final Runnable focusRequestRunnable = new Runnable()
030 {
031
032 public void run()
033 {
034 if (focusControl != null)
035 focusControl.requestFocusInWindow();
036 }
037 };
038
039 /**
040 * Override to do nothing. Superclass registers a default command, but we are using a different system to
041 * define default commands.
042 */
043 @Override
044 protected void handleEnabledChange(boolean enabled)
045 {
046 }
047
048 /**
049 * Registers the component that receives the focus when the form receives focus.
050 *
051 * @see #grabFocus
052 */
053 public void setFocusControl(JComponent field)
054 {
055 this.focusControl = field;
056 }
057
058 public void grabFocus()
059 {
060 if (this.focusControl != null)
061 EventQueue.invokeLater(focusRequestRunnable);
062 }
063
064 /**
065 * @inheritDoc
066 */
067 public AbstractFocussableForm()
068 {
069 super();
070 }
071
072 /**
073 * @inheritDoc
074 */
075 public AbstractFocussableForm(FormModel formModel, String formId)
076 {
077 super(formModel, formId);
078 }
079
080 /**
081 * @inheritDoc
082 */
083 public AbstractFocussableForm(FormModel pageFormModel)
084 {
085 super(pageFormModel);
086 }
087
088 /**
089 * @inheritDoc
090 */
091 public AbstractFocussableForm(HierarchicalFormModel parentFormModel, String formId,
092 String childFormObjectPropertyPath)
093 {
094 super(parentFormModel, formId, childFormObjectPropertyPath);
095 }
096
097 /**
098 * @inheritDoc
099 */
100 public AbstractFocussableForm(HierarchicalFormModel parentFormModel, String formId,
101 ValueModel childFormObjectHolder)
102 {
103 super(parentFormModel, formId, childFormObjectHolder);
104 }
105
106 /**
107 * @inheritDoc
108 */
109 public AbstractFocussableForm(HierarchicalFormModel parentFormModel, String formId)
110 {
111 super(parentFormModel, formId);
112 }
113
114 /**
115 * @inheritDoc
116 */
117 public AbstractFocussableForm(Object formObject)
118 {
119 super(formObject);
120 }
121
122 /**
123 * @inheritDoc
124 */
125 public AbstractFocussableForm(String formId)
126 {
127 super(formId);
128 }
129
130 public boolean canClose()
131 {
132 boolean userBreak = false;
133 int answer = JOptionPane.NO_OPTION; // by default no save is required.
134
135 // unless of course there are unsaved changes and we can commit (isAuthorized)
136 if (this.getFormModel().isEnabled() && this.getFormModel().isDirty()
137 && this.getCommitCommand().isAuthorized())
138 { // then we ask the user to save the mess first: yes/no/cancel
139 answer = RcpSupport.showWarningDialog(this.getControl(), UNSAVEDCHANGES_WARNING_ID,
140 JOptionPane.YES_NO_CANCEL_OPTION);
141
142 switch (answer)
143 {
144 case JOptionPane.CANCEL_OPTION :
145 // backup the selection change so table and detail keep in sync
146 // gives problems (asks unsavedchanges twice)
147 userBreak = true;
148 break;
149 case JOptionPane.YES_OPTION :
150 if (this.getFormModel().getHasErrors() == true)
151 {
152 RcpSupport.showWarningDialog(this.getControl(), UNSAVEDCHANGES_HASERRORS_WARNING_ID);
153 userBreak = true;
154 break;
155 }
156 this.getCommitCommand().execute();
157 break;
158 case JOptionPane.NO_OPTION :
159 {
160 this.revert(); // revert so no strange things happen (hopefully)
161 break;
162 }
163 }
164 }
165
166 return !userBreak;
167 }
168
169 @Override
170 protected void init()
171 {
172 // eerst wordt parent object constructor opgeroepen waarin deze init
173 // wordt opgeroepen. Gewone fields zijn dan nog niet gezet dus doe dat
174 // hier expliciet ipv in velddeclaratie.
175 // authorized = true;
176 // enabled = true;
177 // setSecurityControllerId(getId() + ".authorize");
178 ((ApplicationObjectConfigurer) getApplicationServices().getService(ApplicationObjectConfigurer.class))
179 .configure(this, getId());
180 }
181 }
182