From f9612bcdbdff39ef4204b8770bb36a00cddfd66c Mon Sep 17 00:00:00 2001 From: Federico Fissore Date: Mon, 3 Aug 2015 17:06:21 +0200 Subject: [PATCH] Updatable boards support and libraries notification --- .../UpdatableBoardsLibsFakeURLsHandler.java | 45 ++++ .../BuiltInCoreIsNewerCheck.java | 9 +- .../contributions/ContributionsSelfCheck.java | 83 +++++++ .../libraries/ui/LibraryManagerUI.java | 10 +- .../contributions/ui/InstallerJDialog.java | 13 ++ .../cc/arduino/view/NotificationPopup.form | 123 ++++++++++ .../cc/arduino/view/NotificationPopup.java | 218 ++++++++++++++++++ app/src/processing/app/Base.java | 50 ++-- arduino-core/src/cc/arduino/Constants.java | 4 +- build/build.xml | 2 + build/shared/lib/theme/close.png | Bin 0 -> 375 bytes 11 files changed, 522 insertions(+), 35 deletions(-) create mode 100644 app/src/cc/arduino/UpdatableBoardsLibsFakeURLsHandler.java create mode 100644 app/src/cc/arduino/contributions/ContributionsSelfCheck.java create mode 100644 app/src/cc/arduino/view/NotificationPopup.form create mode 100644 app/src/cc/arduino/view/NotificationPopup.java create mode 100644 build/shared/lib/theme/close.png diff --git a/app/src/cc/arduino/UpdatableBoardsLibsFakeURLsHandler.java b/app/src/cc/arduino/UpdatableBoardsLibsFakeURLsHandler.java new file mode 100644 index 000000000..050c4b3f6 --- /dev/null +++ b/app/src/cc/arduino/UpdatableBoardsLibsFakeURLsHandler.java @@ -0,0 +1,45 @@ +package cc.arduino; + +import processing.app.Base; + +import javax.swing.event.HyperlinkEvent; +import javax.swing.event.HyperlinkListener; +import java.net.URL; + +public class UpdatableBoardsLibsFakeURLsHandler implements HyperlinkListener { + + private static final String BOARDSMANAGER = "boardsmanager"; + private static final String LIBRARYMANAGER = "librarymanager"; + + private final Base base; + + public UpdatableBoardsLibsFakeURLsHandler(Base base) { + this.base = base; + } + + @Override + public void hyperlinkUpdate(HyperlinkEvent event) { + if (event.getEventType() != HyperlinkEvent.EventType.ACTIVATED) { + return; + } + + URL url = event.getURL(); + + if (BOARDSMANAGER.equals(url.getHost())) { + try { + base.openBoardsManager("", "DropdownUpdatableCoresItem"); + } catch (Exception e) { + e.printStackTrace(); + } + return; + } + + if (LIBRARYMANAGER.equals(url.getHost())) { + base.openLibraryManager("DropdownUpdatableLibrariesItem"); + return; + } + + throw new IllegalArgumentException(url.getHost() + " is invalid"); + } + +} diff --git a/app/src/cc/arduino/contributions/BuiltInCoreIsNewerCheck.java b/app/src/cc/arduino/contributions/BuiltInCoreIsNewerCheck.java index 683c00125..800756c19 100644 --- a/app/src/cc/arduino/contributions/BuiltInCoreIsNewerCheck.java +++ b/app/src/cc/arduino/contributions/BuiltInCoreIsNewerCheck.java @@ -92,10 +92,11 @@ public class BuiltInCoreIsNewerCheck implements Runnable { assert base.hasActiveEditor(); int chosenOption = JOptionPane.showConfirmDialog(base.getActiveEditor(), I18n.format(tr("The IDE includes an updated {0} package, but you're using an older one.\nDo you want to upgrade {0}?"), installedBuiltIn.getName()), I18n.format(tr("A newer {0} package is available"), installedBuiltIn.getName()), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); if (chosenOption == JOptionPane.YES_OPTION) { - Action openBoardsManager = base.getOpenBoardsManager(); - Event event = new Event(base.getActiveEditor(), ActionEvent.ACTION_PERFORMED, installedBuiltIn.getName()); - event.getPayload().put("filterText", installedBuiltIn.getName()); - openBoardsManager.actionPerformed(event); + try { + base.openBoardsManager(installedBuiltIn.getName(), ""); + } catch (Exception e) { + e.printStackTrace(); + } } }); } diff --git a/app/src/cc/arduino/contributions/ContributionsSelfCheck.java b/app/src/cc/arduino/contributions/ContributionsSelfCheck.java new file mode 100644 index 000000000..bb5c13d39 --- /dev/null +++ b/app/src/cc/arduino/contributions/ContributionsSelfCheck.java @@ -0,0 +1,83 @@ +package cc.arduino.contributions; + +import cc.arduino.contributions.libraries.LibrariesIndexer; +import cc.arduino.contributions.libraries.LibraryInstaller; +import cc.arduino.contributions.libraries.filters.UpdatableLibraryPredicate; +import cc.arduino.contributions.packages.ContributionInstaller; +import cc.arduino.contributions.packages.ContributionsIndexer; +import cc.arduino.contributions.packages.filters.UpdatablePlatformPredicate; +import cc.arduino.view.NotificationPopup; +import processing.app.Base; +import processing.app.I18n; + +import javax.swing.*; +import javax.swing.event.HyperlinkListener; +import java.util.TimerTask; + +import static processing.app.I18n._; + +public class ContributionsSelfCheck extends TimerTask { + + private final Base base; + private final HyperlinkListener hyperlinkListener; + private final ContributionsIndexer contributionsIndexer; + private final ContributionInstaller contributionInstaller; + private final LibrariesIndexer librariesIndexer; + private final LibraryInstaller libraryInstaller; + + public ContributionsSelfCheck(Base base, HyperlinkListener hyperlinkListener, ContributionsIndexer contributionsIndexer, ContributionInstaller contributionInstaller, LibrariesIndexer librariesIndexer, LibraryInstaller libraryInstaller) { + this.base = base; + this.hyperlinkListener = hyperlinkListener; + this.contributionsIndexer = contributionsIndexer; + this.contributionInstaller = contributionInstaller; + this.librariesIndexer = librariesIndexer; + this.libraryInstaller = libraryInstaller; + } + + @Override + public void run() { + updateContributionIndex(); + updateLibrariesIndex(); + + long updatablePlatforms = contributionsIndexer.getPackages().stream() + .flatMap(pack -> pack.getPlatforms().stream()) + .filter(new UpdatablePlatformPredicate(contributionsIndexer)).count(); + + long updatableLibraries = librariesIndexer.getInstalledLibraries().stream() + .filter(new UpdatableLibraryPredicate(librariesIndexer)) + .count(); + + if (updatableLibraries <= 0 && updatablePlatforms <= 0) { + return; + } + + String text; + if (updatableLibraries > 0 && updatablePlatforms <= 0) { + text = I18n.format(_("Some {0}libraries{1} may be updated"), "", ""); + } else if (updatableLibraries <= 0 && updatablePlatforms > 0) { + text = I18n.format(_("Some {0}boards{1} may be updated"), "", ""); + } else { + text = I18n.format(_("Some {0}boards{1} and some {2}libraries{3} may be updated"), "", "", "", ""); + } + + SwingUtilities.invokeLater(() -> { + new NotificationPopup(base.getActiveEditor(), hyperlinkListener, _("Updates available"), text).setVisible(true); + }); + } + + private void updateLibrariesIndex() { + try { + libraryInstaller.updateIndex(); + } catch (Exception e) { + // ignore + } + } + + private void updateContributionIndex() { + try { + contributionInstaller.updateIndex(); + } catch (Exception e) { + // ignore + } + } +} diff --git a/app/src/cc/arduino/contributions/libraries/ui/LibraryManagerUI.java b/app/src/cc/arduino/contributions/libraries/ui/LibraryManagerUI.java index bcfdba5da..921980310 100644 --- a/app/src/cc/arduino/contributions/libraries/ui/LibraryManagerUI.java +++ b/app/src/cc/arduino/contributions/libraries/ui/LibraryManagerUI.java @@ -125,7 +125,7 @@ public class LibraryManagerUI extends InstallerJDialog { @Override public void updateIndexFilter(String[] filters, Predicate... additionalFilters) { if (additionalFilters.length == 1) { - additionalFilters = new Predicate[] { additionalFilters[0], typeFilter }; + additionalFilters = new Predicate[]{additionalFilters[0], typeFilter}; } super.updateIndexFilter(filters, additionalFilters); } @@ -191,18 +191,14 @@ public class LibraryManagerUI extends InstallerJDialog { }; } - public LibrariesIndexer getIndexer() { - return indexer; + public void selectDropdownItemByClassName(String dropdownItem) { + selectDropdownItemByClassName(typeChooser, dropdownItem); } public void setProgress(Progress progress) { progressBar.setValue(progress); } - /* - * Installer methods follows - */ - private LibraryInstaller installer; private Thread installerThread = null; diff --git a/app/src/cc/arduino/contributions/ui/InstallerJDialog.java b/app/src/cc/arduino/contributions/ui/InstallerJDialog.java index bc69af2c4..255d6f407 100644 --- a/app/src/cc/arduino/contributions/ui/InstallerJDialog.java +++ b/app/src/cc/arduino/contributions/ui/InstallerJDialog.java @@ -276,6 +276,19 @@ public abstract class InstallerJDialog extends JDialog { filterField.setText(filterText); } + public void selectDropdownItemByClassName(String dropdownItem) { + selectDropdownItemByClassName(categoryChooser, dropdownItem); + } + + public void selectDropdownItemByClassName(JComboBox combo, String dropdownItem) { + for (int i = 0; i < combo.getItemCount(); i++) { + if (dropdownItem.equals(combo.getItemAt(i).getClass().getSimpleName())) { + combo.setSelectedIndex(i); + return; + } + } + } + /** * Action performed when the Cancel button is pressed. */ diff --git a/app/src/cc/arduino/view/NotificationPopup.form b/app/src/cc/arduino/view/NotificationPopup.form new file mode 100644 index 000000000..48daea67e --- /dev/null +++ b/app/src/cc/arduino/view/NotificationPopup.form @@ -0,0 +1,123 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/cc/arduino/view/NotificationPopup.java b/app/src/cc/arduino/view/NotificationPopup.java new file mode 100644 index 000000000..e3034dda7 --- /dev/null +++ b/app/src/cc/arduino/view/NotificationPopup.java @@ -0,0 +1,218 @@ +/* + * This file is part of Arduino. + * + * Arduino is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + * + * Copyright 2015 Arduino LLC (http://www.arduino.cc/) + */ + +package cc.arduino.view; + +import cc.arduino.Constants; +import processing.app.Base; +import processing.app.BaseNoGui; + +import javax.swing.*; +import javax.swing.event.HyperlinkEvent; +import javax.swing.event.HyperlinkListener; +import java.awt.*; +import java.awt.event.*; +import java.nio.file.Paths; + +public class NotificationPopup extends JDialog { + + private final ComponentAdapter parentMovedListener; + private final Timer autoCloseAfterTimeout; + + public NotificationPopup(Frame parent, HyperlinkListener hyperlinkListener, String titleText, String message) { + super(parent, false); + initComponents(); + + updateLocation(parent); + parentMovedListener = new ComponentAdapter() { + @Override + public void componentMoved(ComponentEvent e) { + updateLocation(parent); + } + }; + parent.addComponentListener(parentMovedListener); + + title.setText(titleText); + text.setText("" + message.replace("\n", "
") + ""); + + text.addHyperlinkListener(hyperlinkListener); + + addWindowListener(new WindowAdapter() { + @Override + public void windowClosed(WindowEvent e) { + parent.removeComponentListener(parentMovedListener); + } + }); + + autoCloseAfterTimeout = new Timer(Constants.NOTIFICATION_POPUP_AUTOCLOSE_DELAY, (e) -> close()); + autoCloseAfterTimeout.start(); + + text.addHyperlinkListener(e -> { + if (e.getEventType() != HyperlinkEvent.EventType.ACTIVATED) { + return; + } + close(); + }); + + Base.registerWindowCloseKeys(getRootPane(), e -> close()); + + addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + close(); + } + }); + } + + private void updateLocation(Frame parent) { + Point parentLocation = parent.getLocation(); + + int parentX = Double.valueOf(parentLocation.getX()).intValue(); + int parentY = Double.valueOf(parentLocation.getY()).intValue(); + setLocation(parentX + parent.getWidth() - getWidth(), parentY + parent.getHeight() - getHeight()); + } + + private void close() { + if (autoCloseAfterTimeout.isRunning()) { + autoCloseAfterTimeout.stop(); + } + + dispatchEvent(new WindowEvent(NotificationPopup.this, WindowEvent.WINDOW_CLOSING)); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + title = new javax.swing.JLabel(); + javax.swing.JLabel jLabel1 = new javax.swing.JLabel(); + text = new javax.swing.JEditorPane(); + closeButton = new javax.swing.JButton(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + setAlwaysOnTop(true); + setFocusable(false); + setFocusableWindowState(false); + setUndecorated(true); + setResizable(false); + + title.setFont(title.getFont().deriveFont(title.getFont().getStyle() | java.awt.Font.BOLD)); + + jLabel1.setIcon(new ImageIcon(Paths.get(BaseNoGui.getContentFile("lib").getAbsolutePath(), "arduino_small.png").toFile().getAbsolutePath())); + + text.setEditable(false); + text.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0), 0, true)); + text.setContentType("text/html"); // NOI18N + text.setOpaque(false); + + closeButton.setIcon(new ImageIcon(Paths.get(BaseNoGui.getContentFile("lib").getAbsolutePath(), "theme", "close.png").toFile().getAbsolutePath())); + closeButton.setBorder(null); + closeButton.setBorderPainted(false); + closeButton.setHideActionText(true); + closeButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + closeButtonActionPerformed(evt); + } + }); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 48, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(text, javax.swing.GroupLayout.PREFERRED_SIZE, 264, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap()) + .addGroup(layout.createSequentialGroup() + .addComponent(title, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGap(24, 24, 24) + .addComponent(closeButton)))) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(title)) + .addComponent(closeButton)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(text, javax.swing.GroupLayout.PREFERRED_SIZE, 42, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 48, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + + pack(); + }// //GEN-END:initComponents + + private void closeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeButtonActionPerformed + close(); + }//GEN-LAST:event_closeButtonActionPerformed + + /** + * @param args the command line arguments + */ + public static void main(String args[]) { + + /* Create and display the dialog */ + EventQueue.invokeLater(new Runnable() { + public void run() { + NotificationPopup dialog = new NotificationPopup(new JFrame(), System.out::println, "title", "test test test test test test test test test\n" + + " test test test test test test test test test test test"); + dialog.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + dialog.setVisible(true); + } + }); + } + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton closeButton; + private javax.swing.JEditorPane text; + private javax.swing.JLabel title; + // End of variables declaration//GEN-END:variables + +} diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index 6655c94f3..088b14b9e 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -22,10 +22,9 @@ package processing.app; -import cc.arduino.contributions.BuiltInCoreIsNewerCheck; -import cc.arduino.contributions.DownloadableContributionVersionComparator; -import cc.arduino.contributions.GPGDetachedSignatureVerifier; -import cc.arduino.contributions.VersionHelper; +import cc.arduino.Constants; +import cc.arduino.UpdatableBoardsLibsFakeURLsHandler; +import cc.arduino.contributions.*; import cc.arduino.contributions.libraries.*; import cc.arduino.contributions.libraries.ui.LibraryManagerUI; import cc.arduino.contributions.packages.ContributedPlatform; @@ -62,6 +61,7 @@ import java.awt.event.*; import java.io.*; import java.util.*; import java.util.List; +import java.util.Timer; import java.util.function.Predicate; import java.util.logging.Handler; import java.util.logging.Level; @@ -93,6 +93,7 @@ public class Base { public static SplashScreenHelper splashScreenHelper = new SplashScreenHelper(SplashScreen.getSplashScreen()); public static Map FIND_DIALOG_STATE = new HashMap(); + private Timer selfCheckTimer; // set to true after the first time the menu is built. // so that the errors while building don't show up again. @@ -117,7 +118,6 @@ public class Base { // are the same for all windows (since the board and serial port that are // actually used are determined by the preferences, which are shared) private List boardsCustomMenus; - private volatile Action openBoardsManager; private List programmerMenus; private final PdeKeywords pdeKeywords; @@ -481,6 +481,11 @@ public class Base { new Thread(new BuiltInCoreIsNewerCheck(this)).start(); + selfCheckTimer = new Timer(false); + ContributionInstaller contributionInstaller = new ContributionInstaller(BaseNoGui.indexer, BaseNoGui.getPlatform(), new GPGDetachedSignatureVerifier()); + LibraryInstaller libraryInstaller = new LibraryInstaller(BaseNoGui.librariesIndexer, BaseNoGui.getPlatform()); + selfCheckTimer.schedule(new ContributionsSelfCheck(this, new UpdatableBoardsLibsFakeURLsHandler(this), BaseNoGui.indexer, contributionInstaller, BaseNoGui.librariesIndexer, libraryInstaller), Constants.BOARDS_LIBS_UPDATABLE_CHECK_START_PERIOD); + } else if (parser.isNoOpMode()) { // Do nothing (intended for only changing preferences) System.exit(0); @@ -1165,11 +1170,7 @@ public class Base { importMenu.removeAll(); JMenuItem menu = new JMenuItem(tr("Manage Libraries...")); - menu.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - openManageLibrariesDialog(); - } - }); + menu.addActionListener(e -> openLibraryManager("")); importMenu.add(menu); importMenu.addSeparator(); @@ -1257,7 +1258,7 @@ public class Base { } } - private void openManageLibrariesDialog() { + public void openLibraryManager(String dropdownItem) { @SuppressWarnings("serial") LibraryManagerUI managerUI = new LibraryManagerUI(activeEditor, BaseNoGui.getPlatform()) { @Override @@ -1267,6 +1268,9 @@ public class Base { rebuildProgrammerMenu(); onBoardOrPortChange(); setIndexer(BaseNoGui.librariesIndexer); + if (StringUtils.isNotEmpty(dropdownItem)) { + selectDropdownItemByClassName(dropdownItem); + } } }; managerUI.setLocationRelativeTo(activeEditor); @@ -1280,7 +1284,7 @@ public class Base { rebuildExamplesMenu(Editor.examplesMenu); } - private void openInstallBoardDialog(final String filterText) throws Exception { + public void openBoardsManager(final String filterText, String dropdownItem) throws Exception { // Create dialog for contribution manager @SuppressWarnings("serial") ContributionManagerUI managerUI = new ContributionManagerUI(activeEditor, BaseNoGui.getPlatform()) { @@ -1290,10 +1294,12 @@ public class Base { rebuildBoardsMenu(); rebuildProgrammerMenu(); setIndexer(BaseNoGui.indexer); + if (StringUtils.isNotEmpty(dropdownItem)) { + selectDropdownItemByClassName(dropdownItem); + } if (StringUtils.isNotEmpty(filterText)) { setFilterText(filterText); } - } }; managerUI.setLocationRelativeTo(activeEditor); @@ -1316,21 +1322,22 @@ public class Base { boardMenu.putClientProperty("removeOnWindowDeactivation", true); MenuScroller.setScrollerFor(boardMenu); - openBoardsManager = new AbstractAction(tr("Boards Manager...")) { + boardMenu.add(new JMenuItem(new AbstractAction(tr("Boards Manager...")) { public void actionPerformed(ActionEvent actionevent) { String filterText = ""; - if (actionevent instanceof cc.arduino.view.Event) { + String dropdownItem = ""; + if (actionevent instanceof Event) { filterText = ((Event) actionevent).getPayload().get("filterText").toString(); + dropdownItem = ((Event) actionevent).getPayload().get("dropdownItem").toString(); } try { - openInstallBoardDialog(filterText); + openBoardsManager(filterText, dropdownItem); } catch (Exception e) { //TODO show error e.printStackTrace(); } } - }; - boardMenu.add(new JMenuItem(openBoardsManager)); + })); boardsCustomMenus.add(boardMenu); // If there are no platforms installed we are done @@ -2363,11 +2370,7 @@ public class Base { } public List getEditors() { - return new LinkedList(editors); - } - - public Action getOpenBoardsManager() { - return openBoardsManager; + return new LinkedList<>(editors); } public PdeKeywords getPdeKeywords() { @@ -2377,4 +2380,5 @@ public class Base { public List getRecentSketchesMenuItems() { return recentSketchesMenuItems; } + } diff --git a/arduino-core/src/cc/arduino/Constants.java b/arduino-core/src/cc/arduino/Constants.java index 5b0e4436f..48f355736 100644 --- a/arduino-core/src/cc/arduino/Constants.java +++ b/arduino-core/src/cc/arduino/Constants.java @@ -44,6 +44,9 @@ public class Constants { public static final String LIBRARY_DEVELOPMENT_FLAG_FILE = ".development"; + public static final long BOARDS_LIBS_UPDATABLE_CHECK_START_PERIOD = 60000; + public static final int NOTIFICATION_POPUP_AUTOCLOSE_DELAY = 10000; + static { String extenalPackageIndexUrl = System.getProperty("PACKAGE_INDEX_URL"); if (extenalPackageIndexUrl != null && !"".equals(extenalPackageIndexUrl)) { @@ -53,5 +56,4 @@ public class Constants { } } - } diff --git a/build/build.xml b/build/build.xml index b3bc4fd1c..c8ecf2942 100644 --- a/build/build.xml +++ b/build/build.xml @@ -136,6 +136,8 @@ + + diff --git a/build/shared/lib/theme/close.png b/build/shared/lib/theme/close.png new file mode 100644 index 0000000000000000000000000000000000000000..8041c8bded93008efa4c75a7a940e7033e58f010 GIT binary patch literal 375 zcmV--0f_#IP)RohMdIb@JrJLOJN(H^~X0sVc5aSeQ zBPiGd!_1kZKlJ-X`M&SD-&iw0lue4R>$XKvtN{Lk`w8?l&+`>r^K|G`%;5D;rcID< z59#et^DfaS(DZByKzVH2M)NM1z)6yDilRKAQDaTfz%g8w<$ESD8Un^#mu30<0nI?u zC1}3H8hdcI1%q#BVAP8mIHxdn8$l4fp@+4u>ubp5t9x;dzx{lD-{)A@KmO4l!SA^v Vtxt1zu#x}(002ovPDHLkV1ga_t1$oo literal 0 HcmV?d00001