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
42import java.awt.Color;
43import java.awt.Dimension;
44import java.awt.Graphics;
45import java.awt.event.MouseEvent;
46import 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")
58public 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     */
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     */
111    void pause() {
112        pause(-1, -1);
113    }
114
115    /**
116     * Pause a while, and draw the high water mark.
117     * @see SortAlgorithm
118     */
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     */
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
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
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
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
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
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
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
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     */
285    private synchronized void startSort() {
286        if (kicker == null || !kicker.isAlive()) {
287            kicker = new Thread(this);
288            kicker.start();
289        }
290    }
291
292    @Override
293    public void mouseClicked(MouseEvent e) {
294        showStatus(getParameter("alg"));
295    }
296
297    @Override
298    public void mousePressed(MouseEvent e) {
299    }
300
301    /**
302     * The user clicked in the applet. Start the clock!
303     */
304    @Override
305    public void mouseReleased(MouseEvent e) {
306        startSort();
307        e.consume();
308    }
309
310    @Override
311    public void mouseEntered(MouseEvent e) {
312    }
313
314    @Override
315    public void mouseExited(MouseEvent e) {
316    }
317
318    @Override
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
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