Tutorial 2: Turtle Graphic

For this tutorial you can decide if you want to use C or C++.

You will find out what are the differences between using this library in C or C++.

In the first tutorial the only thing the user could do was resizing and closing the window. In this tutorial we will see how the user could interact a little bit more with your application by using the Turtle Graphic.

We will create a Frame an draw two squares on it. When the user clicks on the Frame, we will check, if he clicked into a square and display a message.

In this tutorial we will have to initialize the Java Virtual Machine and the Frame by our self. In Tutorial 1: Simple Turtle this was done by the Simple Turtle library for us.

For the user interaction we need to get informed about the events the user causes. Therefore we will register callback functions to get informed about these events.

We have to program the following for this example:

To initialize the JVM you need a Jvm structure and the path of the "grubc.jar" file:

Jvm jvm;

initJvm(&jvm, "./grubc.jar");

For the callback functions you need normal functions which will be registered as listeners:

...
void mouseListener(jint event, jobject source, jint x, jint y, jint button, jint clickCount) {
   if (event == CB_MOUSE_CLICKED) {
       do something 
   }
}
...
Frame frame;
jobject ml;
...
ml = frame.addMouseListener(&mouseListener);
...
frame.removeMouseListener(ml);
...

Now you should know everything you need. The other functions you need can be found in the documentation.

Overview

Turtle Graphic in C

So lets start and create the new file "tut2.c" in your project:
#include "grubc/turtle/turtlegraphic.h"

/* Define the position, side length and color of square 1. */
#define S1_X_POS   100
#define S1_Y_POS   100
#define S1_LENGTH   100
#define S1_COLOR   BLUE

/* Define the position, side length and color of square 2. */
#define S2_X_POS   300
#define S2_Y_POS   100
#define S2_LENGTH   100
#define S2_COLOR   RED


/* Declare the needed variables. */
Jvm jvm;
Frame frame;
TurtleGraphic tg;

jboolean exitprg = JNI_FALSE;


/* Declare the needed listener callback functions. */
void windowListener(jint event, Window window);
void mouseListener(jint event, Component source, jint x, jint y, jint button, jint clickCount);

/* Declare additional functions. */
void drawSquares();
void drawSquare(jfloat x, jfloat y, jfloat length, Color c);

int main(int argc, char *argv[]) {
   WindowListener wl; /* WindowListener Object. */
   MouseListener ml; /* MouseListener Object. */

   initJvm(&jvm, "./grubc.jar"); /* Initialize the JVM. */

   createFrame(&frame); /* Create the frame. */

   /* Register the callback functions as listeners. */
   wl = frame.addWindowListener(&frame, &windowListener);
   ml = frame.addMouseListener(&frame, &mouseListener);

   /* Create the Turtle Graphic by passing the frame to draw on. */
   createTurtleGraphic(&tg, &frame);

   /* Set the title, size and location of the frame. */
   frame.setTitle(&frame, "Tutorial 2");
   frame.setLocation(&frame, 100, 100);
   frame.setSize(&frame, 500, 300);

   frame.show(&frame); /* Display the frame. */
   
   drawSquares(); /* Draw the squares. */

   /* Wait until exitprg is true. */
   WAIT_UNTIL_TRUE(exitprg);

   frame.close(&frame); /* Close the frame. */

   /* Deregister the callback functions. */
   frame.removeWindowListener(&frame, wl);
   frame.removeMouseListener(&frame, ml);

   /* Cleanup */
   deleteTurtleGraphic(&tg);
   deleteFrame(&frame);

   return 0;
}

void drawSquares() {
   drawSquare(S1_X_POS, S1_Y_POS, S1_LENGTH, S1_COLOR);
   drawSquare(S2_X_POS, S2_Y_POS, S2_LENGTH, S2_COLOR);
}

void drawSquare(jfloat x, jfloat y, jfloat length, Color c) {
   int i;

   tg.setDraw(&tg, JNI_FALSE); /* Disable drawing. */
   tg.moveTo(&tg, x, y); /* Move to start point. */
   tg.setColor(&tg, c); /* Set the color. */
   tg.setDraw(&tg, JNI_TRUE); /* Enable drawing. */
   for (i = 0; i <= 3; i++) { /* Draw the suqare. */
      tg.forward(&tg, length);
      tg.right(&tg, 90);
   }
}

void windowListener(jint event, Window window) {
   if (frame.isSameWindow(&frame, window)) {
      switch (event) {
         case CB_WINDOW_OPENED:
            break;
         case CB_WINDOW_CLOSING:
            exitprg = JNI_TRUE; /* Frame should be closed. */
            break;
         case CB_WINDOW_CLOSED:
            break;
         case CB_WINDOW_ICONIFIED:
            break;
         case CB_WINDOW_DEICONIFIED:
            break;
         case CB_WINDOW_ACTIVATED:
            break;
         case CB_WINDOW_DEACTIVATED:
            break;
      }
   }
}

void mouseListener(jint event, Component source, jint x, jint y, jint button, jint clickCount) {
   switch (event) {
      case CB_MOUSE_CLICKED:
         tg.clearScreen(&tg); /* Clear the frame. */
         tg.setDraw(&tg, JNI_FALSE);
         tg.setColor(&tg, BLACK); /* Set the color. */
         tg.moveTo(&tg, 50, 250); /* Move to the position to write the text. */

         /* Clicked into a square??? */
         if (x >= S1_X_POS && x <= S1_X_POS + S1_LENGTH && y >= S1_Y_POS && y <= S1_Y_POS + S1_LENGTH) {
            tg.printText(&tg, "You clicked into square 1!");
         } else if (x >= S2_X_POS && x <= S2_X_POS + S2_LENGTH && y >= S2_Y_POS && y <= S2_Y_POS + S2_LENGTH) {
            tg.printText(&tg, "You clicked into square 2!");
         }

         tg.setDraw(&tg, JNI_TRUE);
         drawSquares(); /* Draw the squares. */
         break;
      case CB_MOUSE_PRESSED:
         break;
      case CB_MOUSE_RELEASED:
         break;
      case CB_MOUSE_ENTERED:
         break;
      case CB_MOUSE_EXITED:
         break;
   }
}

Turtle Graphic in C++

So lets start and create the new file "tut2.cpp" in your project:
#include "grubc/turtle/turtlegraphic.h"

/* Define the position, side length and color of square 1. */
#define S1_X_POS   100
#define S1_Y_POS   100
#define S1_LENGTH   100
#define S1_COLOR   BLUE

/* Define the position, side length and color of square 2. */
#define S2_X_POS   300
#define S2_Y_POS   100
#define S2_LENGTH   100
#define S2_COLOR   RED


/* Declare the needed variables. */
Jvm jvm;
Frame frame;
TurtleGraphic tg;

jboolean exitprg = JNI_FALSE;


/* Declare the needed listener callback functions. */
void windowListener(jint event, Window window);
void mouseListener(jint event, Component source, jint x, jint y, jint button, jint clickCount);

/* Declare additional functions. */
void drawSquares();
void drawSquare(jfloat x, jfloat y, jfloat length, Color c);

int main(int argc, char *argv[]) {
   WindowListener wl; /* WindowListener Object. */
   MouseListener ml; /* MouseListener Object. */

   initJvm(&jvm, "./grubc.jar"); /* Initialize the JVM. */

   createFrame(&frame); /* Create the frame. */

   /* Register the callback functions as listeners. */
   wl = frame.addWindowListener(&windowListener);
   ml = frame.addMouseListener(&mouseListener);

   /* Create the Turtle Graphic by passing the frame to draw on. */
   createTurtleGraphic(&tg, &frame);

   /* Set the title, size and location of the frame. */
   frame.setTitle("Tutorial 2");
   frame.setLocation(100, 100);
   frame.setSize(500, 300);

   frame.show(); /* Display the frame. */
   
   drawSquares(); /* Draw the squares. */

   /* Wait until exitprg is true. */
   WAIT_UNTIL_TRUE(exitprg);

   frame.close(); /* Close the frame. */

   /* Deregister the callback functions. */
   frame.removeWindowListener(wl);
   frame.removeMouseListener(ml);

   /* Cleanup */
   deleteTurtleGraphic(&tg);
   deleteFrame(&frame);

   return 0;
}

void drawSquares() {
   drawSquare(S1_X_POS, S1_Y_POS, S1_LENGTH, S1_COLOR);
   drawSquare(S2_X_POS, S2_Y_POS, S2_LENGTH, S2_COLOR);
}

void drawSquare(jfloat x, jfloat y, jfloat length, Color c) {
   tg.setDraw(JNI_FALSE); /* Disable drawing. */
   tg.moveTo(x, y); /* Move to start point. */
   tg.setColor(c); /* Set the color. */
   tg.setDraw(JNI_TRUE); /* Enable drawing. */
   for (int i = 0; i <= 3; i++) { /* Draw the suqare. */
      tg.forward(length);
      tg.right(90);
   }
}

void windowListener(jint event, Window window) {
   if (frame.isSameWindow(window)) {
      switch (event) {
         case CB_WINDOW_OPENED:
            break;
         case CB_WINDOW_CLOSING:
            exitprg = JNI_TRUE; /* Frame should be closed. */
            break;
         case CB_WINDOW_CLOSED:
            break;
         case CB_WINDOW_ICONIFIED:
            break;
         case CB_WINDOW_DEICONIFIED:
            break;
         case CB_WINDOW_ACTIVATED:
            break;
         case CB_WINDOW_DEACTIVATED:
            break;
      }
   }
}

void mouseListener(jint event, Component source, jint x, jint y, jint button, jint clickCount) {
   switch (event) {
      case CB_MOUSE_CLICKED:
         tg.clearScreen(); /* Clear the frame. */
         tg.setDraw(JNI_FALSE);
         tg.setColor(BLACK); /* Set the color. */
         tg.moveTo(50, 250); /* Move to the position to write the text. */

         /* Clicked into a square??? */
         if (x >= S1_X_POS && x <= S1_X_POS + S1_LENGTH && y >= S1_Y_POS && y <= S1_Y_POS + S1_LENGTH) {
            tg.printText("You clicked into square 1!");
         } else if (x >= S2_X_POS && x <= S2_X_POS + S2_LENGTH && y >= S2_Y_POS && y <= S2_Y_POS + S2_LENGTH) {
            tg.printText("You clicked into square 2!");
         }

         tg.setDraw(JNI_TRUE);
         drawSquares(); /* Draw the squares. */
         break;
      case CB_MOUSE_PRESSED:
         break;
      case CB_MOUSE_RELEASED:
         break;
      case CB_MOUSE_ENTERED:
         break;
      case CB_MOUSE_EXITED:
         break;
   }
}

When you execute this program you will get a window which looks like this:

tutorial2.gif

Differences between the usage of C and C++

As you can see in this example the difference is the way you have the call the functions / "methods". In C you have to pass the structure when you call a function of a structure, but not in C++. In C++ you can call these functions like normal methods.

Example

You want to set the title of the frame.

In C:

frame.setTitle(&frame, "Title");

In C++:

frame.setTitle("Title");

Callback functions and listeners

In this example we have registered two callback functions as listeners. When you register a function by using addXXXListener() you get the registered listener object back. You need this object to unregister the callback function by using removeXXXListener().

The functions you can register as callback functions must have a certain signature, depending on which events you are interested in. For example the functions you can register as window listeners must look like this:

void functionname(jint event, jobject window)
The parameter event specifies, which window event occurred (like the window has been activated or the user wants to close the window) and the parameter window specifies the source window of the event.

More information about listeners can be found here: listeners.c


Generated on Sat Nov 19 14:11:17 2005 for GrubC by  doxygen 1.4.4