Home
Ceylon logo

Iconbar basics

This site supports Convergence

 

What's new?

Our mission

Who are Topix?


Acorn freeware

The beta area

Articles

CodeCraft

 

Introduction

In this chapter we'll add to the program of the previous chapter an icon on the iconbar. Clicking with Select or Adjust on the icon will popup a short message. Clicking with Menu will end the program.

Just one little icon

Putting an icon on the iconbar is part of the initialisation of the application. Because ceylon_init must be executed first, we will put the icon on the iconbar after that statement:
   iconbar_icon = iconbar_create_icon("!demo2");
The argument of this function is the name of the sprite as present in the !Sprites and !Sprites22 files. The name of the icon must match the name of the application directory. The function returns a handle to the icon. And before you start to panic, read the following paragraph...

What's a handle?

Each element in the WIMP, like windows, icons and menus are appointed a handle. This is a 32 bit integer used to refer to the element. This might be a pointer to a block of memory describing the element, or it could be some abstract number. Anyway, handles are a way for the WIMP to recognise an element. Ceylon makes use of handles too. Instead of referring to an element as "the nth element in window x" we just use "the element with handle h" which is usually a lot easier to work with. You'll see some practical examples later on.

Let's handle the icon

Now we have put an icon on the iconbar, we would like to do something useful with it. As announced in the introduction, clicking with Select. This action by the user (clicking with Select) causes an event. In the first chapter you could read that all events are handled by the event loop. Ofcourse the event loop doesn't know what to do with the event if we don't tell him. So that's what we will do before entering the loop:
   event_install_window_handler(ICONBAR, iconbar_handler, NULL);
This looks rather complicated, but it's really easy, you'll see. What we want to tell to the event handler inside the event loop is the following: "If anything happens with the icon on the iconbar, please call me".

So, let's look to the three arguments of the function. The first argument is the window handle, in this case it's the iconbar. (Yes, the iconbar is a window with its own window handle.) The second argument is a function we provide ourselves, a so-called callback function. The last argument is a pointer to some data we currently don't have to worry about.

The callback function

After the user clicks on the iconbar icon, the event handler remembers we told him to call us when something would happen with the icon and calls us back. So this is how the prototype of the callback function looks like:
void iconbar_handler(ceylon_message mess, void *context);
The first argument is the message Ceylon has to tell us. It will tell us what happened to the iconbar icon. Did the user click on the icon, or was a file dropped onto it? mess tells it all...

The second argument is equal to the last argument of the function described in the previous paragraph. This argument is used when the same callback function is used in two different situations. This argument might contain a pointer to some data which is particular to one of the situations. We don't use it now, so it has been left NULL. If you don't quite understand at the moment, don't worry, it will come back later.

So all we have to do now is find out what the event handler wants to tell us. Did the user click on the icon? And if so, we put a message on the screen:

   switch(mess -> type)
   {
      case message_mouse_click:
         usermsg_mess("You clicked on the icon!", USERMSG_MESSAGE);
   }
message_mouse_click is one of the messages you can receive from the event handler. usermsg_mess puts a message on the screen. The second parameter tells Ceylon that it's a normal message, not an error.

More features...

As we want to be able to quit the program we'll just extend the above case a little with a check for the mouse button used while clicking on the iconbar icon:
      case message_mouse_click:
         if (mess -> position.buttons.bits.menu)
            quit_program(QUIT_USER);
         else
            usermsg_mess("You clicked on the icon!", USERMSG_MESSAGE);
Now we can differentiate between the different mouse buttons and act apparently. When the user uses Menu we call quit_program to end the program in a neat way. The argument of that function tells Ceylon to program has been ended by the user and not by the system. You'll see this value is used elsewhere later.

The complete program

After collecting all pieces from above and adding the necessary glue, we end up with the following:
   #include <stdlib.h>
   #include "ceylon:ceylon.h"
   #include "ceylon:iconbar.h"
   #include "ceylon:usermsg.h"
   
   icon iconbar_icon;
      
   void iconbar_handler(ceylon_message mess, void *handle)
   {
      switch(mess -> type)
      {
         case message_mouse_click:
            if (mess -> position.buttons.bits.menu)
               quit_program(QUIT_USER);
            else
               usermsg_mess("You clicked on the icon!", USERMSG_MESSAGE);
            break;
      }
   }
      
   int main(void)
   {
      // initialise the program
   
      ceylon_init("Demo2", "<Ceylon$Dir>.Resources.Messages");
   
      // put an icon on the iconbar
   
      iconbar_icon = iconbar_create_icon("!demo2");
   
      // tell Ceylon which function to call when something happens with
      // the iconbar icon
   
      event_install_window_handler(ICONBAR, iconbar_handler, NULL);
   
      // wait for things to happen
   
      event_loop();
   
      // the program has been exited by the task manager, so tell the
      // WIMP the program has been terminated succesfully
   
      return EXIT_SUCCESS;
   }
That's all for now!

Last update: 21 Mar 1998