1
0
mirror of https://github.com/arduino/Arduino.git synced 2024-12-01 12:24:14 +01:00

Merge pull request #9158 from joew46167/master

Make update boards and libraries startup dialog accessible -
This commit is contained in:
Martino Facchin 2019-08-21 10:32:33 +02:00 committed by GitHub
commit 140f8e345c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 192 additions and 20 deletions

View File

@ -29,32 +29,34 @@
package cc.arduino.contributions; package cc.arduino.contributions;
import cc.arduino.UpdatableBoardsLibsFakeURLsHandler;
import cc.arduino.contributions.libraries.LibraryInstaller; import cc.arduino.contributions.libraries.LibraryInstaller;
import cc.arduino.contributions.libraries.filters.UpdatableLibraryPredicate; import cc.arduino.contributions.libraries.filters.UpdatableLibraryPredicate;
import cc.arduino.contributions.packages.ContributionInstaller; import cc.arduino.contributions.packages.ContributionInstaller;
import cc.arduino.contributions.packages.filters.UpdatablePlatformPredicate; import cc.arduino.contributions.packages.filters.UpdatablePlatformPredicate;
import cc.arduino.view.NotificationPopup; import cc.arduino.view.NotificationPopup;
import processing.app.Base; import org.apache.logging.log4j.LogManager;
import processing.app.BaseNoGui; import processing.app.*;
import processing.app.Editor;
import processing.app.I18n;
import javax.swing.*; import javax.swing.*;
import javax.swing.event.HyperlinkListener; import javax.swing.event.HyperlinkListener;
import java.awt.event.WindowEvent; import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener; import java.awt.event.WindowFocusListener;
import java.net.URL;
import java.util.TimerTask; import java.util.TimerTask;
import static processing.app.I18n.tr; import static processing.app.I18n.tr;
public class ContributionsSelfCheck extends TimerTask { public class ContributionsSelfCheck extends TimerTask implements NotificationPopup.OptionalButtonCallbacks {
private final Base base; private final Base base;
private final HyperlinkListener hyperlinkListener; private final HyperlinkListener hyperlinkListener;
private final ContributionInstaller contributionInstaller; private final ContributionInstaller contributionInstaller;
private final LibraryInstaller libraryInstaller; private final LibraryInstaller libraryInstaller;
private final ProgressListener progressListener; private final ProgressListener progressListener;
private final String boardsManagerURL = "http://boardsmanager/DropdownUpdatableCoresItem";
private final String libraryManagerURL = "http://librarymanager/DropdownUpdatableLibrariesItem";
private volatile boolean cancelled; private volatile boolean cancelled;
private volatile NotificationPopup notificationPopup; private volatile NotificationPopup notificationPopup;
@ -81,13 +83,41 @@ public class ContributionsSelfCheck extends TimerTask {
return; return;
} }
String text; boolean setAccessible = PreferencesData.getBoolean("ide.accessible");
final String text;
final String button1Name;
final String button2Name;
String openAnchorBoards = "<a href=\"" + boardsManagerURL + "\">";
String closeAnchorBoards = "</a>";
String openAnchorLibraries = "<a href=\"" + libraryManagerURL + "\">";
String closeAnchorLibraries = "</a>";
// if accessibility mode and board updates are available set the button name and clear the anchors
if(setAccessible && updatablePlatforms) {
button1Name = tr("Boards");
openAnchorBoards = "";
closeAnchorBoards = "";
}
else { // when not accessibility mode or no boards to update no button is needed
button1Name = null;
}
// if accessibility mode and libraries updates are available set the button name and clear the anchors
if (setAccessible && updatableLibraries) {
button2Name = tr("Libraries");
openAnchorLibraries = "";
closeAnchorLibraries = "";
}
else { // when not accessibility mode or no libraries to update no button is needed
button2Name = null;
}
if (updatableLibraries && !updatablePlatforms) { if (updatableLibraries && !updatablePlatforms) {
text = I18n.format(tr("Updates available for some of your {0}libraries{1}"), "<a href=\"http://librarymanager/DropdownUpdatableLibrariesItem\">", "</a>"); text = I18n.format(tr("Updates available for some of your {0}libraries{1}"), openAnchorLibraries, closeAnchorLibraries);
} else if (!updatableLibraries && updatablePlatforms) { } else if (!updatableLibraries && updatablePlatforms) {
text = I18n.format(tr("Updates available for some of your {0}boards{1}"), "<a href=\"http://boardsmanager/DropdownUpdatableCoresItem\">", "</a>"); text = I18n.format(tr("Updates available for some of your {0}boards{1}"), openAnchorBoards, closeAnchorBoards);
} else { } else {
text = I18n.format(tr("Updates available for some of your {0}boards{1} and {2}libraries{3}"), "<a href=\"http://boardsmanager/DropdownUpdatableCoresItem\">", "</a>", "<a href=\"http://librarymanager/DropdownUpdatableLibrariesItem\">", "</a>"); text = I18n.format(tr("Updates available for some of your {0}libraries{1} and {2}libraries{3}"), openAnchorBoards, closeAnchorBoards, openAnchorLibraries, closeAnchorLibraries);
} }
if (cancelled) { if (cancelled) {
@ -96,7 +126,13 @@ public class ContributionsSelfCheck extends TimerTask {
SwingUtilities.invokeLater(() -> { SwingUtilities.invokeLater(() -> {
Editor ed = base.getActiveEditor(); Editor ed = base.getActiveEditor();
boolean accessibleIde = PreferencesData.getBoolean("ide.accessible");
if (accessibleIde) {
notificationPopup = new NotificationPopup(ed, hyperlinkListener, text, false, this, button1Name, button2Name);
}
else { // if not accessible view leave it the same
notificationPopup = new NotificationPopup(ed, hyperlinkListener, text); notificationPopup = new NotificationPopup(ed, hyperlinkListener, text);
}
if (ed.isFocused()) { if (ed.isFocused()) {
notificationPopup.begin(); notificationPopup.begin();
return; return;
@ -122,6 +158,24 @@ public class ContributionsSelfCheck extends TimerTask {
}); });
} }
private void goToManager(String link) {
try {
((UpdatableBoardsLibsFakeURLsHandler) hyperlinkListener).openBoardLibManager(new URL(link));
}
catch (Exception e){
LogManager.getLogger(ContributionsSelfCheck.class).warn("Exception while attempting to go to board manager", e);
}
}
// callback for boards button
public void onOptionalButton1Callback() {
goToManager(boardsManagerURL);
}
// callback for libraries button
public void onOptionalButton2Callback() {
goToManager(libraryManagerURL);
}
static boolean checkForUpdatablePlatforms() { static boolean checkForUpdatablePlatforms() {
return BaseNoGui.indexer.getPackages().stream() return BaseNoGui.indexer.getPackages().stream()
.flatMap(pack -> pack.getPlatforms().stream()) .flatMap(pack -> pack.getPlatforms().stream())

View File

@ -36,12 +36,7 @@ import java.awt.FlowLayout;
import java.awt.Frame; import java.awt.Frame;
import java.awt.Image; import java.awt.Image;
import java.awt.Point; import java.awt.Point;
import java.awt.event.ComponentAdapter; import java.awt.event.*;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
@ -55,22 +50,46 @@ import javax.swing.border.LineBorder;
import javax.swing.event.HyperlinkListener; import javax.swing.event.HyperlinkListener;
import cc.arduino.Constants; import cc.arduino.Constants;
import processing.app.PreferencesData;
import processing.app.Theme; import processing.app.Theme;
public class NotificationPopup extends JDialog { import java.awt.event.KeyEvent;
import static processing.app.I18n.tr;
public class NotificationPopup extends JDialog {
private Timer autoCloseTimer = new Timer(false); private Timer autoCloseTimer = new Timer(false);
private boolean autoClose = true; private boolean autoClose = true;
private OptionalButtonCallbacks optionalButtonCallbacks;
public interface OptionalButtonCallbacks {
void onOptionalButton1Callback();
void onOptionalButton2Callback();
}
public NotificationPopup(Frame parent, HyperlinkListener hyperlinkListener, public NotificationPopup(Frame parent, HyperlinkListener hyperlinkListener,
String message) { String message) {
this(parent, hyperlinkListener, message, true); this(parent, hyperlinkListener, message, true, null, null, null);
} }
public NotificationPopup(Frame parent, HyperlinkListener hyperlinkListener, public NotificationPopup(Frame parent, HyperlinkListener hyperlinkListener,
String message, boolean _autoClose) { String message, boolean _autoClose) {
this(parent, hyperlinkListener, message, _autoClose, null, null, null);
}
public NotificationPopup(Frame parent, HyperlinkListener hyperlinkListener,
String message, boolean _autoClose, OptionalButtonCallbacks listener, String button1Name, String button2Name) {
super(parent, false); super(parent, false);
if (!PreferencesData.getBoolean("ide.accessible")) {
// often auto-close is too fast for users of screen readers, so don't allow it.
autoClose = _autoClose; autoClose = _autoClose;
}
else {
autoClose = false;
}
optionalButtonCallbacks = listener;
setLayout(new FlowLayout()); setLayout(new FlowLayout());
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
setUndecorated(true); setUndecorated(true);
@ -90,6 +109,74 @@ public class NotificationPopup extends JDialog {
text.addHyperlinkListener(hyperlinkListener); text.addHyperlinkListener(hyperlinkListener);
add(text); add(text);
if (button1Name != null) {
JButton optionalButton1 = new JButton(tr(button1Name));
MouseAdapter button1Action = new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (optionalButtonCallbacks != null) {
optionalButtonCallbacks.onOptionalButton1Callback();
}
}
};
optionalButton1.addMouseListener(button1Action);
KeyListener button1Key = new KeyListener() {
// Ignore when the key is typed - only act once the key is released
public void keyTyped(KeyEvent e) {
// do nothing here, wait until the key is released
}
// Ignore when the key is pressed - only act once the key is released
public void keyPressed(KeyEvent e) {
// do nothing here, wait until the key is released
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if ((key == KeyEvent.VK_ENTER) || (key == KeyEvent.VK_SPACE)) {
optionalButtonCallbacks.onOptionalButton1Callback();
}
}
};
optionalButton1.addKeyListener(button1Key);
add(optionalButton1);
}
if (button2Name != null) {
JButton optionalButton2 = new JButton(tr(button2Name));
MouseAdapter button2Action = new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (optionalButtonCallbacks != null) {
optionalButtonCallbacks.onOptionalButton2Callback();
}
}
};
optionalButton2.addMouseListener(button2Action);
KeyListener button2Key = new KeyListener() {
// Ignore when the key is typed - only act once the key is released
public void keyTyped(KeyEvent e) {
// do nothing here, wait until the key is released
}
// Ignore when the key is pressed - only act once the key is released
public void keyPressed(KeyEvent e) {
// do nothing here, wait until the key is released
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if ((key == KeyEvent.VK_ENTER) || (key == KeyEvent.VK_SPACE)) {
optionalButtonCallbacks.onOptionalButton2Callback();
}
}
};
optionalButton2.addKeyListener(button2Key);
add(optionalButton2);
}
Image close = Theme.getThemeImage("close", this, scale(22), scale(22)); Image close = Theme.getThemeImage("close", this, scale(22), scale(22));
JButton closeButton = new JButton(new ImageIcon(close)); JButton closeButton = new JButton(new ImageIcon(close));
closeButton.setBorder(null); closeButton.setBorder(null);
@ -97,6 +184,26 @@ public class NotificationPopup extends JDialog {
closeButton.setHideActionText(true); closeButton.setHideActionText(true);
closeButton.setOpaque(false); closeButton.setOpaque(false);
closeButton.setBackground(new Color(0, 0, 0, 0)); closeButton.setBackground(new Color(0, 0, 0, 0));
closeButton.getAccessibleContext().setAccessibleDescription(tr("Close"));
KeyListener closeKey = new KeyListener() {
// Ignore when the key is typed - only act once the key is released
public void keyTyped(KeyEvent e) {
// do nothing here, wait until the key is released
}
// Ignore when the key is pressed - only act once the key is released
public void keyPressed(KeyEvent e) {
// do nothing here, wait until the key is released
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if ((key == KeyEvent.VK_ENTER) || (key == KeyEvent.VK_SPACE)) {
close();
}
}
};
closeButton.addKeyListener(closeKey);
add(closeButton); add(closeButton);
MouseAdapter closeOnClick = new MouseAdapter() { MouseAdapter closeOnClick = new MouseAdapter() {
@ -158,5 +265,9 @@ public class NotificationPopup extends JDialog {
}, Constants.NOTIFICATION_POPUP_AUTOCLOSE_DELAY); }, Constants.NOTIFICATION_POPUP_AUTOCLOSE_DELAY);
} }
setVisible(true); setVisible(true);
if (PreferencesData.getBoolean("ide.accessible")) {
requestFocus();
setModal(true);
}
} }
} }

View File

@ -134,6 +134,7 @@ public class Preferences extends javax.swing.JDialog {
externalEditorBox = new javax.swing.JCheckBox(); externalEditorBox = new javax.swing.JCheckBox();
checkUpdatesBox = new javax.swing.JCheckBox(); checkUpdatesBox = new javax.swing.JCheckBox();
saveVerifyUploadBox = new javax.swing.JCheckBox(); saveVerifyUploadBox = new javax.swing.JCheckBox();
accessibleIDEBox = new javax.swing.JCheckBox();
jLabel1 = new javax.swing.JLabel(); jLabel1 = new javax.swing.JLabel();
jLabel2 = new javax.swing.JLabel(); jLabel2 = new javax.swing.JLabel();
scaleSpinner = new javax.swing.JSpinner(); scaleSpinner = new javax.swing.JSpinner();
@ -281,6 +282,9 @@ public class Preferences extends javax.swing.JDialog {
saveVerifyUploadBox.setText(tr("Save when verifying or uploading")); saveVerifyUploadBox.setText(tr("Save when verifying or uploading"));
checkboxesContainer.add(saveVerifyUploadBox); checkboxesContainer.add(saveVerifyUploadBox);
accessibleIDEBox.setText(tr("Use accessibility features"));
checkboxesContainer.add(accessibleIDEBox);
jLabel1.setText(tr("Interface scale:")); jLabel1.setText(tr("Interface scale:"));
jLabel2.setText(tr(" (requires restart of Arduino)")); jLabel2.setText(tr(" (requires restart of Arduino)"));
@ -713,6 +717,7 @@ public class Preferences extends javax.swing.JDialog {
private javax.swing.JCheckBox autoScaleCheckBox; private javax.swing.JCheckBox autoScaleCheckBox;
private javax.swing.JButton browseButton; private javax.swing.JButton browseButton;
private javax.swing.JCheckBox checkUpdatesBox; private javax.swing.JCheckBox checkUpdatesBox;
private javax.swing.JCheckBox accessibleIDEBox;
private javax.swing.JPanel checkboxesContainer; private javax.swing.JPanel checkboxesContainer;
private javax.swing.JComboBox comboLanguage; private javax.swing.JComboBox comboLanguage;
private javax.swing.JLabel comboLanguageLabel; private javax.swing.JLabel comboLanguageLabel;
@ -826,7 +831,7 @@ public class Preferences extends javax.swing.JDialog {
PreferencesData.setBoolean("update.check", checkUpdatesBox.isSelected()); PreferencesData.setBoolean("update.check", checkUpdatesBox.isSelected());
PreferencesData.setBoolean("editor.save_on_verify", saveVerifyUploadBox.isSelected()); PreferencesData.setBoolean("ide.accessible", accessibleIDEBox.isSelected());
PreferencesData.set("boardsmanager.additional.urls", additionalBoardsManagerField.getText().replace("\r\n", "\n").replace("\r", "\n").replace("\n", ",")); PreferencesData.set("boardsmanager.additional.urls", additionalBoardsManagerField.getText().replace("\r\n", "\n").replace("\r", "\n").replace("\n", ","));
@ -902,6 +907,8 @@ public class Preferences extends javax.swing.JDialog {
PreferencesData.setBoolean("editor.update_extension", true); PreferencesData.setBoolean("editor.update_extension", true);
} }
accessibleIDEBox.setSelected(PreferencesData.getBoolean("ide.accessible"));
saveVerifyUploadBox.setSelected(PreferencesData.getBoolean("editor.save_on_verify")); saveVerifyUploadBox.setSelected(PreferencesData.getBoolean("editor.save_on_verify"));
additionalBoardsManagerField.setText(PreferencesData.get("boardsmanager.additional.urls")); additionalBoardsManagerField.setText(PreferencesData.get("boardsmanager.additional.urls"));