Infolog version 4.0 released

Infolog version 4.0 is released! The communication between the client and the server now uses a Rest webservice. This enabled me to write an Android client as wel. When upgrading, please note that data is now stored in json format. Before upgrading, make sure all your notes are on the server. See Infolog page for details about the program.

Systray not supported with OpenJDK and Compiz

Yesterday I stumbled upon a bug in the the OpenJDK. A system tray icon is not supported while using Compiz. I found out about this because I was playing around with the Google WindowBuilder. It kept freezing while using the Sun-JDK. With the OpenJDK it only freezes with opening a separate preview window. Then I noticed that my Infolog program wouldn’t start anymore. So when you are using the particular combination of Compiz and OpenJDK you won’t be able to use a system tray icon with Java. These options are open to you:

  1. Install Sun-JDK and don’t use the Google WindowBuilder.
  2. Install both JDK’s and use the Sun-JDK with programs that need a system tray icon, and the OpenJDK with Eclipse and the Google WindowBuilder.
  3. Install the OpenJDK en don’t bother with a system tray Icon.
  4. Stop using Compiz.
  5. Install Sun-JDK and use Windho$e in a virtual box.

The last one is not a real option of course, I only mentioned it to be complete ;-).

JCombobox with extra items that are not part of the list

In my last post I spoke about a JCombobox with the ability to add disabled items. Today I muse a little more on the JCombobox. This time I wanted to add an item to the JCombobox that is not part of the list with displayed items.

ComboboxExtraItem

JCombobox has a method setSelectedItem(Object anObject) for this. When you call this method with an item that is not part of the list it will only be displayed when the JCombobox is editable, if the JCombobox is not editable it will be ignored completely. So, in order to get an JCombobox to which we can call setSelectedItem(Object anObject) with the provided Object not being part of the list and that is not editable we extend our previous DisabledItemsCombobox with our own ComboBoxEditor. Now the trick is that we set the JCombobox editable property to true, but the editable property of the ComboBoxEditor to false.

import java.awt.Component;
import java.util.HashSet;
import java.util.Set;

import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.UIManager;
import javax.swing.plaf.basic.BasicComboBoxEditor;
import javax.swing.plaf.basic.BasicComboBoxRenderer;

public class DisabledItemsComboboxDemo extends JFrame {

 public static void main(String[] args) {
  DisabledItemsComboboxDemo frame = new DisabledItemsComboboxDemo(
    "Combobox displaying an item that is not part of the list");
  frame.setVisible(true);
 }

 public DisabledItemsComboboxDemo(String title) {
  super(title);
  this.setDefaultCloseOperation(EXIT_ON_CLOSE);
  this.init();
 }

 private void init() {
  this.setSize(500, 50);
  DisabledItemsComboBox box = new DisabledItemsComboBox();
  box.addItem("This item is disabled but selected at first appearance", true);
  box.addItem("This item is disabled and you cannot select it", true);
  box.addItem("This is the first selectable item");
  box.addItem("This is the second selectable item");
  box.addItem("This is the third selectable item");
  MyComboBoxEditor editor = new MyComboBoxEditor();
  box.setEditor(editor);
  box.setEditable(true);
  box.setSelectedItem("This item is not in the list of selectable items");
  add(box);
 }

 private class DisabledItemsComboBox extends JComboBox {

  public DisabledItemsComboBox() {
   super();
   super.setRenderer(new DisabledItemsRenderer());
  }

  private Set disabled_items = new HashSet();

  public void addItem(Object anObject, boolean disabled) {
   super.addItem(anObject);
   if (disabled) {
    disabled_items.add(getItemCount() - 1);
   }
  }

  @Override
  public void removeAllItems() {
   super.removeAllItems();
   disabled_items = new HashSet();
  }

  @Override
  public void removeItemAt(final int anIndex) {
   super.removeItemAt(anIndex);
   disabled_items.remove(anIndex);
  }

  @Override
  public void removeItem(final Object anObject) {
   for (int i = 0; i < getItemCount(); i++) {
    if (getItemAt(i) == anObject) {
     disabled_items.remove(i);
    }
   }
   super.removeItem(anObject);
  }

  @Override
  public void setSelectedIndex(int index) {
   if (!disabled_items.contains(index)) {
    super.setSelectedIndex(index);
   }
  }

  private class DisabledItemsRenderer extends BasicComboBoxRenderer {

   @Override
   public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
     boolean cellHasFocus) {

    if (isSelected) {
     setBackground(list.getSelectionBackground());
     setForeground(list.getSelectionForeground());
    } else {
     setBackground(list.getBackground());
     setForeground(list.getForeground());
    }
    if (disabled_items.contains(index)) {
     setBackground(list.getBackground());
     setForeground(UIManager.getColor("Label.disabledForeground"));
    }
    setFont(list.getFont());
    setText((value == null) ? "" : value.toString());
    return this;
   }
  }
 }

 public class MyComboBoxEditor extends BasicComboBoxEditor {

  public MyComboBoxEditor() {
   editor.setEditable(false);
  }
 }
}

JCombobox with disabled items

I saw a couple of posts (here and here) about a common problem in Java: creating a JCombobox with some items disabled. To give an idea to what I mean here is a screenshot. It shows a JCombobox with some items in gray that cannot be chosen:

DisabledComboboxItem

Here is my solution to this:

import java.awt.Component;
import java.util.HashSet;
import java.util.Set;

import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.UIManager;
import javax.swing.plaf.basic.BasicComboBoxRenderer;

public class DisabledItemsComboboxDemo extends JFrame {

 public static void main(String[] args) {
  DisabledItemsComboboxDemo frame
    = new DisabledItemsComboboxDemo("Combobox with disabled items");
  frame.setVisible(true);
 }

 public DisabledItemsComboboxDemo(String title) {
  super(title);
  this.setDefaultCloseOperation(EXIT_ON_CLOSE);
  this.init();
 }

 private void init() {
  this.setSize(500, 50);
  DisabledItemsComboBox box = new DisabledItemsComboBox();
  box.addItem("This item is disabled but selected at first appearance",
              true);
  box.addItem("This item is disabled and you cannot select it", true);
  box.addItem("This is the first selectable item");
  box.addItem("This is the second selectable item");
  box.addItem("This is the third selectable item");
  add(box);
 }

 private class DisabledItemsComboBox extends JComboBox {

  public DisabledItemsComboBox() {
   super();
   super.setRenderer(new DisabledItemsRenderer());
  }

  private Set disabled_items = new HashSet();

  public void addItem(Object anObject, boolean disabled) {
   super.addItem(anObject);
   if (disabled) {
    disabled_items.add(getItemCount() - 1);
   }
  }

  @Override
  public void removeAllItems() {
   super.removeAllItems();
   disabled_items = new HashSet();
  }

  @Override
  public void removeItemAt(final int anIndex) {
   super.removeItemAt(anIndex);
   disabled_items.remove(anIndex);
  }

  @Override
  public void removeItem(final Object anObject) {
   for (int i = 0; i < getItemCount(); i++) {
    if (getItemAt(i) == anObject) {
     disabled_items.remove(i);
    }
   }
   super.removeItem(anObject);
  }

  @Override
  public void setSelectedIndex(int index) {
   if (!disabled_items.contains(index)) {
    super.setSelectedIndex(index);
   }
  }

  private class DisabledItemsRenderer extends BasicComboBoxRenderer {

   @Override
   public Component getListCellRendererComponent(JList list,
                                                 Object value,
                                                 int index,
                                                 boolean isSelected,
                                                 boolean cellHasFocus) {

    if (isSelected) {
     setBackground(list.getSelectionBackground());
     setForeground(list.getSelectionForeground());
    } else {
     setBackground(list.getBackground());
     setForeground(list.getForeground());
    }
    if (disabled_items.contains(index)) {
     setBackground(list.getBackground());
     setForeground(UIManager.getColor("Label.disabledForeground"));
    }
    setFont(list.getFont());
    setText((value == null) ? "" : value.toString());
    return this;
   }
  }
 }
}