1+ /* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /*
2+ Part of the Processing project - http://processing.org
3+
4+ Copyright (c) 2015 The Processing Foundation
5+
6+ This program is free software; you can redistribute it and/or
7+ modify it under the terms of the GNU General Public License
8+ version 2, as published by the Free Software Foundation.
9+
10+ This program is distributed in the hope that it will be useful,
11+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+ GNU General Public License for more details.
14+
15+ You should have received a copy of the GNU General Public License
16+ along with this program; if not, write to the Free Software Foundation,
17+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18+ */
19+ package processing .app
20+
21+ import processing .app .ui .Toolkit
22+ import java .awt .EventQueue
23+ import java .awt .Frame
24+ import java .io .PrintWriter
25+ import java .io .StringWriter
26+ import javax .swing .JFrame
27+ import javax .swing .JOptionPane
28+
29+ class Messages {
30+ companion object {
31+ /**
32+ * "No cookie for you" type messages. Nothing fatal or all that
33+ * much of a bummer, but something to notify the user about.
34+ */
35+ @ JvmStatic
36+ fun showMessage (title : String = "Message" , message : String ) {
37+ if (Base .isCommandLine ()) {
38+ println ("$title: $message" )
39+ } else {
40+ JOptionPane .showMessageDialog (
41+ Frame (), message , title ,
42+ JOptionPane .INFORMATION_MESSAGE
43+ )
44+ }
45+ }
46+
47+
48+ /**
49+ * Non-fatal error message with optional stack trace side dish.
50+ */
51+ /**
52+ * Non-fatal error message.
53+ */
54+ @ JvmStatic
55+ @ JvmOverloads
56+ fun showWarning (title : String = "Warning" , message : String , e : Throwable ? = null ) {
57+ if (Base .isCommandLine ()) {
58+ println ("$title: $message" )
59+ } else {
60+ JOptionPane .showMessageDialog (
61+ Frame (), message , title ,
62+ JOptionPane .WARNING_MESSAGE
63+ )
64+ }
65+ e ?.printStackTrace ()
66+ }
67+
68+ /**
69+ * Non-fatal error message with two levels of formatting.
70+ * Unlike the others, this is non-blocking and will run later on the EDT.
71+ */
72+ @ JvmStatic
73+ fun showWarningTiered (
74+ title : String ,
75+ primary : String , secondary : String ,
76+ e : Throwable ?
77+ ) {
78+ if (Base .isCommandLine ()) {
79+ // TODO All these messages need to be handled differently for
80+ // proper parsing on the command line. Many have \n in them.
81+ println ("$title: $primary\n $secondary" )
82+ } else {
83+ EventQueue .invokeLater {
84+ JOptionPane .showMessageDialog (
85+ JFrame (),
86+ Toolkit .formatMessage (primary , secondary ),
87+ title , JOptionPane .WARNING_MESSAGE
88+ )
89+ }
90+ }
91+ e ?.printStackTrace ()
92+ }
93+
94+
95+ /**
96+ * Show an error message that's actually fatal to the program.
97+ * This is an error that can't be recovered. Use showWarning()
98+ * for errors that allow P5 to continue running.
99+ */
100+ @ JvmStatic
101+ fun showError (title : String = "Error" , message : String , e : Throwable ?) {
102+ if (Base .isCommandLine ()) {
103+ System .err .println ("$title: $message" )
104+ } else {
105+ JOptionPane .showMessageDialog (
106+ Frame (), message , title ,
107+ JOptionPane .ERROR_MESSAGE
108+ )
109+ }
110+ e ?.printStackTrace ()
111+ System .exit (1 )
112+ }
113+
114+
115+ /**
116+ * Warning window that includes the stack trace.
117+ */
118+ @ JvmStatic
119+ fun showTrace (
120+ title : String ?,
121+ message : String ,
122+ t : Throwable ?,
123+ fatal : Boolean
124+ ) {
125+ val title = title ? : if (fatal ) "Error" else "Warning"
126+
127+ if (Base .isCommandLine ()) {
128+ System .err .println ("$title: $message" )
129+ t ?.printStackTrace ()
130+ } else {
131+ val sw = StringWriter ()
132+ t !!.printStackTrace (PrintWriter (sw ))
133+
134+ JOptionPane .showMessageDialog (
135+ Frame (), // first <br/> clears to the next line
136+ // second <br/> is a shorter height blank space before the trace
137+ Toolkit .formatMessage ("$message<br/><tt><br/>$sw</tt>" ),
138+ title ,
139+ if (fatal ) JOptionPane .ERROR_MESSAGE else JOptionPane .WARNING_MESSAGE
140+ )
141+
142+ if (fatal ) {
143+ System .exit (1 )
144+ }
145+ }
146+ }
147+
148+ @ JvmStatic
149+ fun showYesNoQuestion (
150+ editor : Frame ?, title : String ?,
151+ primary : String ?, secondary : String ?
152+ ): Int {
153+ if (!Platform .isMacOS ()) {
154+ return JOptionPane .showConfirmDialog (
155+ editor ,
156+ Toolkit .formatMessage (primary , secondary ), //"<html><body>" +
157+ //"<b>" + primary + "</b>" +
158+ //"<br>" + secondary,
159+ title ,
160+ JOptionPane .YES_NO_OPTION ,
161+ JOptionPane .QUESTION_MESSAGE
162+ )
163+ } else {
164+ val result = showCustomQuestion (
165+ editor , title , primary , secondary ,
166+ 0 , "Yes" , "No"
167+ )
168+ return if (result == 0 ) {
169+ JOptionPane .YES_OPTION
170+ } else if (result == 1 ) {
171+ JOptionPane .NO_OPTION
172+ } else {
173+ JOptionPane .CLOSED_OPTION
174+ }
175+ }
176+ }
177+
178+
179+ /**
180+ * @param highlight A valid array index for options[] that specifies the
181+ * default (i.e. safe) choice.
182+ * @return The (zero-based) index of the selected value, -1 otherwise.
183+ */
184+ @ JvmStatic
185+ fun showCustomQuestion (
186+ editor : Frame ?, title : String ?,
187+ primary : String ?, secondary : String ?,
188+ highlight : Int , vararg options : String
189+ ): Int {
190+ val result : Any
191+ if (!Platform .isMacOS ()) {
192+ return JOptionPane .showOptionDialog (
193+ editor ,
194+ Toolkit .formatMessage (primary , secondary ), title ,
195+ JOptionPane .DEFAULT_OPTION , JOptionPane .QUESTION_MESSAGE , null ,
196+ options , options [highlight ]
197+ )
198+ } else {
199+ val pane =
200+ JOptionPane (
201+ Toolkit .formatMessage (primary , secondary ),
202+ JOptionPane .QUESTION_MESSAGE
203+ )
204+
205+ pane .options = options
206+
207+ // highlight the safest option ala apple hig
208+ pane .initialValue = options [highlight ]
209+
210+ val dialog = pane .createDialog (editor , null )
211+ dialog .isVisible = true
212+
213+ result = pane .value
214+ }
215+ for (i in options .indices ) {
216+ if (result != null && result == options [i ]) return i
217+ }
218+ return -1
219+ }
220+
221+
222+ // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
223+ @ JvmStatic
224+ @ Deprecated ("Use log() instead" )
225+ fun log (from : Any , message : String ) {
226+ if (Base .DEBUG ) {
227+ val callingClass = Throwable ()
228+ .stackTrace [2 ]
229+ .className
230+ .formatClassName ()
231+ println ("$callingClass: $message" )
232+ }
233+ }
234+
235+ @ JvmStatic
236+ fun log (message : String ?) {
237+ if (Base .DEBUG ) {
238+ val callingClass = Throwable ()
239+ .stackTrace [2 ]
240+ .className
241+ .formatClassName ()
242+ println ("$callingClass$message" )
243+ }
244+ }
245+
246+ @ JvmStatic
247+ fun logf (message : String ?, vararg args : Any ?) {
248+ if (Base .DEBUG ) {
249+ val callingClass = Throwable ()
250+ .stackTrace [2 ]
251+ .className
252+ .formatClassName ()
253+ System .out .printf ("$callingClass$message" , *args )
254+ }
255+ }
256+
257+ @ JvmStatic
258+ @ JvmOverloads
259+ fun err (message : String ?, e : Throwable ? = null ) {
260+ if (Base .DEBUG ) {
261+ if (message != null ) {
262+ val callingClass = Throwable ()
263+ .stackTrace [4 ]
264+ .className
265+ .formatClassName ()
266+ System .err .println ("$callingClass$message" )
267+ }
268+ e ?.printStackTrace ()
269+ }
270+ }
271+ }
272+ }
273+
274+ // Helper functions to give the base classes a color
275+ fun String .formatClassName () = this
276+ .replace ("processing." , "" )
277+ .replace ("." , "/" )
278+ .padEnd (40 )
279+ .colorizePathParts ()
280+ fun String .colorizePathParts () = split ("/" ).joinToString ("/" ) { part ->
281+ "\u001B [${31 + (part.hashCode() and 0x7).rem(6)}m$part\u001B [0m"
282+ }
0 commit comments