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.Color;
43 import java.awt.Dimension;
44 import java.awt.Graphics;
45 import java.awt.event.MouseEvent;
46 import java.awt.event.MouseListener;
47 
48 
49 /**
50  * A simple applet class to demonstrate a sort algorithm.
51  * You can specify a sorting algorithm using the "alg"
52  * attribute. When you click on the applet, a thread is
53  * forked which animates the sorting algorithm.
54  *
55  * @author James Gosling
56  */
57 @SuppressWarnings("serial")
58 public class SortItem extends java.applet.Applet implements Runnable,
59         MouseListener {
60 
61     /**
62      * The thread that is sorting (or null).
63      */
64     private Thread kicker;
65     /**
66      * The array that is being sorted.
67      */
68     int arr[];
69     /**
70      * The high water mark.
71      */
72     int h1 = -1;
73     /**
74      * The low water mark.
75      */
76     int h2 = -1;
77     /**
78      * The name of the algorithm.
79      */
80     String algName;
81     /**
82      * The sorting algorithm (or null).
83      */
84     SortAlgorithm algorithm;
85     Dimension initialSize = null;
86 
87     /**
88      * Fill the array with random numbers from 0..n-1.
89      */
scramble()90     void scramble() {
91         initialSize = getSize();
92         int a[] = new int[initialSize.height / 2];
93         double f = initialSize.width / (double) a.length;
94 
95         for (int i = a.length; --i >= 0;) {
96             a[i] = (int) (i * f);
97         }
98         for (int i = a.length; --i >= 0;) {
99             int j = (int) (i * Math.random());
100             int t = a[i];
101             a[i] = a[j];
102             a[j] = t;
103         }
104         arr = a;
105     }
106 
107     /**
108      * Pause a while.
109      * @see SortAlgorithm
110      */
pause()111     void pause() {
112         pause(-1, -1);
113     }
114 
115     /**
116      * Pause a while, and draw the high water mark.
117      * @see SortAlgorithm
118      */
pause(int H1)119     void pause(int H1) {
120         pause(H1, -1);
121     }
122 
123     /**
124      * Pause a while, and draw the low&high water marks.
125      * @see SortAlgorithm
126      */
pause(int H1, int H2)127     void pause(int H1, int H2) {
128         h1 = H1;
129         h2 = H2;
130         if (kicker != null) {
131             repaint();
132         }
133         try {
134             Thread.sleep(20);
135         } catch (InterruptedException e) {
136         }
137     }
138 
139     /**
140      * Initialize the applet.
141      */
142     @Override
init()143     public void init() {
144         String at = getParameter("alg");
145         if (at == null) {
146             at = "BubbleSort";
147         }
148 
149         algName = at + "Algorithm";
150         scramble();
151 
152         resize(100, 100);
153         addMouseListener(this);
154     }
155 
156     @Override
start()157     public void start() {
158         h1 = h2 = -1;
159         scramble();
160         repaint();
161         showStatus(getParameter("alg"));
162     }
163 
164     /**
165      * Deallocate resources of applet.
166      */
167     @Override
destroy()168     public void destroy() {
169         removeMouseListener(this);
170     }
171 
172     /**
173      * Paint the array of numbers as a list
174      * of horizontal lines of varying lengths.
175      */
176     @Override
paint(Graphics g)177     public void paint(Graphics g) {
178         int a[] = arr;
179         int y = 0;
180         int deltaY = 0, deltaX = 0, evenY = 0;
181 
182         Dimension currentSize = getSize();
183         int currentHeight = currentSize.height;
184         int currentWidth = currentSize.width;
185 
186         // Check to see if the applet has been resized since it
187         // started running.  If so, need the deltas to make sure
188         // the applet is centered in its containing panel.
189         // The evenX and evenY are because the high and low
190         // watermarks are calculated from the top, but the rest
191         // of the lines are calculated from the bottom, which
192         // can lead to a discrepancy if the window is not an
193         // even size.
194         if (!currentSize.equals(initialSize)) {
195             evenY = (currentHeight - initialSize.height) % 2;
196             deltaY = (currentHeight - initialSize.height) / 2;
197             deltaX = (currentWidth - initialSize.width) / 2;
198 
199             if (deltaY < 0) {
200                 deltaY = 0;
201                 evenY = 0;
202             }
203             if (deltaX < 0) {
204                 deltaX = 0;
205             }
206         }
207 
208         // Erase old lines
209         g.setColor(getBackground());
210         y = currentHeight - deltaY - 1;
211         for (int i = a.length; --i >= 0; y -= 2) {
212             g.drawLine(deltaX + arr[i], y, currentWidth, y);
213         }
214 
215         // Draw new lines
216         g.setColor(Color.black);
217         y = currentHeight - deltaY - 1;
218         for (int i = a.length; --i >= 0; y -= 2) {
219             g.drawLine(deltaX, y, deltaX + arr[i], y);
220         }
221 
222         if (h1 >= 0) {
223             g.setColor(Color.red);
224             y = deltaY + evenY + h1 * 2 + 1;
225             g.drawLine(deltaX, y, deltaX + initialSize.width, y);
226         }
227         if (h2 >= 0) {
228             g.setColor(Color.blue);
229             y = deltaY + evenY + h2 * 2 + 1;
230             g.drawLine(deltaX, y, deltaX + initialSize.width, y);
231         }
232     }
233 
234     /**
235      * Update without erasing the background.
236      */
237     @Override
update(Graphics g)238     public void update(Graphics g) {
239         paint(g);
240     }
241 
242     /**
243      * Run the sorting algorithm. This method is
244      * called by class Thread once the sorting algorithm
245      * is started.
246      * @see java.lang.Thread#run
247      * @see SortItem#mouseUp
248      */
249     @Override
run()250     public void run() {
251         try {
252             if (algorithm == null) {
253                 algorithm = (SortAlgorithm) Class.forName(algName).newInstance();
254                 algorithm.setParent(this);
255             }
256             algorithm.init();
257             algorithm.sort(arr);
258         } catch (Exception e) {
259         }
260     }
261 
262     /**
263      * Stop the applet. Kill any sorting algorithm that
264      * is still sorting.
265      */
266     @Override
stop()267     public synchronized void stop() {
268         if (algorithm != null) {
269             try {
270                 algorithm.stop();
271             } catch (IllegalThreadStateException e) {
272                 // ignore this exception
273             }
274             kicker = null;
275         }
276     }
277 
278     /**
279      * For a Thread to actually do the sorting. This routine makes
280      * sure we do not simultaneously start several sorts if the user
281      * repeatedly clicks on the sort item.  It needs to be
282      * synchronized with the stop() method because they both
283      * manipulate the common kicker variable.
284      */
startSort()285     private synchronized void startSort() {
286         if (kicker == null || !kicker.isAlive()) {
287             kicker = new Thread(this);
288             kicker.start();
289         }
290     }
291 
292     @Override
mouseClicked(MouseEvent e)293     public void mouseClicked(MouseEvent e) {
294         showStatus(getParameter("alg"));
295     }
296 
297     @Override
mousePressed(MouseEvent e)298     public void mousePressed(MouseEvent e) {
299     }
300 
301     /**
302      * The user clicked in the applet. Start the clock!
303      */
304     @Override
mouseReleased(MouseEvent e)305     public void mouseReleased(MouseEvent e) {
306         startSort();
307         e.consume();
308     }
309 
310     @Override
mouseEntered(MouseEvent e)311     public void mouseEntered(MouseEvent e) {
312     }
313 
314     @Override
mouseExited(MouseEvent e)315     public void mouseExited(MouseEvent e) {
316     }
317 
318     @Override
getAppletInfo()319     public String getAppletInfo() {
320         return "Title: SortDemo \nAuthor: James Gosling 1.17f, 10 Apr 1995 \nA simple applet class to demonstrate a sort algorithm.  \nYou can specify a sorting algorithm using the 'alg' attribute.  \nWhen you click on the applet, a thread is forked which animates \nthe sorting algorithm.";
321     }
322 
323     @Override
getParameterInfo()324     public String[][] getParameterInfo() {
325         String[][] info = {
326             { "alg", "string",
327                 "The name of the algorithm to run.  You can choose from the provided algorithms or suppply your own, as long as the classes are runnable as threads and their names end in 'Algorithm.'  BubbleSort is the default.  Example:  Use 'QSort' to run the QSortAlgorithm class." }
328         };
329         return info;
330     }
331 }
332