Trouvant ce widget GTK plutôt intéressant, je me décide de chercher son nom pour tenter de l'utiliser. Malheureusement, impossible de le trouver. En effet, le(s) développeur(s) de emesene nous avai(en)t concocté un widget GTK "custom".
Ce composant permet ici de choisir le statut à utiliser pour se connecter. Étant de nature plutôt curieux, j'ai tout de suite sauté sur l'occasion pour tenter de reproduire ceci en Java avec l'aide de java-gnome.

Commençons sans plus attendre. On va faire ça bien et utiliser au total 3 classes et une énumération (Icons, Main, Status, StatusButton). On va reproduire un bouton identique à celui de emesene avec un peu plus de statuts et d'icônes. Vous pouvez trouver une archive du projet fait via Eclipse en cliquant sur ce lien. Je vous passe la récupération des icônes et leur utilisation, on va se concentrer sur la construction du bouton de statut.

Comme je l'ai dit plus haut, ce bouton de statut n'existe pas par défaut. Il faut donc le créer et lui faire faire ce que l'on souhaite. Ici il s'agit simplement de lui faire afficher une icône et un menu lorsque le bouton est activé via un clique avec la souris. Pour que notre composant soit considéré en tant que widget par l'API java-gnome, on va jouer avec l'héritage et attribuer à notre classe StatusButton la classe mère Button de l'API.
    public class StatusButton extends Button {
        ...
    }


Notre classe se composera de 2 champs, d'un constructeur ainsi que de 3 méthodes dont 2 qui seront des méthodes redéfinies de la classe Button. Commençons par voir à quoi vont nous servir les 2 champs. Le premier sera un structure de données de type Map qui va nous permettre de construire un cache pour ne pas charger les icônes à chaque fois. Il sera utilisé également de manière static pour être commun à chaque StatusButton de notre interface s'il y en a plusieurs.
    private static HashMap<Integer, Image> _cache = new HashMap<Integer, Image>();

Le second champ sera quant à lui un simple objet de type org.gnome.gtk.Image. Il représentera donc l'image actuellement affichée par le bouton.
    private Image _image;

La construction du bouton se fera via le constructeur de notre classe. Il ne demandera aucun argument et fera appel au constructeur de la classe mère via le mot clé super.
    public StatusButton() {
        super();
        ...
    }


C'est ici que l'on va définir ce que le bouton affichera, son style ainsi que l'action à faire en cas de clique. Notre bouton sera donc (si le curseur n'est pas dessus) plat et ressemblera donc à un Label. Par défaut, il affichera l'icône associée au statut "En ligne".
    this.setStatus(Status.ONLINE);
    this.setRelief(ReliefStyle.NONE);
    this.setBorderWidth(0);


Maintenant, nous allons définir l'action réalisée si l'utilisateur clique sur le bouton via le listener Button.Clicked. Il est effectivement possible d'utiliser tous les listeners utilisables par la classe Button car notre widget hérite directement d'elle.
    this.connect(new Button.Clicked() {
        @Override
        public void onClicked(Button source) {
            ...
        }
    });


Lors du clique nous allons donc construire un menu contenant tous les statuts pour pouvoir en sélectionner un et ainsi changer l'icône affichée par notre bouton. Pour cela, on utilise des objets de type Menu, ImageMenuItem pour finalement popup le menu. Tout ceci est donc à placer dans la méthode onClicked ci-dessus.
    Menu contextMenu = new Menu();
    for (final Status status : Status.values()) {
        ImageMenuItem item = new ImageMenuItem(new Image(status.getIcon()), status.toString());
        contextMenu.append(item);

        item.connect(new MenuItem.Activate() {
            @Override
            public void onActivate(MenuItem source) {
                StatusButton.this.setStatus(status);
            }
        });
    }
    contextMenu.showAll();
    contextMenu.popup();


Une fois ce code terminé, notre constructeur est prêt. Regardons donc de plus près les méthodes utilisées à savoir setStatus, show et showAll. Ces deux dernières viennent de la classe mère Button et permettent d'afficher le widget.
    @Override
    public void show() {
        _image.show();
        super.show();
    }

    @Override
    public void showAll() {
        this.show();
    }


La méthode setStatus, elle permettra simplement de changer l'icône affichée par le bouton. Elle mettra également l'icône en cache si elle n'y est pas déjà.
    public void setStatus(Status status) {
        if (_cache.containsKey(status.getId()))
            _image = _cache.get(status.getId());
        else {
            _image = new Image(status.getIcon());
            _cache.put(status.getId(), _image);
        }
        this.setImage(_image);
    }


A ce stade, on a fait le tour de la construction du widget en lui-même. Je vous invite à jeter un oeil sur l'énumération Status et la classe Icons. Pour finir, on va regarder comment construire une fenêtre simple pour tester notre bouton (voir la classe Main).

On construit donc une fenêtre simple qui va contenir une VBox laquelle va avoir un Label et un StatusButton.
    final Window window = new Window();
    ...
    final Alignment align = new Alignment(0.0f, 0.0f, 0.0f, 0.0f);
    ...
    final VBox vbox = new VBox(false, 0);
    align.add(vbox);

    final Label label = new Label("Click on the above button.");
    vbox.add(label);
    final StatusButton button = new StatusButton();
    vbox.add(button);

    window.showAll();


Enfin, on écrit notre méthode principale à savoir le main. Il initialisera GTK, chargera les icônes et affichera la fenêtre.
    public static void main(String[] args) {
        Gtk.init(args);

        Icons.loadIcons();
        new Main();

        Gtk.main();
    }


Et finalement, on doit se retrouver avec quelque chose dans ce genre.