Skip to content

Commit a43757d

Browse files
author
Federico Fissore
committed
Update notification: UX feedback
1 parent 0bb7fd7 commit a43757d

File tree

3 files changed

+56
-127
lines changed

3 files changed

+56
-127
lines changed

app/src/cc/arduino/contributions/ContributionsSelfCheck.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -59,19 +59,19 @@ public void run() {
5959

6060
String text;
6161
if (updatableLibraries > 0 && updatablePlatforms <= 0) {
62-
text = I18n.format(_("Some {0}libraries{1} may be updated"), "<a href=\"http://librarymanager\">", "</a>");
62+
text = I18n.format(_("<br/>Update available for some of your {0}libraries{1}"), "<a href=\"http://librarymanager\">", "</a>");
6363
} else if (updatableLibraries <= 0 && updatablePlatforms > 0) {
64-
text = I18n.format(_("Some {0}boards{1} may be updated"), "<a href=\"http://boardsmanager\">", "</a>");
64+
text = I18n.format(_("<br/>Update available for some of your {0}boards{1}"), "<a href=\"http://boardsmanager\">", "</a>");
6565
} else {
66-
text = I18n.format(_("Some {0}boards{1} and some {2}libraries{3} may be updated"), "<a href=\"http://boardsmanager\">", "</a>", "<a href=\"http://librarymanager\">", "</a>");
66+
text = I18n.format(_("<br/>Update available for some of your {0}boards{1} and {2}libraries{3}"), "<a href=\"http://boardsmanager\">", "</a>", "<a href=\"http://librarymanager\">", "</a>");
6767
}
6868

6969
if (cancelled) {
7070
return;
7171
}
7272

7373
SwingUtilities.invokeLater(() -> {
74-
notificationPopup = new NotificationPopup(base.getActiveEditor(), hyperlinkListener, _("Updates available"), text);
74+
notificationPopup = new NotificationPopup(base.getActiveEditor(), hyperlinkListener, text);
7575
notificationPopup.setVisible(true);
7676
});
7777
}

app/src/cc/arduino/view/NotificationPopup.form

+25-59
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,13 @@
77
<Property name="focusable" type="boolean" value="false"/>
88
<Property name="focusableWindowState" type="boolean" value="false"/>
99
<Property name="undecorated" type="boolean" value="true"/>
10+
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
11+
<Dimension value="[350, 70]"/>
12+
</Property>
1013
<Property name="resizable" type="boolean" value="false"/>
14+
<Property name="size" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
15+
<Dimension value="[350, 70]"/>
16+
</Property>
1117
</Properties>
1218
<SyntheticProperties>
1319
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
@@ -23,74 +29,24 @@
2329
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
2430
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
2531
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
32+
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,0,0,0,2,14"/>
2633
</AuxValues>
2734

28-
<Layout>
29-
<DimensionLayout dim="0">
30-
<Group type="103" groupAlignment="0" attributes="0">
31-
<Group type="102" attributes="0">
32-
<EmptySpace max="-2" attributes="0"/>
33-
<Component id="jLabel1" min="-2" pref="48" max="-2" attributes="0"/>
34-
<EmptySpace max="-2" attributes="0"/>
35-
<Group type="103" groupAlignment="0" attributes="0">
36-
<Group type="102" attributes="0">
37-
<Component id="text" min="-2" pref="264" max="-2" attributes="0"/>
38-
<EmptySpace max="32767" attributes="0"/>
39-
</Group>
40-
<Group type="102" alignment="0" attributes="0">
41-
<Component id="title" max="32767" attributes="0"/>
42-
<EmptySpace min="-2" pref="24" max="-2" attributes="0"/>
43-
<Component id="closeButton" min="-2" max="-2" attributes="0"/>
44-
</Group>
45-
</Group>
46-
</Group>
47-
</Group>
48-
</DimensionLayout>
49-
<DimensionLayout dim="1">
50-
<Group type="103" groupAlignment="0" attributes="0">
51-
<Group type="102" attributes="0">
52-
<Group type="103" groupAlignment="0" attributes="0">
53-
<Group type="102" attributes="0">
54-
<Group type="103" groupAlignment="0" attributes="0">
55-
<Group type="102" attributes="0">
56-
<EmptySpace max="-2" attributes="0"/>
57-
<Component id="title" min="-2" max="-2" attributes="0"/>
58-
</Group>
59-
<Component id="closeButton" alignment="0" min="-2" max="-2" attributes="0"/>
60-
</Group>
61-
<EmptySpace max="-2" attributes="0"/>
62-
<Component id="text" min="-2" pref="42" max="-2" attributes="0"/>
63-
</Group>
64-
<Group type="102" alignment="0" attributes="0">
65-
<EmptySpace max="-2" attributes="0"/>
66-
<Component id="jLabel1" min="-2" pref="48" max="-2" attributes="0"/>
67-
</Group>
68-
</Group>
69-
<EmptySpace max="32767" attributes="0"/>
70-
</Group>
71-
</Group>
72-
</DimensionLayout>
35+
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout">
36+
<Property name="useNullLayout" type="boolean" value="true"/>
7337
</Layout>
7438
<SubComponents>
75-
<Component class="javax.swing.JLabel" name="title">
76-
<Properties>
77-
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
78-
<FontInfo relative="true">
79-
<Font bold="true" component="title" property="font" relativeSize="true" size="0"/>
80-
</FontInfo>
81-
</Property>
82-
</Properties>
83-
</Component>
84-
<Component class="javax.swing.JLabel" name="jLabel1">
39+
<Component class="javax.swing.JLabel" name="icon">
8540
<Properties>
8641
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
8742
<Connection code="new ImageIcon(Paths.get(BaseNoGui.getContentFile(&quot;lib&quot;).getAbsolutePath(), &quot;arduino_small.png&quot;).toFile().getAbsolutePath())" type="code"/>
8843
</Property>
8944
</Properties>
90-
<AuxValues>
91-
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
92-
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
93-
</AuxValues>
45+
<Constraints>
46+
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
47+
<AbsoluteConstraints x="10" y="10" width="50" height="50"/>
48+
</Constraint>
49+
</Constraints>
9450
</Component>
9551
<Component class="javax.swing.JEditorPane" name="text">
9652
<Properties>
@@ -103,6 +59,11 @@
10359
<Property name="contentType" type="java.lang.String" value="text/html" noResource="true"/>
10460
<Property name="opaque" type="boolean" value="false"/>
10561
</Properties>
62+
<Constraints>
63+
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
64+
<AbsoluteConstraints x="70" y="10" width="270" height="50"/>
65+
</Constraint>
66+
</Constraints>
10667
</Component>
10768
<Component class="javax.swing.JButton" name="closeButton">
10869
<Properties>
@@ -118,6 +79,11 @@
11879
<Events>
11980
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="closeButtonActionPerformed"/>
12081
</Events>
82+
<Constraints>
83+
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
84+
<AbsoluteConstraints x="328" y="0" width="22" height="22"/>
85+
</Constraint>
86+
</Constraints>
12187
</Component>
12288
</SubComponents>
12389
</Form>

app/src/cc/arduino/view/NotificationPopup.java

+27-64
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929

3030
package cc.arduino.view;
3131

32-
import cc.arduino.Constants;
3332
import processing.app.Base;
3433
import processing.app.BaseNoGui;
3534

@@ -43,9 +42,8 @@
4342
public class NotificationPopup extends JDialog {
4443

4544
private final ComponentAdapter parentMovedListener;
46-
private final Timer autoCloseAfterTimeout;
4745

48-
public NotificationPopup(Frame parent, HyperlinkListener hyperlinkListener, String titleText, String message) {
46+
public NotificationPopup(Frame parent, HyperlinkListener hyperlinkListener, String message) {
4947
super(parent, false);
5048
initComponents();
5149

@@ -58,10 +56,15 @@ public void componentMoved(ComponentEvent e) {
5856
};
5957
parent.addComponentListener(parentMovedListener);
6058

61-
title.setText(titleText);
62-
text.setText("<html><body style=\"font-family:sans-serif;font-size:12pt\">" + message.replace("\n", "<br/>") + "</body></html>");
59+
text.setText("<html><body style=\"font-family:sans-serif;font-size:12pt\">" + message + "</body></html>");
6360

6461
text.addHyperlinkListener(hyperlinkListener);
62+
text.addHyperlinkListener(e -> {
63+
if (e.getEventType() != HyperlinkEvent.EventType.ACTIVATED) {
64+
return;
65+
}
66+
close();
67+
});
6568

6669
addWindowListener(new WindowAdapter() {
6770
@Override
@@ -70,39 +73,28 @@ public void windowClosed(WindowEvent e) {
7073
}
7174
});
7275

73-
autoCloseAfterTimeout = new Timer(Constants.NOTIFICATION_POPUP_AUTOCLOSE_DELAY, (e) -> close());
74-
autoCloseAfterTimeout.start();
75-
76-
text.addHyperlinkListener(e -> {
77-
if (e.getEventType() != HyperlinkEvent.EventType.ACTIVATED) {
78-
return;
79-
}
80-
close();
81-
});
82-
8376
Base.registerWindowCloseKeys(getRootPane(), e -> close());
8477

85-
addMouseListener(new MouseAdapter() {
78+
MouseAdapter closeOnClick = new MouseAdapter() {
8679
@Override
8780
public void mouseClicked(MouseEvent e) {
8881
close();
8982
}
90-
});
83+
};
84+
addMouseListener(closeOnClick);
85+
text.addMouseListener(closeOnClick);
86+
icon.addMouseListener(closeOnClick);
9187
}
9288

9389
private void updateLocation(Frame parent) {
9490
Point parentLocation = parent.getLocation();
9591

9692
int parentX = Double.valueOf(parentLocation.getX()).intValue();
9793
int parentY = Double.valueOf(parentLocation.getY()).intValue();
98-
setLocation(parentX + parent.getWidth() - getWidth(), parentY + parent.getHeight() - getHeight());
94+
setLocation(parentX, parentY + parent.getHeight() - getHeight());
9995
}
10096

10197
public void close() {
102-
if (autoCloseAfterTimeout.isRunning()) {
103-
autoCloseAfterTimeout.stop();
104-
}
105-
10698
dispatchEvent(new WindowEvent(NotificationPopup.this, WindowEvent.WINDOW_CLOSING));
10799
}
108100

@@ -115,8 +107,7 @@ public void close() {
115107
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
116108
private void initComponents() {
117109

118-
title = new javax.swing.JLabel();
119-
javax.swing.JLabel jLabel1 = new javax.swing.JLabel();
110+
icon = new javax.swing.JLabel();
120111
text = new javax.swing.JEditorPane();
121112
closeButton = new javax.swing.JButton();
122113

@@ -125,16 +116,21 @@ private void initComponents() {
125116
setFocusable(false);
126117
setFocusableWindowState(false);
127118
setUndecorated(true);
119+
setPreferredSize(new java.awt.Dimension(350, 70));
128120
setResizable(false);
121+
setSize(new java.awt.Dimension(350, 70));
122+
getContentPane().setLayout(null);
129123

130-
title.setFont(title.getFont().deriveFont(title.getFont().getStyle() | java.awt.Font.BOLD));
131-
132-
jLabel1.setIcon(new ImageIcon(Paths.get(BaseNoGui.getContentFile("lib").getAbsolutePath(), "arduino_small.png").toFile().getAbsolutePath()));
124+
icon.setIcon(new ImageIcon(Paths.get(BaseNoGui.getContentFile("lib").getAbsolutePath(), "arduino_small.png").toFile().getAbsolutePath()));
125+
getContentPane().add(icon);
126+
icon.setBounds(10, 10, 50, 50);
133127

134128
text.setEditable(false);
135129
text.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0), 0, true));
136130
text.setContentType("text/html"); // NOI18N
137131
text.setOpaque(false);
132+
getContentPane().add(text);
133+
text.setBounds(70, 10, 270, 50);
138134

139135
closeButton.setIcon(new ImageIcon(Paths.get(BaseNoGui.getContentFile("lib").getAbsolutePath(), "theme", "close.png").toFile().getAbsolutePath()));
140136
closeButton.setBorder(null);
@@ -145,41 +141,8 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
145141
closeButtonActionPerformed(evt);
146142
}
147143
});
148-
149-
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
150-
getContentPane().setLayout(layout);
151-
layout.setHorizontalGroup(
152-
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
153-
.addGroup(layout.createSequentialGroup()
154-
.addContainerGap()
155-
.addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 48, javax.swing.GroupLayout.PREFERRED_SIZE)
156-
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
157-
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
158-
.addGroup(layout.createSequentialGroup()
159-
.addComponent(text, javax.swing.GroupLayout.PREFERRED_SIZE, 264, javax.swing.GroupLayout.PREFERRED_SIZE)
160-
.addContainerGap())
161-
.addGroup(layout.createSequentialGroup()
162-
.addComponent(title, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
163-
.addGap(24, 24, 24)
164-
.addComponent(closeButton))))
165-
);
166-
layout.setVerticalGroup(
167-
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
168-
.addGroup(layout.createSequentialGroup()
169-
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
170-
.addGroup(layout.createSequentialGroup()
171-
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
172-
.addGroup(layout.createSequentialGroup()
173-
.addContainerGap()
174-
.addComponent(title))
175-
.addComponent(closeButton))
176-
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
177-
.addComponent(text, javax.swing.GroupLayout.PREFERRED_SIZE, 42, javax.swing.GroupLayout.PREFERRED_SIZE))
178-
.addGroup(layout.createSequentialGroup()
179-
.addContainerGap()
180-
.addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 48, javax.swing.GroupLayout.PREFERRED_SIZE)))
181-
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
182-
);
144+
getContentPane().add(closeButton);
145+
closeButton.setBounds(328, 0, 22, 22);
183146

184147
pack();
185148
}// </editor-fold>//GEN-END:initComponents
@@ -196,7 +159,7 @@ public static void main(String args[]) {
196159
/* Create and display the dialog */
197160
EventQueue.invokeLater(new Runnable() {
198161
public void run() {
199-
NotificationPopup dialog = new NotificationPopup(new JFrame(), System.out::println, "title", "<a href='arduinoide://boardsmanager'>test</a> test test test test test test test test\n" +
162+
NotificationPopup dialog = new NotificationPopup(new JFrame(), System.out::println, "<a href='arduinoide://boardsmanager'>test</a> test test test test test test test test\n" +
200163
" test test test test test test test test test test test");
201164
dialog.addWindowListener(new WindowAdapter() {
202165
@Override
@@ -211,8 +174,8 @@ public void windowClosing(WindowEvent e) {
211174

212175
// Variables declaration - do not modify//GEN-BEGIN:variables
213176
private javax.swing.JButton closeButton;
177+
private javax.swing.JLabel icon;
214178
private javax.swing.JEditorPane text;
215-
private javax.swing.JLabel title;
216179
// End of variables declaration//GEN-END:variables
217180

218181
}

0 commit comments

Comments
 (0)