mirror of
https://github.com/arduino/Arduino.git
synced 2024-11-29 10:24:12 +01:00
Merge pull request #9158 from joew46167/master
Make update boards and libraries startup dialog accessible -
This commit is contained in:
commit
140f8e345c
@ -29,32 +29,34 @@
|
||||
|
||||
package cc.arduino.contributions;
|
||||
|
||||
import cc.arduino.UpdatableBoardsLibsFakeURLsHandler;
|
||||
import cc.arduino.contributions.libraries.LibraryInstaller;
|
||||
import cc.arduino.contributions.libraries.filters.UpdatableLibraryPredicate;
|
||||
import cc.arduino.contributions.packages.ContributionInstaller;
|
||||
import cc.arduino.contributions.packages.filters.UpdatablePlatformPredicate;
|
||||
import cc.arduino.view.NotificationPopup;
|
||||
import processing.app.Base;
|
||||
import processing.app.BaseNoGui;
|
||||
import processing.app.Editor;
|
||||
import processing.app.I18n;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import processing.app.*;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.HyperlinkListener;
|
||||
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.event.WindowFocusListener;
|
||||
import java.net.URL;
|
||||
import java.util.TimerTask;
|
||||
|
||||
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 HyperlinkListener hyperlinkListener;
|
||||
private final ContributionInstaller contributionInstaller;
|
||||
private final LibraryInstaller libraryInstaller;
|
||||
private final ProgressListener progressListener;
|
||||
private final String boardsManagerURL = "http://boardsmanager/DropdownUpdatableCoresItem";
|
||||
private final String libraryManagerURL = "http://librarymanager/DropdownUpdatableLibrariesItem";
|
||||
|
||||
private volatile boolean cancelled;
|
||||
private volatile NotificationPopup notificationPopup;
|
||||
@ -81,13 +83,41 @@ public class ContributionsSelfCheck extends TimerTask {
|
||||
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) {
|
||||
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) {
|
||||
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 {
|
||||
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) {
|
||||
@ -96,7 +126,13 @@ public class ContributionsSelfCheck extends TimerTask {
|
||||
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
Editor ed = base.getActiveEditor();
|
||||
notificationPopup = new NotificationPopup(ed, hyperlinkListener, text);
|
||||
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);
|
||||
}
|
||||
if (ed.isFocused()) {
|
||||
notificationPopup.begin();
|
||||
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() {
|
||||
return BaseNoGui.indexer.getPackages().stream()
|
||||
.flatMap(pack -> pack.getPlatforms().stream())
|
||||
|
@ -36,12 +36,7 @@ import java.awt.FlowLayout;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Image;
|
||||
import java.awt.Point;
|
||||
import java.awt.event.ComponentAdapter;
|
||||
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.awt.event.*;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
@ -55,22 +50,46 @@ import javax.swing.border.LineBorder;
|
||||
import javax.swing.event.HyperlinkListener;
|
||||
|
||||
import cc.arduino.Constants;
|
||||
import processing.app.PreferencesData;
|
||||
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 boolean autoClose = true;
|
||||
private OptionalButtonCallbacks optionalButtonCallbacks;
|
||||
|
||||
public interface OptionalButtonCallbacks {
|
||||
void onOptionalButton1Callback();
|
||||
void onOptionalButton2Callback();
|
||||
}
|
||||
|
||||
public NotificationPopup(Frame parent, HyperlinkListener hyperlinkListener,
|
||||
String message) {
|
||||
this(parent, hyperlinkListener, message, true);
|
||||
this(parent, hyperlinkListener, message, true, null, null, null);
|
||||
}
|
||||
|
||||
public NotificationPopup(Frame parent, HyperlinkListener hyperlinkListener,
|
||||
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);
|
||||
autoClose = _autoClose;
|
||||
|
||||
if (!PreferencesData.getBoolean("ide.accessible")) {
|
||||
// often auto-close is too fast for users of screen readers, so don't allow it.
|
||||
autoClose = _autoClose;
|
||||
}
|
||||
else {
|
||||
autoClose = false;
|
||||
}
|
||||
optionalButtonCallbacks = listener;
|
||||
|
||||
setLayout(new FlowLayout());
|
||||
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
|
||||
setUndecorated(true);
|
||||
@ -90,6 +109,74 @@ public class NotificationPopup extends JDialog {
|
||||
text.addHyperlinkListener(hyperlinkListener);
|
||||
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));
|
||||
JButton closeButton = new JButton(new ImageIcon(close));
|
||||
closeButton.setBorder(null);
|
||||
@ -97,6 +184,26 @@ public class NotificationPopup extends JDialog {
|
||||
closeButton.setHideActionText(true);
|
||||
closeButton.setOpaque(false);
|
||||
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);
|
||||
|
||||
MouseAdapter closeOnClick = new MouseAdapter() {
|
||||
@ -158,5 +265,9 @@ public class NotificationPopup extends JDialog {
|
||||
}, Constants.NOTIFICATION_POPUP_AUTOCLOSE_DELAY);
|
||||
}
|
||||
setVisible(true);
|
||||
if (PreferencesData.getBoolean("ide.accessible")) {
|
||||
requestFocus();
|
||||
setModal(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -134,6 +134,7 @@ public class Preferences extends javax.swing.JDialog {
|
||||
externalEditorBox = new javax.swing.JCheckBox();
|
||||
checkUpdatesBox = new javax.swing.JCheckBox();
|
||||
saveVerifyUploadBox = new javax.swing.JCheckBox();
|
||||
accessibleIDEBox = new javax.swing.JCheckBox();
|
||||
jLabel1 = new javax.swing.JLabel();
|
||||
jLabel2 = new javax.swing.JLabel();
|
||||
scaleSpinner = new javax.swing.JSpinner();
|
||||
@ -281,6 +282,9 @@ public class Preferences extends javax.swing.JDialog {
|
||||
saveVerifyUploadBox.setText(tr("Save when verifying or uploading"));
|
||||
checkboxesContainer.add(saveVerifyUploadBox);
|
||||
|
||||
accessibleIDEBox.setText(tr("Use accessibility features"));
|
||||
checkboxesContainer.add(accessibleIDEBox);
|
||||
|
||||
jLabel1.setText(tr("Interface scale:"));
|
||||
|
||||
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.JButton browseButton;
|
||||
private javax.swing.JCheckBox checkUpdatesBox;
|
||||
private javax.swing.JCheckBox accessibleIDEBox;
|
||||
private javax.swing.JPanel checkboxesContainer;
|
||||
private javax.swing.JComboBox comboLanguage;
|
||||
private javax.swing.JLabel comboLanguageLabel;
|
||||
@ -826,7 +831,7 @@ public class Preferences extends javax.swing.JDialog {
|
||||
|
||||
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", ","));
|
||||
|
||||
@ -902,6 +907,8 @@ public class Preferences extends javax.swing.JDialog {
|
||||
PreferencesData.setBoolean("editor.update_extension", true);
|
||||
}
|
||||
|
||||
accessibleIDEBox.setSelected(PreferencesData.getBoolean("ide.accessible"));
|
||||
|
||||
saveVerifyUploadBox.setSelected(PreferencesData.getBoolean("editor.save_on_verify"));
|
||||
|
||||
additionalBoardsManagerField.setText(PreferencesData.get("boardsmanager.additional.urls"));
|
||||
|
Loading…
Reference in New Issue
Block a user