Subversion Repository Public Repository

litesoft

Diff Revisions 949 vs 950 for /trunk/Java/GWT/Client/src/org/litesoft/GWT/forms/client/components/impls/input/FormRadioGroup.java

Diff revisions: vs.
  @@ -1,496 +1,496 @@
1 - // This Source Code is in the Public Domain per: http://unlicense.org
2 - package org.litesoft.GWT.forms.client.components.impls.input;
3 -
4 - import org.litesoft.GWT.client.widgets.*;
5 - import org.litesoft.GWT.client.widgets.nonpublic.*;
6 - import org.litesoft.GWT.forms.client.components.nonpublic.*;
7 - import org.litesoft.commonfoundation.html.*;
8 - import org.litesoft.commonfoundation.typeutils.*;
9 - import org.litesoft.core.*;
10 - import org.litesoft.core.simpletypes.*;
11 - import org.litesoft.ui.*;
12 - import org.litesoft.uispecification.*;
13 -
14 - import com.google.gwt.core.client.*;
15 - import com.google.gwt.dom.client.*;
16 - import com.google.gwt.event.dom.client.*;
17 - import com.google.gwt.user.client.*;
18 - import com.google.gwt.user.client.Element;
19 - import com.google.gwt.user.client.ui.*;
20 -
21 - import java.util.*;
22 -
23 - public class FormRadioGroup extends AbstractFormElement implements ChangeHandler {
24 - protected final InfoIndicator mInfoIndicator = new InfoIndicator();
25 -
26 - public FormRadioGroup( String pGroupLabel, UiFont pLabelFont, String pTooltip, SimpleKeyValuePair... pOptions ) {
27 - super( DOM.createFieldSet() );
28 - mFieldLabel = pGroupLabel;
29 - mTooltip = pTooltip;
30 - int zInstanceNumber = StaticSimpleIdSource.getNext();
31 -
32 - mInfoIndicator.setTooltip( Strings.deNull( pTooltip ).trim() );
33 -
34 - pGroupLabel = Strings.noEmpty( pGroupLabel );
35 -
36 - String zGroupName = "RadioGroup" + zInstanceNumber;
37 - String legendId = "lgnd" + zInstanceNumber;
38 - String legendHTML = (pGroupLabel == null) ? "" :
39 - "<legend id=" + legendId + " class='litesoft-FormComponentRadioGroupLegend'" + ApplyFont.toHtmlStyle( pLabelFont ) +
40 - "><img src='common/images/misc/TransparentSpacer_h18.gif'>" + pGroupLabel + "</legend>";
41 - String html = legendHTML + "<div id='" + zGroupName + "'></div>";
42 -
43 - initializeHTML( html );
44 - if ( (legendHTML.length() != 0) && mInfoIndicator.mCanShow ) {
45 - mInnerHTMLpanel.add( mInfoIndicator, legendId );
46 - }
47 -
48 - if ( pOptions != null ) {
49 - for ( SimpleKeyValuePair option : pOptions ) {
50 - if ( option != null ) {
51 - RadioButtonProxy radioButtonProxy = new RadioButtonProxy( zGroupName, option, this );
52 - mRadioButtons.add( radioButtonProxy );
53 - mInnerHTMLpanel.add( radioButtonProxy, zGroupName );
54 - }
55 - }
56 - }
57 - if ( mRadioButtons.size() < 2 ) {
58 - throw new IllegalArgumentException( "Radio Groups Must have at least two options" );
59 - }
60 - setDefaultSelection();
61 - }
62 -
63 - public FormRadioGroup( String pGroupLabel, UiFont pLabelFont, String pTooltip, String... pOptions ) {
64 - this( pGroupLabel, pLabelFont, pTooltip, convertToKeyValuePairs( pOptions ) );
65 - }
66 -
67 - private ArrayList<RadioButtonProxy> mRadioButtons = new ArrayList<RadioButtonProxy>();
68 -
69 - private RadioButtonProxy getRadioButon( int pI ) {
70 - return mRadioButtons.get( pI );
71 - }
72 -
73 - // Changehandler
74 -
75 - @Override
76 - public void onChange( ChangeEvent event ) // possibleStateChange
77 - {
78 - if ( mDelayedStateChecker == null ) {
79 - mDelayedStateChecker = new DelayedStateChecker();
80 - }
81 - Scheduler.get().scheduleDeferred( mDelayedStateChecker.getCommandToDefer() );
82 - }
83 -
84 - // SizeManaged
85 -
86 - @Override
87 - public void relayout() {
88 - Widget parent = getParent();
89 - if ( parent instanceof SizeManaged ) {
90 - ((SizeManaged) parent).relayout();
91 - }
92 - }
93 -
94 - // IFormComponent
95 -
96 - @Override
97 - public boolean setFocus() {
98 - pullFocusTo( getRadioButon( 0 ) );
99 - return true;
100 - }
101 -
102 - @Override
103 - public Object getCurrentValue() {
104 - return (mLastSelection != null) ? mLastSelection.getKeyValuePair() : setDefaultSelection();
105 - }
106 -
107 - @Override
108 - public void setCurrentValue( Object pNewValue ) {
109 - if ( pNewValue != null ) {
110 - setSelected( getProxyFor( pNewValue ) );
111 - }
112 - }
113 -
114 - @Override
115 - public void setEnabled( boolean pEnabled ) {
116 - mEnabled = pEnabled;
117 - for ( int i = 0; i < mRadioButtons.size(); i++ ) {
118 - RadioButtonProxy radioButtonProxy = getRadioButon( i );
119 - radioButtonProxy.setEnabled( pEnabled );
120 - }
121 - stateChanged();
122 - }
123 -
124 - // AbstractFormElement
125 -
126 - @Override
127 - protected void setEnabledStyles() {
128 - super.setEnabledStyles();
129 - mInfoIndicator.setVisible( hasFocus() );
130 - }
131 -
132 - @Override
133 - public void publishAnyPendingChanges() {
134 - FocusSelection zFS = determineFocusSelection();
135 - RadioButtonProxy prevLastSelection = mLastSelection;
136 - if ( zFS.getSelected() != null ) {
137 - setLastSelected( zFS.getSelected() );
138 - }
139 - RadioButtonProxy curLastSelection = mLastSelection;
140 - if ( prevLastSelection != curLastSelection ) {
141 - fireChangeListeners();
142 - }
143 - if ( mReportedFocus ) {
144 - mReportedFocus = false;
145 - fireBlurListeners();
146 - }
147 - super.publishAnyPendingChanges();
148 - }
149 -
150 - // Support...
151 -
152 - @Override
153 - public void simulateUserTextEntry( String pText ) {
154 - RadioButtonProxy zCurrentSelection = mLastSelection;
155 - setLastSelected( determineItemToSelect( Strings.deNull( pText ).trim() ) );
156 - if ( zCurrentSelection != mLastSelection ) {
157 - mLastSelection.setChecked();
158 - fireChangeListeners();
159 - }
160 - pullFocusTo( mLastSelection );
161 - }
162 -
163 - private RadioButtonProxy determineItemToSelect( String pText ) {
164 - for ( int i = 0; i < mRadioButtons.size(); i++ ) {
165 - RadioButtonProxy radioButtonProxy = getRadioButon( i );
166 - if ( pText.equals( radioButtonProxy.getKeyValuePair().toStringValue() ) ) {
167 - return radioButtonProxy;
168 - }
169 - }
170 - throw new IllegalArgumentException( "simulateUserTextEntry on '" + mFieldLabel + "' to:" + pText );
171 - }
172 -
173 - //vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv//
174 -
175 - private RadioButtonProxy getProxyFor( Object pNewValue ) {
176 - Object pairKey;
177 - if ( pNewValue instanceof SimpleKeyValuePair ) {
178 - pairKey = ((SimpleKeyValuePair) pNewValue).getKey();
179 - } else if ( pNewValue instanceof String ) {
180 - pairKey = pNewValue;
181 - } else {
182 - pairKey = "?" + pNewValue;
183 - }
184 - for ( int i = 0; i < mRadioButtons.size(); i++ ) {
185 - RadioButtonProxy radioButtonProxy = getRadioButon( i );
186 - if ( pairKey.equals( radioButtonProxy.getKeyValuePair().getKey() ) ) {
187 - return radioButtonProxy;
188 - }
189 - }
190 - throw new IllegalArgumentException( "No Valid Option in Radio Group of: " + pNewValue );
191 - }
192 -
193 - private SimpleKeyValuePair setDefaultSelection() {
194 - SimpleKeyValuePair rv = getRadioButon( 0 ).getKeyValuePair();
195 - setCurrentValue( rv );
196 - return rv;
197 - }
198 -
199 - private void setSelected( RadioButtonProxy pRadioButtonProxy ) {
200 - setInitialSelection( pRadioButtonProxy );
201 - setLastSelected( pRadioButtonProxy );
202 - /*
203 - * Work around for IE bug where you can select multiple radio buttons
204 - * when not attached (part 1)
205 - */
206 - if ( isAttached() ) {
207 - pRadioButtonProxy.setChecked();
208 - }
209 - }
210 -
211 - @Override
212 - protected void onLoad() {
213 - super.onLoad();
214 - /*
215 - * Work around for IE bug where you can select multiple radio buttons
216 - * when not attached (part 2)
217 - */
218 - if ( mLastSelection != null ) {
219 - mLastSelection.setChecked();
220 - }
221 - }
222 -
223 - private FocusSelection determineFocusSelection() {
224 - boolean anyFocus = false;
225 - RadioButtonProxy selected = null;
226 - for ( int i = 0; i < mRadioButtons.size(); i++ ) {
227 - RadioButtonProxy radioButtonProxy = getRadioButon( i );
228 - if ( radioButtonProxy.isChecked() ) {
229 - selected = radioButtonProxy;
230 - }
231 - anyFocus |= radioButtonProxy.hasFocus();
232 - }
233 - return new FocusSelection( anyFocus, selected );
234 - }
235 -
236 - private static class FocusSelection {
237 - private boolean mFocused;
238 - private RadioButtonProxy mSelected;
239 -
240 - public FocusSelection( boolean pFocused, RadioButtonProxy pSelected ) {
241 - mFocused = pFocused;
242 - mSelected = pSelected;
243 - }
244 -
245 - public boolean isFocused() {
246 - return mFocused;
247 - }
248 -
249 - public RadioButtonProxy getSelected() {
250 - return mSelected;
251 - }
252 - }
253 -
254 - public void publishAnyDelayedChanges() {
255 - if ( mPendingReentries++ != 0 ) {
256 - return;
257 - }
258 - do {
259 - FocusSelection zFS = determineFocusSelection();
260 - boolean shouldIssueBlur = false;
261 - if ( zFS.isFocused() != mReportedFocus ) {
262 - if ( zFS.isFocused() ) {
263 - mReportedFocus = true;
264 - fireFocusListeners();
265 - } else {
266 - shouldIssueBlur = true;
267 - }
268 - }
269 - RadioButtonProxy prevLastSelection = mLastSelection;
270 - if ( zFS.getSelected() != null ) {
271 - setLastSelected( zFS.getSelected() );
272 - }
273 - RadioButtonProxy curLastSelection = mLastSelection;
274 - if ( prevLastSelection != curLastSelection ) {
275 - fireChangeListeners();
276 - }
277 - if ( shouldIssueBlur ) {
278 - mReportedFocus = false;
279 - fireBlurListeners();
280 - }
281 - }
282 - while ( --mPendingReentries > 0 );
283 - }
284 -
285 - private int mPendingReentries = 0;
286 - private boolean mReportedFocus = false;
287 - private RadioButtonProxy mInitialSelection = null;
288 - private RadioButtonProxy mLastSelection = null;
289 -
290 - private void setInitialSelection( RadioButtonProxy pInitialSelection ) {
291 - RadioButtonProxy prev = mInitialSelection;
292 - switchChangeFromTo( prev, mInitialSelection = pInitialSelection );
293 - }
294 -
295 - private RadioButtonProxy setLastSelected( RadioButtonProxy pSelected ) {
296 - return mLastSelection = switchChangeFromTo( mLastSelection, pSelected );
297 - }
298 -
299 - private RadioButtonProxy switchChangeFromTo( RadioButtonProxy pPrev, RadioButtonProxy pNew ) {
300 - if ( pPrev != pNew ) {
301 - if ( pPrev != null ) {
302 - pPrev.removeChangeIndicator();
303 - }
304 - if ( pNew != null ) {
305 - if ( pNew != mInitialSelection ) {
306 - mInitialSelection.addChangeIndicator();
307 - pNew.addChangeIndicator();
308 - } else {
309 - mInitialSelection.removeChangeIndicator();
310 - pNew.removeChangeIndicator();
311 - }
312 - }
313 - }
314 - return pNew;
315 - }
316 -
317 - //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//
318 -
319 - private DelayedStateChecker mDelayedStateChecker = null;
320 -
321 - private class DelayedStateChecker implements Command {
322 - private int mPendingDelays = 0;
323 -
324 - public Command getCommandToDefer() {
325 - mPendingDelays++;
326 - return this;
327 - }
328 -
329 - @Override
330 - public void execute() {
331 - if ( --mPendingDelays == 0 ) {
332 - publishAnyDelayedChanges();
333 - }
334 - }
335 - }
336 -
337 - private static class RadioButtonProxy extends Composite implements Focusable,
338 - FocusHandler,
339 - BlurHandler,
340 - ClickHandler {
341 - private SimpleKeyValuePair mKeyValuePair;
342 - private ChangeHandler mChangeHandler;
343 - private RadioButton mRadioButton;
344 - private boolean mHasFocus = false;
345 - private boolean mChangeIndicated = false;
346 -
347 - public RadioButtonProxy( String pRadioGroupName, SimpleKeyValuePair pKeyValuePair, ChangeHandler pChangeHandler ) {
348 - mKeyValuePair = pKeyValuePair;
349 - mChangeHandler = pChangeHandler;
350 - String zLabel = HTMLize.escapeNoWrap( pKeyValuePair.toStringValue() );
351 - mRadioButton = new RadioButton( pRadioGroupName, zLabel, true );
352 - //noinspection GWTStyleCheck
353 - mRadioButton.setStyleName( "frmRadioBtn" );
354 -
355 - initWidget( buildComponentPanel() );
356 -
357 - mRadioButton.addFocusHandler( this );
358 - mRadioButton.addBlurHandler( this );
359 - mRadioButton.addClickHandler( this );
360 -
361 - // setStyleName( BASE_STYLE_NAME );
362 - }
363 -
364 - private HTMLPanel buildComponentPanel() {
365 - String inputId = "input" + StaticSimpleIdSource.getNext();
366 - String html = "<nowrap><table cellpadding='0' cellspacing='0'><tr><td id='" + inputId + "'></td></tr></table></nowrap>";
367 -
368 - HTMLPanel panel = new HTMLPanel( html );
369 - panel.add( mRadioButton, inputId );
370 - return panel;
371 - }
372 -
373 - @Override
374 - public int getTabIndex() {
375 - return mRadioButton.getTabIndex();
376 - }
377 -
378 - @Override
379 - public void setTabIndex( int index ) {
380 - mRadioButton.setTabIndex( index );
381 - }
382 -
383 - @Override
384 - public void setAccessKey( char key ) {
385 - mRadioButton.setAccessKey( key );
386 - }
387 -
388 - @Override
389 - public void setFocus( boolean pFocus ) {
390 - mRadioButton.setFocus( pFocus );
391 - }
392 -
393 - @Override
394 - public void onFocus( FocusEvent event ) {
395 - // System.out.println( "RadioButtonProxy.onFocus: " + mKeyValuePair );
396 - mHasFocus = true;
397 - mChangeHandler.onChange( null );
398 - }
399 -
400 - @Override
401 - public void onBlur( BlurEvent event ) {
402 - // System.out.println( "RadioButtonProxy.onLostFocus: " + mKeyValuePair );
403 - mHasFocus = false;
404 - mChangeHandler.onChange( null );
405 - }
406 -
407 - @Override
408 - public void onClick( ClickEvent event ) {
409 - // System.out.println( "RadioButtonProxy.onClick: " + mKeyValuePair );
410 - mChangeHandler.onChange( null );
411 - }
412 -
413 - public SimpleKeyValuePair getKeyValuePair() {
414 - return mKeyValuePair;
415 - }
416 -
417 - public void setChecked() {
418 - mRadioButton.setValue( true );
419 - }
420 -
421 - public void setEnabled( boolean pEnabled ) {
422 - mRadioButton.setEnabled( pEnabled );
423 - }
424 -
425 - public boolean isChecked() {
426 - return mRadioButton.getValue();
427 - }
428 -
429 - public boolean hasFocus() {
430 - return mHasFocus;
431 - }
432 -
433 - public void addChangeIndicator() {
434 - if ( !mChangeIndicated ) {
435 - mChangeIndicated = true;
436 - //noinspection GWTStyleCheck
437 - mRadioButton.addStyleName( "frmRadioBtn-Changed" );
438 - }
439 - }
440 -
441 - public void removeChangeIndicator() {
442 - if ( mChangeIndicated ) {
443 - mChangeIndicated = false;
444 - //noinspection GWTStyleCheck
445 - mRadioButton.removeStyleName( "frmRadioBtn-Changed" );
446 - }
447 - }
448 -
449 - @Override
450 - public String toString() {
451 - return "RadioButtonProxy: " + mKeyValuePair.toStringValue();
452 - }
453 - }
454 -
455 - private static class InfoIndicator extends Widget {
456 - private Element iconImg = DOM.createImg();
457 - private boolean mCanShow = false;
458 -
459 - public InfoIndicator() {
460 - Element span = DOM.createSpan();
461 - // DOM.setElementProperty( span, "className", "litesoft-FormComponentIndicatorContainer" );
462 - setElement( span );
463 -
464 - CommonElementHelper.setImgSrc( iconImg, TransparentImage.URL );
465 - CommonElementHelper.setStyleClass( iconImg, "litesoft-FormComponentIndicator" );
466 - DOM.appendChild( span, iconImg );
467 -
468 - setVisible( false );
469 - }
470 -
471 - public void setTooltip( String pTooltip ) {
472 - mCanShow = (pTooltip.length() != 0);
473 - DOM.setElementProperty( iconImg, "title", pTooltip );
474 - }
475 -
476 - @Override
477 - public void setVisible( boolean pVisible ) {
478 - getElement().getStyle().setDisplay( (mCanShow && pVisible) ? Style.Display.INLINE : Style.Display.NONE );
479 - }
480 - }
481 -
482 - private static SimpleKeyValuePair[] convertToKeyValuePairs( String[] pOptions ) {
483 - if ( pOptions == null ) {
484 - return SimpleKeyValuePair.EMPTY_ARRAY;
485 - }
486 - SimpleKeyValuePair[] rv = new SimpleKeyValuePair[pOptions.length];
487 - for ( int i = 0; i < pOptions.length; i++ ) {
488 - rv[i] = convertToKeyValuePair( pOptions[i] );
489 - }
490 - return rv;
491 - }
492 -
493 - private static SimpleKeyValuePair convertToKeyValuePair( String pOption ) {
494 - return (pOption != null) ? new StringKeyValuePair( pOption, pOption ) : null;
495 - }
496 - }
1 + // This Source Code is in the Public Domain per: http://unlicense.org
2 + package org.litesoft.GWT.forms.client.components.impls.input;
3 +
4 + import org.litesoft.GWT.client.widgets.*;
5 + import org.litesoft.GWT.client.widgets.nonpublic.*;
6 + import org.litesoft.GWT.forms.client.components.nonpublic.*;
7 + import org.litesoft.commonfoundation.base.*;
8 + import org.litesoft.commonfoundation.html.*;
9 + import org.litesoft.core.*;
10 + import org.litesoft.core.simpletypes.*;
11 + import org.litesoft.ui.*;
12 + import org.litesoft.uispecification.*;
13 +
14 + import com.google.gwt.core.client.*;
15 + import com.google.gwt.dom.client.*;
16 + import com.google.gwt.event.dom.client.*;
17 + import com.google.gwt.user.client.*;
18 + import com.google.gwt.user.client.Element;
19 + import com.google.gwt.user.client.ui.*;
20 +
21 + import java.util.*;
22 +
23 + public class FormRadioGroup extends AbstractFormElement implements ChangeHandler {
24 + protected final InfoIndicator mInfoIndicator = new InfoIndicator();
25 +
26 + public FormRadioGroup( String pGroupLabel, UiFont pLabelFont, String pTooltip, SimpleKeyValuePair... pOptions ) {
27 + super( DOM.createFieldSet() );
28 + mFieldLabel = pGroupLabel;
29 + mTooltip = pTooltip;
30 + int zInstanceNumber = StaticSimpleIdSource.getNext();
31 +
32 + mInfoIndicator.setTooltip( ConstrainTo.notNull( pTooltip ).trim() );
33 +
34 + pGroupLabel = ConstrainTo.significantOrNull( pGroupLabel );
35 +
36 + String zGroupName = "RadioGroup" + zInstanceNumber;
37 + String legendId = "lgnd" + zInstanceNumber;
38 + String legendHTML = (pGroupLabel == null) ? "" :
39 + "<legend id=" + legendId + " class='litesoft-FormComponentRadioGroupLegend'" + ApplyFont.toHtmlStyle( pLabelFont ) +
40 + "><img src='common/images/misc/TransparentSpacer_h18.gif'>" + pGroupLabel + "</legend>";
41 + String html = legendHTML + "<div id='" + zGroupName + "'></div>";
42 +
43 + initializeHTML( html );
44 + if ( (legendHTML.length() != 0) && mInfoIndicator.mCanShow ) {
45 + mInnerHTMLpanel.add( mInfoIndicator, legendId );
46 + }
47 +
48 + if ( pOptions != null ) {
49 + for ( SimpleKeyValuePair option : pOptions ) {
50 + if ( option != null ) {
51 + RadioButtonProxy radioButtonProxy = new RadioButtonProxy( zGroupName, option, this );
52 + mRadioButtons.add( radioButtonProxy );
53 + mInnerHTMLpanel.add( radioButtonProxy, zGroupName );
54 + }
55 + }
56 + }
57 + if ( mRadioButtons.size() < 2 ) {
58 + throw new IllegalArgumentException( "Radio Groups Must have at least two options" );
59 + }
60 + setDefaultSelection();
61 + }
62 +
63 + public FormRadioGroup( String pGroupLabel, UiFont pLabelFont, String pTooltip, String... pOptions ) {
64 + this( pGroupLabel, pLabelFont, pTooltip, convertToKeyValuePairs( pOptions ) );
65 + }
66 +
67 + private ArrayList<RadioButtonProxy> mRadioButtons = new ArrayList<RadioButtonProxy>();
68 +
69 + private RadioButtonProxy getRadioButon( int pI ) {
70 + return mRadioButtons.get( pI );
71 + }
72 +
73 + // Changehandler
74 +
75 + @Override
76 + public void onChange( ChangeEvent event ) // possibleStateChange
77 + {
78 + if ( mDelayedStateChecker == null ) {
79 + mDelayedStateChecker = new DelayedStateChecker();
80 + }
81 + Scheduler.get().scheduleDeferred( mDelayedStateChecker.getCommandToDefer() );
82 + }
83 +
84 + // SizeManaged
85 +
86 + @Override
87 + public void relayout() {
88 + Widget parent = getParent();
89 + if ( parent instanceof SizeManaged ) {
90 + ((SizeManaged) parent).relayout();
91 + }
92 + }
93 +
94 + // IFormComponent
95 +
96 + @Override
97 + public boolean setFocus() {
98 + pullFocusTo( getRadioButon( 0 ) );
99 + return true;
100 + }
101 +
102 + @Override
103 + public Object getCurrentValue() {
104 + return (mLastSelection != null) ? mLastSelection.getKeyValuePair() : setDefaultSelection();
105 + }
106 +
107 + @Override
108 + public void setCurrentValue( Object pNewValue ) {
109 + if ( pNewValue != null ) {
110 + setSelected( getProxyFor( pNewValue ) );
111 + }
112 + }
113 +
114 + @Override
115 + public void setEnabled( boolean pEnabled ) {
116 + mEnabled = pEnabled;
117 + for ( int i = 0; i < mRadioButtons.size(); i++ ) {
118 + RadioButtonProxy radioButtonProxy = getRadioButon( i );
119 + radioButtonProxy.setEnabled( pEnabled );
120 + }
121 + stateChanged();
122 + }
123 +
124 + // AbstractFormElement
125 +
126 + @Override
127 + protected void setEnabledStyles() {
128 + super.setEnabledStyles();
129 + mInfoIndicator.setVisible( hasFocus() );
130 + }
131 +
132 + @Override
133 + public void publishAnyPendingChanges() {
134 + FocusSelection zFS = determineFocusSelection();
135 + RadioButtonProxy prevLastSelection = mLastSelection;
136 + if ( zFS.getSelected() != null ) {
137 + setLastSelected( zFS.getSelected() );
138 + }
139 + RadioButtonProxy curLastSelection = mLastSelection;
140 + if ( prevLastSelection != curLastSelection ) {
141 + fireChangeListeners();
142 + }
143 + if ( mReportedFocus ) {
144 + mReportedFocus = false;
145 + fireBlurListeners();
146 + }
147 + super.publishAnyPendingChanges();
148 + }
149 +
150 + // Support...
151 +
152 + @Override
153 + public void simulateUserTextEntry( String pText ) {
154 + RadioButtonProxy zCurrentSelection = mLastSelection;
155 + setLastSelected( determineItemToSelect( ConstrainTo.notNull( pText ).trim() ) );
156 + if ( zCurrentSelection != mLastSelection ) {
157 + mLastSelection.setChecked();
158 + fireChangeListeners();
159 + }
160 + pullFocusTo( mLastSelection );
161 + }
162 +
163 + private RadioButtonProxy determineItemToSelect( String pText ) {
164 + for ( int i = 0; i < mRadioButtons.size(); i++ ) {
165 + RadioButtonProxy radioButtonProxy = getRadioButon( i );
166 + if ( pText.equals( radioButtonProxy.getKeyValuePair().toStringValue() ) ) {
167 + return radioButtonProxy;
168 + }
169 + }
170 + throw new IllegalArgumentException( "simulateUserTextEntry on '" + mFieldLabel + "' to:" + pText );
171 + }
172 +
173 + //vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv//
174 +
175 + private RadioButtonProxy getProxyFor( Object pNewValue ) {
176 + Object pairKey;
177 + if ( pNewValue instanceof SimpleKeyValuePair ) {
178 + pairKey = ((SimpleKeyValuePair) pNewValue).getKey();
179 + } else if ( pNewValue instanceof String ) {
180 + pairKey = pNewValue;
181 + } else {
182 + pairKey = "?" + pNewValue;
183 + }
184 + for ( int i = 0; i < mRadioButtons.size(); i++ ) {
185 + RadioButtonProxy radioButtonProxy = getRadioButon( i );
186 + if ( pairKey.equals( radioButtonProxy.getKeyValuePair().getKey() ) ) {
187 + return radioButtonProxy;
188 + }
189 + }
190 + throw new IllegalArgumentException( "No Valid Option in Radio Group of: " + pNewValue );
191 + }
192 +
193 + private SimpleKeyValuePair setDefaultSelection() {
194 + SimpleKeyValuePair rv = getRadioButon( 0 ).getKeyValuePair();
195 + setCurrentValue( rv );
196 + return rv;
197 + }
198 +
199 + private void setSelected( RadioButtonProxy pRadioButtonProxy ) {
200 + setInitialSelection( pRadioButtonProxy );
201 + setLastSelected( pRadioButtonProxy );
202 + /*
203 + * Work around for IE bug where you can select multiple radio buttons
204 + * when not attached (part 1)
205 + */
206 + if ( isAttached() ) {
207 + pRadioButtonProxy.setChecked();
208 + }
209 + }
210 +
211 + @Override
212 + protected void onLoad() {
213 + super.onLoad();
214 + /*
215 + * Work around for IE bug where you can select multiple radio buttons
216 + * when not attached (part 2)
217 + */
218 + if ( mLastSelection != null ) {
219 + mLastSelection.setChecked();
220 + }
221 + }
222 +
223 + private FocusSelection determineFocusSelection() {
224 + boolean anyFocus = false;
225 + RadioButtonProxy selected = null;
226 + for ( int i = 0; i < mRadioButtons.size(); i++ ) {
227 + RadioButtonProxy radioButtonProxy = getRadioButon( i );
228 + if ( radioButtonProxy.isChecked() ) {
229 + selected = radioButtonProxy;
230 + }
231 + anyFocus |= radioButtonProxy.hasFocus();
232 + }
233 + return new FocusSelection( anyFocus, selected );
234 + }
235 +
236 + private static class FocusSelection {
237 + private boolean mFocused;
238 + private RadioButtonProxy mSelected;
239 +
240 + public FocusSelection( boolean pFocused, RadioButtonProxy pSelected ) {
241 + mFocused = pFocused;
242 + mSelected = pSelected;
243 + }
244 +
245 + public boolean isFocused() {
246 + return mFocused;
247 + }
248 +
249 + public RadioButtonProxy getSelected() {
250 + return mSelected;
251 + }
252 + }
253 +
254 + public void publishAnyDelayedChanges() {
255 + if ( mPendingReentries++ != 0 ) {
256 + return;
257 + }
258 + do {
259 + FocusSelection zFS = determineFocusSelection();
260 + boolean shouldIssueBlur = false;
261 + if ( zFS.isFocused() != mReportedFocus ) {
262 + if ( zFS.isFocused() ) {
263 + mReportedFocus = true;
264 + fireFocusListeners();
265 + } else {
266 + shouldIssueBlur = true;
267 + }
268 + }
269 + RadioButtonProxy prevLastSelection = mLastSelection;
270 + if ( zFS.getSelected() != null ) {
271 + setLastSelected( zFS.getSelected() );
272 + }
273 + RadioButtonProxy curLastSelection = mLastSelection;
274 + if ( prevLastSelection != curLastSelection ) {
275 + fireChangeListeners();
276 + }
277 + if ( shouldIssueBlur ) {
278 + mReportedFocus = false;
279 + fireBlurListeners();
280 + }
281 + }
282 + while ( --mPendingReentries > 0 );
283 + }
284 +
285 + private int mPendingReentries = 0;
286 + private boolean mReportedFocus = false;
287 + private RadioButtonProxy mInitialSelection = null;
288 + private RadioButtonProxy mLastSelection = null;
289 +
290 + private void setInitialSelection( RadioButtonProxy pInitialSelection ) {
291 + RadioButtonProxy prev = mInitialSelection;
292 + switchChangeFromTo( prev, mInitialSelection = pInitialSelection );
293 + }
294 +
295 + private RadioButtonProxy setLastSelected( RadioButtonProxy pSelected ) {
296 + return mLastSelection = switchChangeFromTo( mLastSelection, pSelected );
297 + }
298 +
299 + private RadioButtonProxy switchChangeFromTo( RadioButtonProxy pPrev, RadioButtonProxy pNew ) {
300 + if ( pPrev != pNew ) {
301 + if ( pPrev != null ) {
302 + pPrev.removeChangeIndicator();
303 + }
304 + if ( pNew != null ) {
305 + if ( pNew != mInitialSelection ) {
306 + mInitialSelection.addChangeIndicator();
307 + pNew.addChangeIndicator();
308 + } else {
309 + mInitialSelection.removeChangeIndicator();
310 + pNew.removeChangeIndicator();
311 + }
312 + }
313 + }
314 + return pNew;
315 + }
316 +
317 + //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//
318 +
319 + private DelayedStateChecker mDelayedStateChecker = null;
320 +
321 + private class DelayedStateChecker implements Command {
322 + private int mPendingDelays = 0;
323 +
324 + public Command getCommandToDefer() {
325 + mPendingDelays++;
326 + return this;
327 + }
328 +
329 + @Override
330 + public void execute() {
331 + if ( --mPendingDelays == 0 ) {
332 + publishAnyDelayedChanges();
333 + }
334 + }
335 + }
336 +
337 + private static class RadioButtonProxy extends Composite implements Focusable,
338 + FocusHandler,
339 + BlurHandler,
340 + ClickHandler {
341 + private SimpleKeyValuePair mKeyValuePair;
342 + private ChangeHandler mChangeHandler;
343 + private RadioButton mRadioButton;
344 + private boolean mHasFocus = false;
345 + private boolean mChangeIndicated = false;
346 +
347 + public RadioButtonProxy( String pRadioGroupName, SimpleKeyValuePair pKeyValuePair, ChangeHandler pChangeHandler ) {
348 + mKeyValuePair = pKeyValuePair;
349 + mChangeHandler = pChangeHandler;
350 + String zLabel = HTMLize.escapeNoWrap( pKeyValuePair.toStringValue() );
351 + mRadioButton = new RadioButton( pRadioGroupName, zLabel, true );
352 + //noinspection GWTStyleCheck
353 + mRadioButton.setStyleName( "frmRadioBtn" );
354 +
355 + initWidget( buildComponentPanel() );
356 +
357 + mRadioButton.addFocusHandler( this );
358 + mRadioButton.addBlurHandler( this );
359 + mRadioButton.addClickHandler( this );
360 +
361 + // setStyleName( BASE_STYLE_NAME );
362 + }
363 +
364 + private HTMLPanel buildComponentPanel() {
365 + String inputId = "input" + StaticSimpleIdSource.getNext();
366 + String html = "<nowrap><table cellpadding='0' cellspacing='0'><tr><td id='" + inputId + "'></td></tr></table></nowrap>";
367 +
368 + HTMLPanel panel = new HTMLPanel( html );
369 + panel.add( mRadioButton, inputId );
370 + return panel;
371 + }
372 +
373 + @Override
374 + public int getTabIndex() {
375 + return mRadioButton.getTabIndex();
376 + }
377 +
378 + @Override
379 + public void setTabIndex( int index ) {
380 + mRadioButton.setTabIndex( index );
381 + }
382 +
383 + @Override
384 + public void setAccessKey( char key ) {
385 + mRadioButton.setAccessKey( key );
386 + }
387 +
388 + @Override
389 + public void setFocus( boolean pFocus ) {
390 + mRadioButton.setFocus( pFocus );
391 + }
392 +
393 + @Override
394 + public void onFocus( FocusEvent event ) {
395 + // System.out.println( "RadioButtonProxy.onFocus: " + mKeyValuePair );
396 + mHasFocus = true;
397 + mChangeHandler.onChange( null );
398 + }
399 +
400 + @Override
401 + public void onBlur( BlurEvent event ) {
402 + // System.out.println( "RadioButtonProxy.onLostFocus: " + mKeyValuePair );
403 + mHasFocus = false;
404 + mChangeHandler.onChange( null );
405 + }
406 +
407 + @Override
408 + public void onClick( ClickEvent event ) {
409 + // System.out.println( "RadioButtonProxy.onClick: " + mKeyValuePair );
410 + mChangeHandler.onChange( null );
411 + }
412 +
413 + public SimpleKeyValuePair getKeyValuePair() {
414 + return mKeyValuePair;
415 + }
416 +
417 + public void setChecked() {
418 + mRadioButton.setValue( true );
419 + }
420 +
421 + public void setEnabled( boolean pEnabled ) {
422 + mRadioButton.setEnabled( pEnabled );
423 + }
424 +
425 + public boolean isChecked() {
426 + return mRadioButton.getValue();
427 + }
428 +
429 + public boolean hasFocus() {
430 + return mHasFocus;
431 + }
432 +
433 + public void addChangeIndicator() {
434 + if ( !mChangeIndicated ) {
435 + mChangeIndicated = true;
436 + //noinspection GWTStyleCheck
437 + mRadioButton.addStyleName( "frmRadioBtn-Changed" );
438 + }
439 + }
440 +
441 + public void removeChangeIndicator() {
442 + if ( mChangeIndicated ) {
443 + mChangeIndicated = false;
444 + //noinspection GWTStyleCheck
445 + mRadioButton.removeStyleName( "frmRadioBtn-Changed" );
446 + }
447 + }
448 +
449 + @Override
450 + public String toString() {
451 + return "RadioButtonProxy: " + mKeyValuePair.toStringValue();
452 + }
453 + }
454 +
455 + private static class InfoIndicator extends Widget {
456 + private Element iconImg = DOM.createImg();
457 + private boolean mCanShow = false;
458 +
459 + public InfoIndicator() {
460 + Element span = DOM.createSpan();
461 + // DOM.setElementProperty( span, "className", "litesoft-FormComponentIndicatorContainer" );
462 + setElement( span );
463 +
464 + CommonElementHelper.setImgSrc( iconImg, TransparentImage.URL );
465 + CommonElementHelper.setStyleClass( iconImg, "litesoft-FormComponentIndicator" );
466 + DOM.appendChild( span, iconImg );
467 +
468 + setVisible( false );
469 + }
470 +
471 + public void setTooltip( String pTooltip ) {
472 + mCanShow = (pTooltip.length() != 0);
473 + DOM.setElementProperty( iconImg, "title", pTooltip );
474 + }
475 +
476 + @Override
477 + public void setVisible( boolean pVisible ) {
478 + getElement().getStyle().setDisplay( (mCanShow && pVisible) ? Style.Display.INLINE : Style.Display.NONE );
479 + }
480 + }
481 +
482 + private static SimpleKeyValuePair[] convertToKeyValuePairs( String[] pOptions ) {
483 + if ( pOptions == null ) {
484 + return SimpleKeyValuePair.EMPTY_ARRAY;
485 + }
486 + SimpleKeyValuePair[] rv = new SimpleKeyValuePair[pOptions.length];
487 + for ( int i = 0; i < pOptions.length; i++ ) {
488 + rv[i] = convertToKeyValuePair( pOptions[i] );
489 + }
490 + return rv;
491 + }
492 +
493 + private static SimpleKeyValuePair convertToKeyValuePair( String pOption ) {
494 + return (pOption != null) ? new StringKeyValuePair( pOption, pOption ) : null;
495 + }
496 + }