1414import com .intellij .ui .components .fields .ExtendableTextField ;
1515import com .microsoft .azure .toolkit .lib .common .messager .AzureMessager ;
1616import com .microsoft .azure .toolkit .lib .common .operation .AzureOperation ;
17- import com .microsoft .azure .toolkit .lib .common .task .AzureTask ;
18- import com .microsoft .azure .toolkit .lib .common .task .AzureTaskManager ;
1917import com .microsoft .azure .toolkit .lib .common .utils .TailingDebouncer ;
2018import lombok .Getter ;
2119import lombok .Setter ;
22- import org .apache .commons .collections .CollectionUtils ;
20+ import org .apache .commons .collections4 .CollectionUtils ;
2321import org .apache .commons .lang .StringUtils ;
2422import org .apache .commons .lang3 .exception .ExceptionUtils ;
2523import rx .Observable ;
2624import rx .schedulers .Schedulers ;
2725
26+ import javax .accessibility .AccessibleRelation ;
2827import javax .annotation .Nonnull ;
2928import javax .annotation .Nullable ;
3029import javax .swing .*;
@@ -56,10 +55,7 @@ public abstract class AzureComboBox<T> extends ComboBox<T> implements AzureFormI
5655 private boolean required ;
5756 private Object value ;
5857 private boolean valueNotSet = true ;
59- private String label ;
60- @ Nullable
61- @ Setter
62- protected Boolean valueFixed ;
58+ protected boolean enabled = true ;
6359 @ Getter
6460 @ Setter
6561 private Supplier <? extends List <? extends T >> itemsLoader ;
@@ -73,7 +69,7 @@ public AzureComboBox(boolean refresh) {
7369 this .init ();
7470 this .refresher = new TailingDebouncer (this ::doRefreshItems , DEBOUNCE_DELAY );
7571 if (refresh ) {
76- AzureTaskManager . getInstance (). runLater ( this :: refreshItems , AzureTask . Modality . ANY );
72+ this . refreshItems ( );
7773 }
7874 }
7975
@@ -108,8 +104,7 @@ public void customize(@Nonnull final JList<? extends T> l, final T t, final int
108104 this .addPopupMenuListener (new AzureComboBoxPopupMenuListener ());
109105 }
110106 final TailingDebouncer valueDebouncer = new TailingDebouncer (() -> {
111- @ SuppressWarnings ("unchecked" )
112- final ValueListener <T >[] listeners = this .listenerList .getListeners (ValueListener .class );
107+ @ SuppressWarnings ("unchecked" ) final ValueListener <T >[] listeners = this .listenerList .getListeners (ValueListener .class );
113108 for (final ValueListener <T > listener : listeners ) {
114109 listener .onValueChanged (this .getValue ());
115110 }
@@ -118,9 +113,6 @@ public void customize(@Nonnull final JList<? extends T> l, final T t, final int
118113 if (e .getStateChange () == ItemEvent .SELECTED ) {
119114 this .refreshValue ();
120115 }
121- if (e .getStateChange () == ItemEvent .SELECTED || e .getStateChange () == ItemEvent .DESELECTED ) {
122- valueDebouncer .debounce ();
123- }
124116 });
125117 }
126118
@@ -136,7 +128,7 @@ public void setValue(final T val) {
136128
137129 public void setValue (final T val , final Boolean fixed ) {
138130 Optional .ofNullable (fixed ).ifPresent (f -> {
139- this .valueFixed = fixed ;
131+ this .setEnabled (! fixed ) ;
140132 this .setEditable (!f );
141133 });
142134 this .valueNotSet = false ;
@@ -150,7 +142,7 @@ public void setValue(final ItemReference<T> val) {
150142
151143 public void setValue (final ItemReference <T > val , final Boolean fixed ) {
152144 Optional .ofNullable (fixed ).ifPresent (f -> {
153- this .valueFixed = fixed ;
145+ this .setEnabled (! fixed ) ;
154146 this .setEditable (!f );
155147 });
156148 this .valueNotSet = false ;
@@ -159,23 +151,27 @@ public void setValue(final ItemReference<T> val, final Boolean fixed) {
159151 }
160152
161153 private void refreshValue () {
162- if (Objects .equals (this .value , this .getSelectedItem ())) {
163- return ;
164- }
165- final List <T > items = this .getItems ();
166- if (!this .valueNotSet && this .value instanceof AzureComboBox .ItemReference ) {
167- items .stream ().filter (i -> ((ItemReference <?>) this .value ).is (i )).findFirst ().ifPresent (this ::setValue );
168- }
169- if (this .valueNotSet && this .value == null && !items .isEmpty ()) {
170- super .setSelectedItem (items .get (0 ));
171- } else if (items .contains (this .value )) {
172- super .setSelectedItem (this .value );
173- } else if (value instanceof Draft ) {
174- // todo: unify model for custom created resource
175- super .addItem ((T ) value );
176- super .setSelectedItem (value );
154+ if (this .valueNotSet ) {
155+ if (this .getItemCount () > 0 && this .getSelectedIndex () != 0 ) {
156+ super .setSelectedIndex (0 );
157+ }
177158 } else {
178- super .setSelectedItem (null );
159+ final Object selected = this .getSelectedItem ();
160+ if (Objects .equals (selected , this .value ) || (this .value instanceof ItemReference && ((ItemReference <?>) this .value ).is (selected ))) {
161+ return ;
162+ }
163+ final List <T > items = this .getItems ();
164+ if (this .value instanceof AzureComboBox .ItemReference ) {
165+ items .stream ().filter (i -> ((ItemReference <?>) this .value ).is (i )).findFirst ().ifPresent (this ::setValue );
166+ } else if (this .value instanceof Draft ) {
167+ // todo: unify model for custom created resource
168+ super .addItem ((T ) this .value );
169+ super .setSelectedItem (this .value );
170+ } else if (items .contains (this .value )) {
171+ super .setSelectedItem (this .value );
172+ } else {
173+ super .setSelectedItem (null );
174+ }
179175 }
180176 }
181177
@@ -189,16 +185,16 @@ public void refreshItems() {
189185 }
190186
191187 @ AzureOperation (
192- name = "common|combobox.load_items" ,
193- params = {"this.label ()" },
194- type = AzureOperation .Type .ACTION
188+ name = "common|combobox.load_items" ,
189+ params = {"this.getLabel ()" },
190+ type = AzureOperation .Type .ACTION
195191 )
196192 private void doRefreshItems () {
197193 try {
198194 this .setLoading (true );
199195 final List <? extends T > items = this .loadItemsInner ();
200196 this .setLoading (false );
201- AzureTaskManager . getInstance (). runLater (() -> this .setItems (items ), AzureTask . Modality . ANY );
197+ this .setItems (items );
202198 } catch (final Exception e ) {
203199 final Throwable rootCause = ExceptionUtils .getRootCause (e );
204200 if (rootCause instanceof InterruptedIOException || rootCause instanceof InterruptedException ) {
@@ -217,26 +213,45 @@ public List<T> getItems() {
217213 return result ;
218214 }
219215
220- protected void setItems (final List <? extends T > items ) {
221- this .removeAllItems ();
222- items .forEach (super ::addItem );
223- this .refreshValue ();
216+ protected synchronized void setItems (final List <? extends T > items ) {
217+ SwingUtilities .invokeLater (() -> {
218+ final DefaultComboBoxModel <T > model = (DefaultComboBoxModel <T >) this .getModel ();
219+ model .removeAllElements ();
220+ model .addAll (items );
221+ this .refreshValue ();
222+ });
224223 }
225224
226225 public void clear () {
227- this .setItems (Collections .emptyList ());
226+ this .value = null ;
227+ this .valueNotSet = true ;
228+ final DefaultComboBoxModel <T > model = (DefaultComboBoxModel <T >) this .getModel ();
229+ model .removeAllElements ();
230+ this .refreshValue ();
228231 }
229232
230233 protected void setLoading (final boolean loading ) {
231- AzureTaskManager . getInstance (). runLater (() -> {
234+ SwingUtilities . invokeLater (() -> {
232235 if (loading ) {
233- this .setEnabled (false );
236+ super .setEnabled (false );
234237 this .setEditor (this .loadingSpinner );
235238 } else {
236- this .setEnabled (! Objects . equals ( valueFixed , true ) );
239+ super .setEnabled (this . enabled );
237240 this .setEditor (this .inputEditor );
238241 }
239- }, AzureTask .Modality .ANY );
242+ this .repaint ();
243+ });
244+ }
245+
246+ @ Override
247+ public void setEnabled (boolean b ) {
248+ this .enabled = b ;
249+ super .setEnabled (b );
250+ }
251+
252+ @ Override
253+ public boolean isEnabled () {
254+ return this .enabled || super .isEnabled ();
240255 }
241256
242257 protected String getItemText (Object item ) {
@@ -324,10 +339,10 @@ protected JTextField createEditorComponent() {
324339 protected ExtendableTextComponent .Extension getExtension () {
325340 final ExtendableTextComponent .Extension extension = AzureComboBox .this .getExtension ();
326341 return extension == null ? null : ExtendableTextComponent .Extension .create (
327- extension .getIcon (true ), extension .getTooltip (), () -> {
328- AzureComboBox .this .hidePopup ();
329- extension .getActionOnClick ().run ();
330- });
342+ extension .getIcon (true ), extension .getTooltip (), () -> {
343+ AzureComboBox .this .hidePopup ();
344+ extension .getActionOnClick ().run ();
345+ });
331346 }
332347 }
333348
@@ -344,7 +359,7 @@ public void setItem(Object item) {
344359
345360 protected ExtendableTextComponent .Extension getExtension () {
346361 return ExtendableTextComponent .Extension .create (
347- new AnimatedIcon .Default (), null , null );
362+ new AnimatedIcon .Default (), null , null );
348363 }
349364 }
350365
@@ -359,7 +374,7 @@ public void popupMenuWillBecomeVisible(final PopupMenuEvent e) {
359374 itemList = AzureComboBox .this .getItems ();
360375 // todo: support customized combo box filter
361376 comboFilterListener = new ComboFilterListener (itemList ,
362- (item , input ) -> StringUtils .containsIgnoreCase (getItemText (item ), input ));
377+ (item , input ) -> StringUtils .containsIgnoreCase (getItemText (item ), input ));
363378 getEditorComponent ().getDocument ().addDocumentListener (comboFilterListener );
364379 }
365380
@@ -397,28 +412,23 @@ public ComboFilterListener(List<? extends T> list, BiPredicate<? super T, ? supe
397412
398413 @ Override
399414 protected void textChanged (@ Nonnull final DocumentEvent documentEvent ) {
400- AzureTaskManager . getInstance (). runLater (() -> {
415+ SwingUtilities . invokeLater (() -> {
401416 try {
402417 final String text = documentEvent .getDocument ().getText (0 , documentEvent .getDocument ().getLength ());
403418 list .stream ().filter (item -> filter .test (item , text ) && !getItems ().contains (item )).forEach (AzureComboBox .this ::addItem );
404419 getItems ().stream ().filter (item -> !filter .test (item , text )).forEach (AzureComboBox .this ::removeItem );
405420 } catch (BadLocationException e ) {
406421 // swallow exception and show all items
407422 }
408- }, AzureTask . Modality . ANY );
423+ });
409424 }
410425 }
411426
412- public void setLabel (final String label ) {
413- this .label = label ;
414- }
415-
416427 public String getLabel () {
417- return Optional .ofNullable (this .label ).orElse ("" );
418- }
419-
420- private String label () {
421- return Optional .ofNullable (this .label ).orElse (this .getClass ().getSimpleName ());
428+ final JLabel label = (JLabel ) this .getClientProperty (AccessibleRelation .LABELED_BY );
429+ return Optional .ofNullable (label ).map (JLabel ::getText )
430+ .map (t -> t .endsWith (":" ) ? t .substring (0 , t .length () - 1 ) : t )
431+ .orElse (this .getClass ().getSimpleName ());
422432 }
423433
424434 public static class ItemReference <T > {
0 commit comments