|
1 /* |
|
2 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. |
|
3 * |
|
4 * Redistribution and use in source and binary forms, with or without |
|
5 * modification, are permitted provided that the following conditions |
|
6 * are met: |
|
7 * |
|
8 * - Redistributions of source code must retain the above copyright |
|
9 * notice, this list of conditions and the following disclaimer. |
|
10 * |
|
11 * - Redistributions in binary form must reproduce the above copyright |
|
12 * notice, this list of conditions and the following disclaimer in the |
|
13 * documentation and/or other materials provided with the distribution. |
|
14 * |
|
15 * - Neither the name of Oracle nor the names of its |
|
16 * contributors may be used to endorse or promote products derived |
|
17 * from this software without specific prior written permission. |
|
18 * |
|
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS |
|
20 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
|
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
|
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
|
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
|
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
|
26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
|
27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
|
28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
|
29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
30 */ |
|
31 |
|
32 /* |
|
33 * This source code is provided to illustrate the usage of a given feature |
|
34 * or technique and has been deliberately simplified. Additional steps |
|
35 * required for a production-quality application, such as security checks, |
|
36 * input validation and proper error handling, might not be present in |
|
37 * this sample code. |
|
38 */ |
|
39 |
|
40 |
|
41 |
|
42 import java.awt.*; |
|
43 import java.awt.event.*; |
|
44 import java.applet.*; |
|
45 |
|
46 |
|
47 /** |
|
48 * An interactive test of the Graphics.drawArc and Graphics.fillArc |
|
49 * routines. Can be run either as a standalone application by |
|
50 * typing "java ArcTest" or as an applet in the AppletViewer. |
|
51 */ |
|
52 @SuppressWarnings("serial") |
|
53 public class ArcTest extends Applet { |
|
54 |
|
55 ArcControls controls; // The controls for marking and filling arcs |
|
56 ArcCanvas canvas; // The drawing area to display arcs |
|
57 |
|
58 @Override |
|
59 public void init() { |
|
60 setLayout(new BorderLayout()); |
|
61 canvas = new ArcCanvas(); |
|
62 add("Center", canvas); |
|
63 add("South", controls = new ArcControls(canvas)); |
|
64 } |
|
65 |
|
66 @Override |
|
67 public void destroy() { |
|
68 remove(controls); |
|
69 remove(canvas); |
|
70 } |
|
71 |
|
72 @Override |
|
73 public void start() { |
|
74 controls.setEnabled(true); |
|
75 } |
|
76 |
|
77 @Override |
|
78 public void stop() { |
|
79 controls.setEnabled(false); |
|
80 } |
|
81 |
|
82 @Override |
|
83 public void processEvent(AWTEvent e) { |
|
84 if (e.getID() == Event.WINDOW_DESTROY) { |
|
85 System.exit(0); |
|
86 } |
|
87 } |
|
88 |
|
89 public static void main(String args[]) { |
|
90 Frame f = new Frame("ArcTest"); |
|
91 ArcTest arcTest = new ArcTest(); |
|
92 |
|
93 arcTest.init(); |
|
94 arcTest.start(); |
|
95 |
|
96 f.add("Center", arcTest); |
|
97 f.setSize(300, 300); |
|
98 f.setVisible(true); |
|
99 } |
|
100 |
|
101 @Override |
|
102 public String getAppletInfo() { |
|
103 return "An interactive test of the Graphics.drawArc and \nGraphics." |
|
104 + "fillArc routines. Can be run \neither as a standalone " |
|
105 + "application by typing 'java ArcTest' \nor as an applet in " |
|
106 + "the AppletViewer."; |
|
107 } |
|
108 } |
|
109 |
|
110 |
|
111 @SuppressWarnings("serial") |
|
112 class ArcCanvas extends Canvas { |
|
113 |
|
114 int startAngle = 0; |
|
115 int extent = 45; |
|
116 boolean filled = false; |
|
117 Font font = new java.awt.Font("SansSerif", Font.PLAIN, 12); |
|
118 |
|
119 @Override |
|
120 public void paint(Graphics g) { |
|
121 Rectangle r = getBounds(); |
|
122 int hlines = r.height / 10; |
|
123 int vlines = r.width / 10; |
|
124 |
|
125 g.setColor(Color.pink); |
|
126 for (int i = 1; i <= hlines; i++) { |
|
127 g.drawLine(0, i * 10, r.width, i * 10); |
|
128 } |
|
129 for (int i = 1; i <= vlines; i++) { |
|
130 g.drawLine(i * 10, 0, i * 10, r.height); |
|
131 } |
|
132 |
|
133 g.setColor(Color.red); |
|
134 if (filled) { |
|
135 g.fillArc(0, 0, r.width - 1, r.height - 1, startAngle, extent); |
|
136 } else { |
|
137 g.drawArc(0, 0, r.width - 1, r.height - 1, startAngle, extent); |
|
138 } |
|
139 |
|
140 g.setColor(Color.black); |
|
141 g.setFont(font); |
|
142 g.drawLine(0, r.height / 2, r.width, r.height / 2); |
|
143 g.drawLine(r.width / 2, 0, r.width / 2, r.height); |
|
144 g.drawLine(0, 0, r.width, r.height); |
|
145 g.drawLine(r.width, 0, 0, r.height); |
|
146 int sx = 10; |
|
147 int sy = r.height - 28; |
|
148 g.drawString("Start = " + startAngle, sx, sy); |
|
149 g.drawString("Extent = " + extent, sx, sy + 14); |
|
150 } |
|
151 |
|
152 public void redraw(boolean filled, int start, int extent) { |
|
153 this.filled = filled; |
|
154 this.startAngle = start; |
|
155 this.extent = extent; |
|
156 repaint(); |
|
157 } |
|
158 } |
|
159 |
|
160 |
|
161 @SuppressWarnings("serial") |
|
162 class ArcControls extends Panel |
|
163 implements ActionListener { |
|
164 |
|
165 TextField startTF; |
|
166 TextField extentTF; |
|
167 ArcCanvas canvas; |
|
168 |
|
169 @SuppressWarnings("LeakingThisInConstructor") |
|
170 public ArcControls(ArcCanvas canvas) { |
|
171 Button b = null; |
|
172 |
|
173 this.canvas = canvas; |
|
174 add(startTF = new IntegerTextField("0", 4)); |
|
175 add(extentTF = new IntegerTextField("45", 4)); |
|
176 b = new Button("Fill"); |
|
177 b.addActionListener(this); |
|
178 add(b); |
|
179 b = new Button("Draw"); |
|
180 b.addActionListener(this); |
|
181 add(b); |
|
182 } |
|
183 |
|
184 @Override |
|
185 public void actionPerformed(ActionEvent ev) { |
|
186 String label = ev.getActionCommand(); |
|
187 |
|
188 int start, extent; |
|
189 try { |
|
190 start = Integer.parseInt(startTF.getText().trim()); |
|
191 } catch (NumberFormatException ignored) { |
|
192 start = 0; |
|
193 } |
|
194 try { |
|
195 extent = Integer.parseInt(extentTF.getText().trim()); |
|
196 } catch (NumberFormatException ignored) { |
|
197 extent = 0; |
|
198 } |
|
199 |
|
200 canvas.redraw(label.equals("Fill"), start, extent); |
|
201 } |
|
202 } |
|
203 |
|
204 |
|
205 @SuppressWarnings("serial") |
|
206 class IntegerTextField extends TextField { |
|
207 |
|
208 String oldText = null; |
|
209 |
|
210 public IntegerTextField(String text, int columns) { |
|
211 super(text, columns); |
|
212 enableEvents(AWTEvent.KEY_EVENT_MASK | AWTEvent.TEXT_EVENT_MASK); |
|
213 oldText = getText(); |
|
214 } |
|
215 |
|
216 // Consume non-digit KeyTyped events |
|
217 // Note that processTextEvent kind of eliminates the need for this |
|
218 // function, but this is neater, since ideally, it would prevent |
|
219 // the text from appearing at all. Sigh. See bugid 4100317/4114565. |
|
220 // |
|
221 @Override |
|
222 protected void processEvent(AWTEvent evt) { |
|
223 int id = evt.getID(); |
|
224 if (id != KeyEvent.KEY_TYPED) { |
|
225 super.processEvent(evt); |
|
226 return; |
|
227 } |
|
228 |
|
229 KeyEvent kevt = (KeyEvent) evt; |
|
230 char c = kevt.getKeyChar(); |
|
231 |
|
232 // Digits, backspace, and delete are okay |
|
233 // Note that the minus sign is allowed, but not the decimal |
|
234 if (Character.isDigit(c) || (c == '\b') || (c == '\u007f') || (c |
|
235 == '\u002d')) { |
|
236 super.processEvent(evt); |
|
237 return; |
|
238 } |
|
239 |
|
240 Toolkit.getDefaultToolkit().beep(); |
|
241 kevt.consume(); |
|
242 } |
|
243 |
|
244 // Should consume TextEvents for non-integer Strings |
|
245 // Store away the text in the tf for every TextEvent |
|
246 // so we can revert to it on a TextEvent (paste, or |
|
247 // legal key in the wrong location) with bad text |
|
248 // |
|
249 @Override |
|
250 protected void processTextEvent(TextEvent te) { |
|
251 // The empty string is okay, too |
|
252 String newText = getText(); |
|
253 if (newText.equals("") || textIsInteger(newText)) { |
|
254 oldText = newText; |
|
255 super.processTextEvent(te); |
|
256 return; |
|
257 } |
|
258 |
|
259 Toolkit.getDefaultToolkit().beep(); |
|
260 setText(oldText); |
|
261 } |
|
262 |
|
263 // Returns true for Integers (zero and negative |
|
264 // values are allowed). |
|
265 // Note that the empty string is not allowed. |
|
266 // |
|
267 private boolean textIsInteger(String textToCheck) { |
|
268 |
|
269 try { |
|
270 Integer.parseInt(textToCheck, 10); |
|
271 return true; |
|
272 } catch (NumberFormatException ignored) { |
|
273 return false; |
|
274 } |
|
275 } |
|
276 } |