Skip to content

Commit 6568d0e

Browse files
authored
Fix webapp combo box accessibility issues (#3541)
1 parent 08be070 commit 6568d0e

File tree

1 file changed

+44
-39
lines changed

1 file changed

+44
-39
lines changed

PluginsAndFeatures/azure-toolkit-for-intellij/src/com/microsoft/intellij/runner/webapp/webappconfig/slimui/WebAppSlimSettingPanel.java

Lines changed: 44 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
import com.intellij.icons.AllIcons;
44
import com.intellij.ide.IdeTooltipManager;
55
import com.intellij.openapi.project.Project;
6+
import com.intellij.openapi.ui.ComboBox;
67
import com.intellij.openapi.util.Comparing;
78
import com.intellij.packaging.artifacts.Artifact;
89
import com.intellij.ui.HideableDecorator;
910
import com.intellij.ui.HyperlinkLabel;
1011
import com.intellij.ui.ListCellRendererWrapper;
12+
import com.intellij.ui.PopupMenuListenerAdapter;
1113
import com.microsoft.azure.management.appservice.DeploymentSlot;
1214
import com.microsoft.azure.management.appservice.OperatingSystem;
1315
import com.microsoft.azure.management.appservice.WebApp;
@@ -39,19 +41,18 @@
3941
import javax.swing.JRadioButton;
4042
import javax.swing.JTextField;
4143
import javax.swing.SwingConstants;
44+
import javax.swing.event.EventListenerList;
45+
import javax.swing.event.PopupMenuEvent;
4246
import java.awt.Component;
4347
import java.awt.Dimension;
4448
import java.awt.KeyboardFocusManager;
45-
import java.awt.event.ActionListener;
46-
import java.awt.event.FocusEvent;
47-
import java.awt.event.FocusListener;
48-
import java.awt.event.MouseEvent;
49-
import java.awt.event.WindowAdapter;
50-
import java.awt.event.WindowEvent;
49+
import java.awt.event.*;
5150
import java.text.DateFormat;
5251
import java.text.SimpleDateFormat;
52+
import java.util.Arrays;
5353
import java.util.Date;
5454
import java.util.List;
55+
import java.util.UUID;
5556
import java.util.concurrent.TimeUnit;
5657
import java.util.stream.Collectors;
5758

@@ -62,10 +63,9 @@ public class WebAppSlimSettingPanel extends AzureSettingPanel<WebAppConfiguratio
6263
private static final String CREATE_NEW_WEBAPP = "Create New WebApp";
6364
private static final String REFRESHING_WEBAPP = "Refreshing...";
6465
private static final String DEPLOYMENT_SLOT_HOVER = "Deployment slots are live apps with their own hostnames. App" +
65-
" content and configurations elements can be swapped between two deployment slots, including the production " +
66-
"slot.";
66+
" content and configurations elements can be swapped between two deployment slots, including the production " +
67+
"slot.";
6768

68-
private boolean refreshingWebApp = false;
6969
private ResourceEx<WebApp> selectedWebApp = null;
7070
private WebAppDeployViewPresenterSlim presenter = null;
7171

@@ -105,7 +105,7 @@ public WebAppSlimSettingPanel(@NotNull Project project, @NotNull WebAppConfigura
105105
this.webAppConfiguration = webAppConfiguration;
106106
this.presenter = new WebAppDeployViewPresenterSlim();
107107
this.presenter.onAttachView(this);
108-
// Slot
108+
109109
final ButtonGroup slotButtonGroup = new ButtonGroup();
110110
slotButtonGroup.add(rbtExistingSlot);
111111
slotButtonGroup.add(rbtNewSlot);
@@ -114,13 +114,19 @@ public WebAppSlimSettingPanel(@NotNull Project project, @NotNull WebAppConfigura
114114

115115
chkDeployToSlot.addActionListener(e -> toggleSlotPanel(chkDeployToSlot.isSelected()));
116116

117-
cbxWebApp.addActionListener(e -> selectWebApp());
118117
cbxWebApp.setRenderer(new WebAppCombineBoxRender(cbxWebApp));
118+
cbxWebApp.addPopupMenuListener(new PopupMenuListenerAdapter() {
119+
@Override
120+
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
121+
selectWebApp();
122+
}
123+
});
119124
// Set the editor of combobox, otherwise it will use box render when popup is invisible, which may render the
120125
// combobox to twoline
121126
cbxWebApp.setEditor(new ComboBoxEditor() {
122-
Object item;
123-
JLabel label = new JLabel();
127+
private Object item;
128+
private JLabel label = new JLabel();
129+
private EventListenerList listenerList = new EventListenerList();
124130

125131
@Override
126132
public Component getEditorComponent() {
@@ -138,6 +144,8 @@ public void setItem(Object anObject) {
138144
ResourceEx<WebApp> webApp = (ResourceEx<WebApp>) anObject;
139145
label.setText(webApp.getResource().name());
140146
}
147+
label.getAccessibleContext().setAccessibleName(label.getText());
148+
label.getAccessibleContext().setAccessibleDescription(label.getText());
141149
}
142150

143151
@Override
@@ -152,15 +160,14 @@ public void selectAll() {
152160

153161
@Override
154162
public void addActionListener(ActionListener l) {
155-
return;
163+
listenerList.add(ActionListener.class, l);
156164
}
157165

158166
@Override
159167
public void removeActionListener(ActionListener l) {
160-
return;
168+
listenerList.remove(ActionListener.class, l);
161169
}
162170
});
163-
cbxWebApp.setEditable(true);
164171

165172
Icon informationIcon = AllIcons.General.Information;
166173
btnSlotHover.setIcon(informationIcon);
@@ -197,7 +204,6 @@ public void focusLost(FocusEvent focusEvent) {
197204
});
198205

199206
cbArtifact.addActionListener(e -> artifactActionPeformed((Artifact) cbArtifact.getSelectedItem()));
200-
201207
cbArtifact.setRenderer(new ListCellRendererWrapper<Artifact>() {
202208
@Override
203209
public void customize(JList list, Artifact artifact, int index, boolean isSelected, boolean cellHasFocus) {
@@ -235,12 +241,11 @@ public void disposeEditor() {
235241

236242
@Override
237243
public synchronized void fillWebApps(List<ResourceEx<WebApp>> webAppLists) {
238-
refreshingWebApp = true;
239244
cbxWebApp.removeAllItems();
240245
webAppLists = webAppLists.stream()
241-
.filter(resource -> WebAppUtils.isJavaWebApp(resource.getResource()))
242-
.sorted((a, b) -> a.getResource().name().compareToIgnoreCase(b.getResource().name()))
243-
.collect(Collectors.toList());
246+
.filter(resource -> WebAppUtils.isJavaWebApp(resource.getResource()))
247+
.sorted((a, b) -> a.getResource().name().compareToIgnoreCase(b.getResource().name()))
248+
.collect(Collectors.toList());
244249
if (webAppLists.size() == 0) {
245250
lblCreateWebApp.setVisible(true);
246251
cbxWebApp.setVisible(false);
@@ -251,13 +256,12 @@ public synchronized void fillWebApps(List<ResourceEx<WebApp>> webAppLists) {
251256
webAppLists.forEach(webAppResourceEx -> cbxWebApp.addItem(webAppResourceEx));
252257
// Find webapp which id equals to configuration, or use the first available one.
253258
final ResourceEx<WebApp> selectWebApp = webAppLists.stream()
254-
.filter(webAppResourceEx -> webAppResourceEx.getResource().id().equals(webAppConfiguration.getWebAppId()))
255-
.findFirst().orElse(webAppLists.get(0));
259+
.filter(webAppResourceEx -> webAppResourceEx.getResource().id().equals(webAppConfiguration.getWebAppId()))
260+
.findFirst().orElse(webAppLists.get(0));
256261
cbxWebApp.setSelectedItem(selectWebApp);
257262
}
258-
refreshingWebApp = false;
259-
cbxWebApp.setEnabled(true);
260263
selectWebApp();
264+
cbxWebApp.setEnabled(true);
261265
}
262266

263267
@Override
@@ -320,7 +324,7 @@ protected void resetFromConfig(@NotNull WebAppConfiguration configuration) {
320324
toggleSlotPanel(true);
321325
chkDeployToSlot.setSelected(true);
322326
final boolean useNewDeploymentSlot = Comparing.equal(configuration.getSlotName(),
323-
Constants.CREATE_NEW_SLOT);
327+
Constants.CREATE_NEW_SLOT);
324328
rbtNewSlot.setSelected(useNewDeploymentSlot);
325329
rbtExistingSlot.setSelected(!useNewDeploymentSlot);
326330
toggleSlotType(!useNewDeploymentSlot);
@@ -330,7 +334,7 @@ protected void resetFromConfig(@NotNull WebAppConfiguration configuration) {
330334
}
331335
final DateFormat df = new SimpleDateFormat("yyMMddHHmmss");
332336
final String defaultSlotName = StringUtils.isEmpty(webAppConfiguration.getNewSlotName()) ?
333-
String.format(DEFAULT_SLOT_NAME, df.format(new Date())) : webAppConfiguration.getNewSlotName();
337+
String.format(DEFAULT_SLOT_NAME, df.format(new Date())) : webAppConfiguration.getNewSlotName();
334338
txtNewSlotName.setText(defaultSlotName);
335339
chkToRoot.setSelected(configuration.isDeployToRoot());
336340
chkOpenBrowser.setSelected(configuration.isOpenBrowserAfterDeployment());
@@ -352,7 +356,7 @@ protected void apply(@NotNull WebAppConfiguration configuration) {
352356
if (chkDeployToSlot.isSelected()) {
353357
configuration.setDeployToSlot(true);
354358
configuration.setSlotName(cbxSlotName.getSelectedItem() == null ? "" :
355-
cbxSlotName.getSelectedItem().toString());
359+
cbxSlotName.getSelectedItem().toString());
356360
if (rbtNewSlot.isSelected()) {
357361
configuration.setSlotName(Constants.CREATE_NEW_SLOT);
358362
configuration.setNewSlotName(txtNewSlotName.getText());
@@ -367,15 +371,14 @@ protected void apply(@NotNull WebAppConfiguration configuration) {
367371

368372
private void selectWebApp() {
369373
Object value = cbxWebApp.getSelectedItem();
370-
if (Comparing.equal(CREATE_NEW_WEBAPP, value) && !refreshingWebApp) {
371-
cbxWebApp.setSelectedItem(null);
372-
createNewWebApp();
373-
} else if (value == null || value instanceof String) {
374-
return;
375-
} else {
374+
if (value != null && value instanceof ResourceEx) {
376375
chkDeployToSlot.setEnabled(true);
377376
selectedWebApp = (ResourceEx<WebApp>) cbxWebApp.getSelectedItem();
378377
presenter.onLoadDeploymentSlots(selectedWebApp);
378+
} else if (Comparing.equal(CREATE_NEW_WEBAPP, value)) {
379+
// Create new web app
380+
cbxWebApp.setSelectedItem(null);
381+
createNewWebApp();
379382
}
380383
}
381384

@@ -385,9 +388,9 @@ private boolean isAbleToDeployToRoot(final String targetName) {
385388
}
386389
final WebApp app = selectedWebApp.getResource();
387390
final boolean isDeployingWar =
388-
MavenRunTaskUtil.getFileType(targetName).equalsIgnoreCase(MavenConstants.TYPE_WAR);
391+
MavenRunTaskUtil.getFileType(targetName).equalsIgnoreCase(MavenConstants.TYPE_WAR);
389392
return isDeployingWar && (app.operatingSystem() == OperatingSystem.WINDOWS ||
390-
!Constants.LINUX_JAVA_SE_RUNTIME.equalsIgnoreCase(app.linuxFxVersion()));
393+
!Constants.LINUX_JAVA_SE_RUNTIME.equalsIgnoreCase(app.linuxFxVersion()));
391394
}
392395

393396
private void createNewWebApp() {
@@ -467,14 +470,16 @@ public void customize(JList jList, Object value, int i, boolean b, boolean b1) {
467470
setText(getStringLabelText((String) value));
468471
} else {
469472
final ResourceEx<WebApp> webApp = (ResourceEx<WebApp>) value;
470-
setText(getWebAppLabelText(webApp.getResource()));
473+
// For label in combobox textfield, just show webapp name
474+
final String text = i>=0 ? getWebAppLabelText(webApp.getResource()) : webApp.getResource().name();
475+
setText(text);
471476
}
472477
jList.setFixedCellHeight(cellHeight);
473478
}
474479

475480
private String getStringLabelText(String message) {
476481
return comboBox.isPopupVisible() ? String.format("<html><div>%s</div><small></small></html>",
477-
message) : message;
482+
message) : message;
478483
}
479484

480485
private String getWebAppLabelText(WebApp webApp) {
@@ -484,7 +489,7 @@ private String getWebAppLabelText(WebApp webApp) {
484489
final String resourceGroup = webApp.resourceGroupName();
485490

486491
return comboBox.isPopupVisible() ? String.format("<html><div>%s</div></div><small>OS:%s Runtime:%s " +
487-
"ResourceGroup:%s</small></html>", webAppName, os, runtime, resourceGroup) : webAppName;
492+
"ResourceGroup:%s</small></html>", webAppName, os, runtime, resourceGroup) : webAppName;
488493
}
489494
}
490495
}

0 commit comments

Comments
 (0)