PortYourJavaApplets

By John Kostaras


There is a large number of Java applets (i.e. AWT) out there (the Internet) that they don't work! I don't mean that they don't work because they 're buggy, but due to the security restrictions of modern browsers that don't allow their execution. There are many Java applets for training, e.g. to demonstrate physics, or maths or chemistry etc. You may find instructions on how to enable the Java plugin in various browsers here. However, no matter what you do you will eventually get an error similar to the following:

File:AppletBlocked.png

This article provides some solutions on what you can do to revive your applets.

Contents

Introduction

One of the most common interview questions in the first years of Java was: "What is the difference between a Java application and a Java applet?" Apart from the obvious answer that the applet could only run in a browser, I would expect to hear that a Java applet does not have a main() method, but an init() method instead. The skeleton of a Java applet is:

public class MyApplet extends java.applet.Applet {
 
  public void init() { ... }
 
  public void start() { ... }
 
  public void paint (java.awt.Graphics g) { ... }
 
  public void stop() { ... } 		
 
  public void destroy() { ... }
}

You can also have other methods to handle mouse or keyboard events but the above is what you usually need. The above methods show the lifecycle of a Java applet. Any initialisation code goes to init(), then the start() method is executed everytime the browser gets the focus, with stop() and destroy() being the opposite of start() and init() respectively. The rendering of the applet is done in the paint() method which requires a Graphics instance.

The applet is called by the html file like so:

<APPLET code="MyApplet.class" width=600 height=600 ></APPLET>

As already mentioned, if you try to execute a Java applet in a modern browser, you get a security exception message.

What can you do? You need to migrate/port your Java applet to something else. There are a number of solutions:

  • convert it to JavaFX
  • convert it to DukeScript
  • convert it directly to Javascript (HTML 5)

They all require that you re-write part of your applet to the new API; there is no one-click migration solution. What you choose is a matter of preference. But let's go down the road to see what caveats/advantages each of these new technologies has to offer.

If you want to follow the examples of this tutorial you need to install:

  • JDK 8 or later (for JavaFX 8)
  • NetBeans 8.0 or later
  • DukeScript plugin 1.2 or later (see relevant section below)

Java Applet

As an example, I will use the following Java applet, ported from C++ (see [1]). You don't need to understand what it is doing, but an explanation is given in the appendix. It draws a nice fractal as shown in the following figure:

File:TendrilsApplet.png

Let's introduce the Tendrils applet step by step:

public class Tendrils extends java.applet.Applet {
    private static final int X = 300;
    private static final int Y = 300;
    private static final int SEGS = 60;		// max number of segments
    private Cluster cluster;
 
    public void init() {
        setSize(600, 600);
        cluster = new Cluster();
    }
 
    public void start() {
    }
 
    public void paint(Graphics g) {
        cluster.display(g, SEGS, X, Y);
    }
 
    public void stop() {
    }
 
    public void dispose() {
    }
...
}

paint() calls the display() method of the Cluster class:

   private class Cluster {
 
        private static final int NUMBER = 7;	// Number of helixes in a cluster
 
        public void display(Graphics g, int size, int x, int y) {
            for (int i = 0; i < NUMBER; i++) {
                double theta = i * 2 * Math.PI / NUMBER;
                Tendril t = new Tendril();
                t.display(g, size, theta, x, y);
            }
        }
    }

which initialises a Tendril class and calls its display() method:

    private class Tendril {
        private static final int NUME = 30;		// Numerator of probability
        private static final int DENOM = 100;           // Denominator of probability
        private static final double RAD = 3.0;          // length of line segments
        private static final double DELTHETA = 0.1;	// change in angle theta (in rad)
        private static final int REDUX = 3;		// division of number of helixes
        private static final int MIN = 1;		// min number of segments
 
        public void display(Graphics g, int size, double theta, int x, int y) {
            for (int j = 0; j < size; j++) {
                // System.out.println("Rand: " + (int)(Math.random()*DENOM));
                int chng = ((int) (DENOM * Math.random()) < NUME) ? -1 : 1;
                theta += chng * DELTHETA;
                int x0 = x;
                int y0 = y;
                x += RAD * Math.sin(theta);
                y += RAD * Math.cos(theta);
                if (size < 4) {
                    g.setColor(Color.red);
                } else if (size < 13) {
                    g.setColor(Color.green);
                } else if (size < 40) {
                    g.setColor(Color.cyan);
                } else {
                    g.setColor(Color.yellow);
                }
                g.drawLine(x0, y0, x, y);
            }
            if (size > MIN) {
                Cluster c = new Cluster();
                int newsize = size / REDUX;
                c.display(g, newsize, x, y);
            }
        }
    }

As I mentioned, the details are not important; they are explained in the Appendix for those who cannot sleep at night without understanding how the code works.

You can execute the applet from inside NetBeans by right-clicking on Tendrils class and selecting Run File from the popup menu. However, if you try to run it from the Tendrils.html file, then the security exception message reminds you of the reality.

In the following I will show you how to convert this simple applet to some other technology in order to be able to run it in a browser again.

Convert to JavaFX

Swing replaced AWT (which Java Applets use to draw their graphical part with) and JavaFX is the replacement of Swing. While your Java Applet cannot run in modern browsers, a JavaFX applet has many chances to be able to.

Here are some pros & cons of this new technology:

  • + Write in Java
  • + A lot of documentation
  • + Rich UI widgets
  • - Difficult to deploy
  • - Cannot run in all browsers
  • - Need to learn a new API if you are not familiar with JavaFX before, but part of Java

I won't go into the details of how to install JavaFX here; I assume that you have JavaFX8 which comes by default with JDK 8.

  1. Create a new Project (File -> New Project) and choose JavaFX under Categories and JavaFX Application under Projects. Click Next.

File:FX_Fig_1.png

Enter a project name and location and click on Finish.

File:FX_Fig_2.png

NetBeans has created a simple JavaFX application without the use of a FXML. We will modify start() method like so:

public class TendrilsFX extends Application {
    private static final int SEGS = 60;	// max number of segments
    private static final int X = 600;
    private static final int Y = 600;
    private final Cluster cluster = new Cluster();
 
    @Override
    public void start(Stage primaryStage) {
        Canvas canvas = new Canvas(X, Y);
        GraphicsContext g2D = canvas.getGraphicsContext2D();
        cluster.display(g2D, SEGS, X/2, Y/2);
 
        StackPane root = new StackPane();
        root.getChildren().add(canvas);
 
        Scene scene = new Scene(root, X, Y);
 
        primaryStage.setTitle("Tendrils!");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

We draw on a Canvas from which we ask for a GraphicsContext which is the equivalent to java.awt.Graphics. After we call Cluster's display() method, we add the canvas to a Scene and then to the Stage.

Copy Tendril and Cluster classes to TendrilsFX and make sure you modify their display() methods to use GraphicsContext.

A few more errors are remaining which are resolved if you rename g.setColor() and g.drawLine() to their JFX counterparts:

      if (size < 4) {
          g.setStroke(javafx.scene.paint.Color.RED);
      } else if (size < 13) {
          g.setStroke(javafx.scene.paint.Color.GREEN);
      } else if (size < 40) {
          g.setStroke(javafx.scene.paint.Color.CYAN);
      } else {
         g.setStroke(javafx.scene.paint.Color.YELLOW);
      }
      g.strokeLine(x0, y0, x, y);

Run TendrilsFX and you will see a nice picture like the following:

File:FX_Fig_3.png

Deploy

To be able to execute it outside the IDE you need to modify the security of your Java Control Panel according the following steps:

File:FX_Fig_4.png

  1. Open the Java Control Panel (on Windows open Control Panel and search for Java, on Mac it should be in the System Preferences window) and select the Security tab (see previous figure)
  2. Click on Edit Site List and add the URL that contains the TendrilsFX.html file, e.g.
    file:///Users/
  3. Right-click on the TendrilsFX project in NetBeans and select Properties -> Run and under the section Run select In Browser and enter the Width and Height to be the same as in the code, i.e. 600 and 600 (see following figure)
  4. Clean and build the project. The result is under folder dist:

  • web-files/
  • TendrilsFX.html
  • TendrilsFX.jar
  • TendrilsFX.jnlp

File:FX_Fig_5.png

Open TendrilsFX.html on your browser, accept any warnings, in order to see the Tendrils JavaFX8 applet. However, this depends on your browser:

  • Firefox: you need to enable the Java Applet plugin if it is not enabled and accepting the warning you should be able to view your TendrilsFX applet
  • Safari doesn’t allow to execute an applet from the filesystem, i.e. with URL
    file:///
    . You need to deploy your JFX applet to a web server, e.g. Apache and in Java Control Panel to allow e.g.
    http://localhost
  • Opera & Chrome do not allow execution of JavaFX applets
Content can not be displayed using your Web browser. Please open this page using another browser.
  • Internet Explorer (?)

Please note that Internet Explorer 10, Safari, Chrome and Opera don't permit execution of plugins using the NPAPI currently used by the Java browser plugin.

Convert to DukeScript

DukeScript is a new technology that allows you to write your logic in Java and render the result to a number of clients, which can be web browser, portable devices etc. It achieves this by transforming Java code to HTML 5 (Javascript) which can run in any device.

Some pros & cons of this technology are:

  • + Write in Java
  • + Write once run everywhere (web, JavaFX, Android, iOS, etc.)
  • - Not a lot of documentation available
  • - Need to learn a new API which is however similar to JavaFX

Let's see how to convert our Java applet to DukeScript.

  1. Before you start you need to install the DukeScript plugin. Go to Tools -> Plugins -> Available Plugins and select DukeScript Project Wizard and (optionally) Mine Sweeper (an application written in DukeScript). Click on the Install button to install them. (Restart of the IDE maybe needed).
  2. Create a new Project (File -> New Project) and choose HTML 5 under Categories and HTML 5 with Java Application Logic under Projects. Click Next.

File:DS_Fig_1.png‎

As DukeScript is mavenized, provide a project name (artifact id) and a base package (group id) and click Next:

File:DS_Fig_2.png‎

In the next step of the wizard you choose on which platforms you want to deploy your application. If you have the Android SDK for example, then you can choose Run on Android devices. For our example I only choose:

File:DS_Fig_3.png‎

For the last step I chose the simplest case, i.e. Knockout, as shown in the following figure:

File:DS_Fig_4.png‎

Click on Finish.

NetBeans created a new maven project which contains a number of modules, depending on your choice of platforms in step 3 of the wizard, as shown below.

File:DS_Fig_5.png‎

Right click on it and choose Build with Dependencies. Once finished, double click on tendrils Client for JavaFX to open it, and then right click on the opened project (not the one inside Modules) and run it. You should see the default JavaFX demo:

File:DS_Fig_6.png‎

Do the same for tendrils Client for Web. When you run it, a web server is executed and the result is displayed in a browser:

File:DS_Fig_7.png‎

Let's now see how can we port our Tendrils Java Applet to DukeScript.

Let's start with tendrils Client for JavaFX. Opening the Source Packages you will see two classes:

  • DataModel
  • Main

Delete DataModel and any test classes and cleanup the body of the static onPageLoad() method of Main. Finally, open the index.html (under Web Pages -> pages) and clean it up so that it looks like:

<!DOCTYPE html>
<html>
    <head>
        <title></title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body>
        <h1>Words Demo</h1>
        <!-- boot bck2brwsr -->
        <script type="text/javascript" src="bck2brwsr.js"></script>
        <script>
            var vm = bck2brwsr('tendrils.js');
            var c = vm.loadClass('tendrils.tendrils.BrowserMain');
            c.invoke('main');
        </script>
    </body>
</html>

Now you can start changing it!

Copy the Tendril and Cluster inner classes from the original Java applet to Main. Do not add the recommended imports. We will fix them later.

Copy the contents of paint() to onPageLoad() and any constant fields, too.

The first modification we need to do is to convert java.awt.Graphics to its DukeScript equivalent com.dukescript.api.canvas.GraphicsContext2D:

    public static void onPageLoad() throws Exception {
        GraphicsContext2D g = HTML5Graphics.getOrCreate("tendrils");
        cluster.display(g, SEGS, X/2, Y/2);
    }

In order to locate GraphicsContext2D and HTML5Graphics, click on the little lightbulb on the left and select Search Dependency at Maven Repositories. Then import the dependencies for these two classes. Update the signatures of the display() methods accordingly.

Next, you cannot call non-static content from a static method; onPageLoad() has to be static, so one way, if it doesn't harm your logic, is to make Tendril and Cluster inner classes static, too. Fix also the fields of Main to be static:

    private static final int X = 300;
    private static final int Y = 300;
    private static final int SEGS = 60;		// max number of segments
    private static final Cluster cluster = new Cluster();

Now, most errors should have gone away apart from references to java.awt.Color and g.drawLine(x0, y0, x, y) all inside Tendril's display() method. g.setColor() needs to be transformed to g.setStrokeStyle (unfortunately, no Color constants are defined so you need to pass their RGB value), while g.drawLine(x0, y0, x, y) is a bit more complex:

     if (size < 4) {
         g.setStrokeStyle(g.getWebColor("#ff0000"));  // Color.RED
     } else if (size < 13) {
         g.setStrokeStyle(g.getWebColor("#00ff00"));  // Color.GREEN
     } else if (size < 40) {
         g.setStrokeStyle(g.getWebColor("#00FFFF"));  // Color.CYAN
     } else {
         g.setStrokeStyle(g.getWebColor("##FFFF00"));  // Color.YELLOW
     }
     g.beginPath();
     g.moveTo(x0, y0);
     g.lineTo(x, y);
     g.stroke();

The final changes where we also define the canvas size are in index.html which you need to do above the comment :

        <h1>Tendrils Demo</h1>
        <canvas width="600" height="600" id="tendrils"></canvas>
        <!-- boot bck2brwsr -->

Run project tendrils Client for JavaFX and you should see something similar to the following image:

File:DS_Fig_8.png‎

Note: There is a bug as of this version of DukeScript which does not display the colors correctly; this bug should disappear in the next version of DukeScript.

After you have successfully ported your applet to the JavaFX client of DukeScript, running it in a browser just requires that you clean and build the tendrils maven project. Run the tendrils Client for Web project and:

File:DS_Fig_9.png‎

No need to write a single Javascript line of code!

Deploy

Of course, you don't want to run it from within you IDE but you should be able to deploy and run it independently in a browser. What you need to deploy to your web server is the contents of tendrils/client-web/target/tendrils-web-1.0-SNAPSHOT-bck2brwsr/public_html/:

  • lib/
  • bck2brwsr.js
  • index.html
  • tendrils.js

That's it! Open index.html in your modern browser and let the magic work! No security exceptions any more!

To recap, DukeScript offers you many advantages. It is not only a solution to deploy to desktop, but at the same time it supports many different devices. Porting your applet to DukeScript required few changes and in the end you just need to learn an API similar to JavaFX.

Convert to HTML 5 Javascript

Another alternative is to convert your applet directly to HTML 5 if you like Javascript. Pros & cons

  • + A lot of documentation on HTML 5
  • + Easier deployment
  • - Write in Javascript
  • - Learning curve of learning a new language if not already familiar with it

NetBeans 8 provides excellent support for HTML 5.

  1. Create a new Project (File -> New Project) and choose HTML 5 under Categories and HTML 5 Application under Projects. Click Next.

File:HTML_Fig_1.png

Enter a project name and location and click on Finish.

The result is index.html:

<!DOCTYPE html>
<html>
    <head>
        <title>TODO supply a title</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
    <body>
        <div>TODO write content</div>
    </body>
</html>

Let's start by adding a Canvas to our page:

<!DOCTYPE html>
<html>
    <head>
        <title>Tendrils</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <script type="text/javascript">
            function loader() {
                var canvas = document.getElementById('canvas');
                var context = canvas.getContext('2d');
            }
        </script>        
    </head>
    <body onload="loader()">
         <h1>Tendrils Demo!</h1>
         <canvas id="canvas" width="600" height="600">
         </canvas>
    </body>
</html>

context is the equivalent to java.awt.Graphics. Before we port our Java code to JavaScript, please keep in mind some guidelines which may save you hours of debugging.

  • Local variables are defined with the keyword var; don't forget this. A simple rule is to find where local variables are defined in your Java code and replace their type with var in JavaScript, e.g. int newsize = size / REDUX; should become var newsize = size / REDUX;. If you don't, then JavaScript assumes this is a global variable and this can cause you a number of problems. Do not prepend var to variables that are passed as arguments in functions, as that would mean that you redefine a new local variable.
  • Read the references on how to write Object-Oriented JavaScript code. This is done like so, e.g.: var Custer = new function() {} where you can also pass arguments. The keyword prototype defines member methods, e.g.: Cluster.prototype.display = function (g, size, x, y) {}.

Here is the ported code:

<script type="text/javascript">
            var NUMBER = 7;	// Number of helixes in a cluster
            // Cluster
            var Cluster = function() {
            };
            Cluster.prototype.display = function (g, size, x, y) {
                for (var i = 0; i < NUMBER; i++) {
                    var theta = i * 2 * Math.PI / NUMBER;
                    var t = new Tendril();
                    t.display(g, size, theta, x, y);
                }
            };
            
            var NUME = 30;         // Numerator of probability
            var DENOM = 100;       // Denominator of probability
            var RAD = 3.0;         // length of line segments
            var DELTHETA = 0.1;    // change in angle theta (in rad)
            var REDUX = 3;         // division of number of helixes
            var MIN = 1;           // min number of segments
            
            // Tendril
            var Tendril = function() {
            };
            
            Tendril.prototype.display = function(g, size, theta, x, y) {
                for (var j = 0; j < size; j++) {
                    var chng = (((DENOM * Math.random()) | 0) < NUME) ? -1 : 1;
                    theta += chng * DELTHETA;
                    var x0 = x;
                    var y0 = y;
                    x += RAD * Math.sin(theta);
                    y += RAD * Math.cos(theta);
                    if (size < 4) {
                        g.strokeStyle = '#ff0000';  // Color.red
                    } else if (size < 13) {
                        g.strokeStyle = '#00ff00';  // Color.green
                    } else if (size < 40) {
                        g.strokeStyle = '#ffff00';  // Color.cyan
                    } else {
                        g.strokeStyle = '#0000ff';  // Color.yellow
                    }
                    g.beginPath();
                    g.moveTo(x0, y0);
                    g.lineTo(x, y);
                    g.stroke();
                }
                if (size > MIN) {
                    var c = new Cluster();
                    var newsize = size / REDUX;
                    c.display(g, newsize, x, y);
                }
            };
            
            var X = 300;
            var Y = 300;
            var SEGS = 60;		// max number of segments
            
            function loader() {
                var canvas = document.getElementById('canvas');
                var context = canvas.getContext('2d');
                var cluster = new Cluster();
                cluster.display(context, SEGS, X, Y);
            };
</script>

g.setColor() is converted to JavaScript g.strokeStyle() passing an RGB color, while drawing a line is similar to the DukeScript way (or vice versa):

 g.beginPath();
 g.moveTo(x0, y0);
 g.lineTo(x, y);
 g.stroke();

Finally: (DENOM * Math.random()) | 0 is a simple way to round to an integer instead of using Math.round(). Run the file from inside NetBeans to see a nice fractal!

To debug JavaScript code, either:

File:HTML_Fig_2.png

Deploy

Deployment is very easy. Just one file (since we didn't extract the JavaScript code to its own .js file): Tendrils/public_html/index.html.

Add Interaction

Let's see how easy is it to add interaction to our applet, i.e. when you click on the fractal a new fractal will be rendered like you clicked on the refresh button of your browser.

Java Applet

Let's start with our legacy Java applet. Adding a mouse listener is no different than what a Java programmer should already now.

public class Tendrils extends java.applet.Applet {
  ...
 public void init() {
    setSize(600, 600);
    cluster = new Cluster();
    this.addMouseListener(new MouseAdapter() {
      public void mouseClicked(MouseEvent e) {
         repaint();
      }       
    });
 }
...

Pretty easy!

JavaFX

Adding a mouse listener in JavaFX is similar:

public class TendrilsFX extends Application {
  ...
  @Override 
  public void start(Stage primaryStage) {
    ...
        scene.addEventHandler(MouseEvent.MOUSE_CLICKED, (MouseEvent event) -> {
            g2D.clearRect(0, 0, X, Y);
            cluster.display(g2D, SEGS, X/2, Y/2);
            event.consume();
        });
    ...
  }
...

We clear the scene before we display a new tendril.

HTML5

Adding a mouse listener in HTML5 can be tricky (if you add unecessary parentheses):

... 
 var X = 300;
 var Y = 300;
 var SEGS = 60;		// max number of segments
 function loader() {
    var canvas = document.getElementById('canvas');
    onMouseClick(null);   // to remove code duplication
    canvas.addEventListener("click", onMouseClick, false);
 }
 function onMouseClick(evt) {
    var canvas = document.getElementById('canvas');
    var context = canvas.getContext('2d');
    context.clearRect(0, 0, canvas.width, canvas.height);
    var cluster = new Cluster();
    cluster.display(context, SEGS, X, Y);
 }
...

We clear the scene before we display a new tendril. A JavaScript programmer might come up with a better solution.

DukeScript

More changes are required by DukeScript. Interaction is done via Knockout.js. We can either modify the existing code or create a new DukeScript project and modify that.

The following changes are needed. In the index.html bind to the method refresh() of the data model:

<canvas width="600" height="600" id="tendrils" data-bind="click: $root.refresh()"></canvas>

$root refers to the root of the datamodels.

Main class needs to be cleaned up and call a method to apply the bindings to the data model which we will create next (if you chose to create a new DukeScript project then the DataModel class should have been already created for you):

import net.java.html.boot.BrowserBuilder;
 
public final class Main {
    private Main() {
    }
 
    public static void main(String... args) throws Exception {
        BrowserBuilder.newBrowser().
            loadPage("pages/index.html").
            loadClass(Main.class).
            invoke("onPageLoad", args).
            showAndWait();
        System.exit(0);
    }
 
    /**
     * Called when the page is ready.
     */
    public static void onPageLoad() throws Exception {
//        DataModel.onPageLoad();
        Data d = new Data();
        d.applyBindings();
    }
}

Finally, the DataModel class needs to be modified to remove any other bindings (or created) and add the Cluster and Tendril classes into it:

@Model(className = "Data", targetId = "", properties = {})
final class DataModel {
 
    private static final int X = 600;
    private static final int Y = 600;
    private static final int SEGS = 60;         // max number of segments
    private static final Cluster cluster = new Cluster();
    private static final GraphicsContext2D g = HTML5Graphics.getOrCreate("tendrils");
 
    @Function
    static void refresh() {
        g.clearRect(0, 0, X, Y);
        cluster.display(g, SEGS, X / 2, Y / 2);
    }
 
 // classes Tendril and Cluster follow

You need to clean and build the project before you run it. Now when you click on the fractal on the screen, a new tendril is rendered because the binding from index.html calls the refresh() method which clears the canvas and repaints the fractal.

The changes needed for DukeScript are more than the other solutions, but this is because we started our implementation by deleting the DataModel (if you remember). If we had left it, then the only addition would have been the binding in index.html and the addition of the refresh() method in DataModel:

    @Function
    static void refresh() {
        g.clearRect(0, 0, X, Y);
        cluster.display(g, SEGS, X / 2, Y / 2);
    }

Summary

I showed you three ways to revive your Java Applets and make them useful again:

  • via JavaFX
  • via DukeScript
  • via HTML 5 (JavaScript)

Other ways do exist (please drop me an email: jkosta at mailbox dot gr). Of the three, JavaScript is the one that requires most modifications while JavaFX is the most difficult to deploy. DukeScript is somewhere in the middle regarding easiness of portability and of deployment. In the end, which road to follow is a matter of personal taste and experience.

Appendix

The appendix provides an explanation of the Tendrils Java applet. Fractals are mathematical graphical constructs that are self-resemblant. That means that a part of them resembles their total. Fractals start with a simple graphic (a line segment in Tendrils) and repeat it in different scales in order to construct the final image. In Tendrils every line segment connect to its previous by an obtuse angle (theta) that might be clockwise or anti-clockwise depending on randomness (chng). We try to make it turn more times clockwise than anti-clockwise or vice-versa. All these consequent line segments produce an helix or tendril. A number of helixes is called a cluster. All helixes that belong to the same cluster start from the same point.

Class Tendril draws an helix (consists of 60 segments) while class Cluster a cluster of helixes (7 in total). The main program starts by drawing a cluster, which in turn creates a number of tendrils (all starting from the same point and each one consisting of line segments). When the drawing of the tendrils finishes, a new cluster starts but with smaller size. Helixes (tendrils) create clusters and clusters create tendrils until they are not visible any more in which case each tendril creates itself but doesn't create a new cluster (we reach the minimum number of segments which is 1).

References

  1. Lafore R. (1991), Object Oriented Programming in Turbo C++, Waite Group.
  2. Stefanov S. (2008), Object Oriented JavaScript, Packt.
  3. Introduction to Object-Oriented JavaScript, MDN.
Not logged in. Log in, Register

By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2012, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo