3636import java .awt .Frame ;
3737import java .awt .Image ;
3838import java .awt .Point ;
39- import java .awt .event .ComponentAdapter ;
40- import java .awt .event .ComponentEvent ;
41- import java .awt .event .MouseAdapter ;
42- import java .awt .event .MouseEvent ;
43- import java .awt .event .WindowAdapter ;
44- import java .awt .event .WindowEvent ;
39+ import java .awt .event .*;
4540import java .util .Timer ;
4641import java .util .TimerTask ;
4742
5550import javax .swing .event .HyperlinkListener ;
5651
5752import cc .arduino .Constants ;
53+ import processing .app .PreferencesData ;
5854import processing .app .Theme ;
5955
56+ import java .awt .event .KeyEvent ;
57+
58+ import static processing .app .I18n .tr ;
59+
6060public class NotificationPopup extends JDialog {
61+ public interface OptionalButtonCallbacks {
62+ void onOptionalButton1Callback ();
63+ void onOptionalButton2Callback ();
64+ }
6165
6266 private Timer autoCloseTimer = new Timer (false );
6367 private boolean autoClose = true ;
68+ private OptionalButtonCallbacks optionalButtonCallbacks ;
6469
6570 public NotificationPopup (Frame parent , HyperlinkListener hyperlinkListener ,
6671 String message ) {
67- this (parent , hyperlinkListener , message , true );
72+ this (parent , hyperlinkListener , message , true , null , null , null );
6873 }
6974
7075 public NotificationPopup (Frame parent , HyperlinkListener hyperlinkListener ,
7176 String message , boolean _autoClose ) {
77+ this (parent , hyperlinkListener , message , _autoClose , null , null , null );
78+ }
79+
80+ public NotificationPopup (Frame parent , HyperlinkListener hyperlinkListener ,
81+ String message , boolean _autoClose , OptionalButtonCallbacks listener , String button1Name , String button2Name ) {
7282 super (parent , false );
73- autoClose = _autoClose ;
83+
84+ if (!PreferencesData .getBoolean ("ide.accessible" )) {
85+ // often auto-close is too fast for users of screen readers, so don't allow it.
86+ autoClose = _autoClose ;
87+ }
88+ else {
89+ autoClose = false ;
90+ }
91+ optionalButtonCallbacks = listener ;
92+
7493 setLayout (new FlowLayout ());
7594 setDefaultCloseOperation (WindowConstants .DISPOSE_ON_CLOSE );
7695 setUndecorated (true );
@@ -90,13 +109,89 @@ public NotificationPopup(Frame parent, HyperlinkListener hyperlinkListener,
90109 text .addHyperlinkListener (hyperlinkListener );
91110 add (text );
92111
112+ if (button1Name != null ) {
113+ JButton optionalButton1 = new JButton (tr (button1Name ));
114+ MouseAdapter button1Action = new MouseAdapter () {
115+ @ Override
116+ public void mouseClicked (MouseEvent e ) {
117+ if (optionalButtonCallbacks != null ) {
118+ optionalButtonCallbacks .onOptionalButton1Callback ();
119+ }
120+ }
121+ };
122+ optionalButton1 .addMouseListener (button1Action );
123+
124+ KeyListener button1Key = new KeyListener () {
125+ public void keyTyped (KeyEvent e ) {
126+ }
127+
128+ public void keyPressed (KeyEvent e ) {
129+ }
130+
131+ public void keyReleased (KeyEvent e ) {
132+ int key = e .getKeyCode ();
133+ if ((key == KeyEvent .VK_ENTER ) || (key == KeyEvent .VK_SPACE )) {
134+ optionalButtonCallbacks .onOptionalButton1Callback ();
135+ }
136+ }
137+ };
138+ optionalButton1 .addKeyListener (button1Key );
139+ add (optionalButton1 );
140+ }
141+
142+ if (button2Name != null ) {
143+ JButton optionalButton2 = new JButton (tr (button2Name ));
144+ MouseAdapter button2Action = new MouseAdapter () {
145+ @ Override
146+ public void mouseClicked (MouseEvent e ) {
147+ if (optionalButtonCallbacks != null ) {
148+ optionalButtonCallbacks .onOptionalButton2Callback ();
149+ }
150+ }
151+ };
152+ optionalButton2 .addMouseListener (button2Action );
153+
154+ KeyListener button2Key = new KeyListener () {
155+ public void keyTyped (KeyEvent e ) {
156+ }
157+
158+ public void keyPressed (KeyEvent e ) {
159+ }
160+
161+ public void keyReleased (KeyEvent e ) {
162+ int key = e .getKeyCode ();
163+ if ((key == KeyEvent .VK_ENTER ) || (key == KeyEvent .VK_SPACE )) {
164+ optionalButtonCallbacks .onOptionalButton2Callback ();
165+ }
166+ }
167+ };
168+ optionalButton2 .addKeyListener (button2Key );
169+ add (optionalButton2 );
170+ }
171+
93172 Image close = Theme .getThemeImage ("close" , this , scale (22 ), scale (22 ));
94173 JButton closeButton = new JButton (new ImageIcon (close ));
95174 closeButton .setBorder (null );
96175 closeButton .setBorderPainted (false );
97176 closeButton .setHideActionText (true );
98177 closeButton .setOpaque (false );
99178 closeButton .setBackground (new Color (0 , 0 , 0 , 0 ));
179+ closeButton .getAccessibleContext ().setAccessibleDescription (tr ("Close" ));
180+ KeyListener closeKey = new KeyListener () {
181+ public void keyTyped (KeyEvent e ) {
182+ }
183+
184+ public void keyPressed (KeyEvent e ) {
185+ }
186+
187+ public void keyReleased (KeyEvent e ) {
188+ int key = e .getKeyCode ();
189+ if ((key == KeyEvent .VK_ENTER ) || (key == KeyEvent .VK_SPACE )) {
190+ close ();
191+ }
192+ }
193+ };
194+ closeButton .addKeyListener (closeKey );
100195 add (closeButton );
101196
102197 MouseAdapter closeOnClick = new MouseAdapter () {
@@ -158,5 +253,9 @@ public void run() {
158253 }, Constants .NOTIFICATION_POPUP_AUTOCLOSE_DELAY );
159254 }
160255 setVisible (true );
256+ if (PreferencesData .getBoolean ("ide.accessible" )) {
257+ requestFocus ();
258+ setModal (true );
259+ }
161260 }
162261}
0 commit comments