пятница, 27 августа 2010 г.

ListView Multiple Selection 2

After reading the post about ListView Multiple Selection I started integrating a new ListView it into my project, but in few minutes I figured out that there were no normal key multiple selection support. So, I decided to fix this problem.

The problem

At first I was thinking about overriding callActionForEvent(e:KeyEvent):Void method in com.sun.javafx.scene.control.behavior.ListViewBehavior, but I've found out that it's not so simple. After applying a new behavior for a ListView in ListViewSkin like this:
class ListSkin extends ListViewSkin {
     override var behavior = ListBehavior{}
     ...
}
The ListView stops scrolling up/down if I use keys for navigation. I was thinking about putting some parameters in ListBehavior, but still no luck.

Workaround

As for workaround you'll need to put some extra code in MultiSelectListView class
override var onKeyPressed = function(e:KeyEvent):Void {
if ((e.code == KeyCode.VK_UP) or (e.code == KeyCode.VK_DOWN)
        or (e.code == KeyCode.VK_PAGE_DOWN) or (e.code == KeyCode.VK_PAGE_UP)
        or (e.code == KeyCode.VK_HOME) or (e.code == KeyCode.VK_END)) {
        if (not e.controlDown and not e.shiftDown) {
           delete selectedIndexes;
        }            
    }
    if (e.controlDown and e.code == KeyCode.VK_SPACE) {
        def index:Integer = (e.node as List).focusedIndex;
        if (-1 == Sequences.indexOf(selectedIndexes, index)) {
            insert index into selectedIndexes;
        } else {
            delete index from selectedIndexes;
            if (index == selectedIndex) select(selectedIndexes[0]);
        }
    }
}

As a result

  • So, now you are able to use Ctrl+Space to add new selected items or remove old items from selection.
  • If you use keys such as: HOME, END, PAGE_UP, PAGE_DOWN, UP or DOWN without holding a Ctrl button multiple selection will be lost(I think it's user expected behavior :) )
  • I didn't do anything with Shift key. So, it does nothing.

Small fix

The ListView by Jonathan Giles has a small bug, it's also about using keys for selecting items. In MultiSelectListCellBehavior class, he has a case for deselecting all previously selected items.
public class MultiSelectListCellBehavior extends ListCellBehavior {
    ...
    override function mouseReleased(e) {
       ...
       } else {
           delete listView.selectedIndexes;
           insert row into listView.selectedIndexes;
           listView.focus(row);
       }
    }
}
As you can see in the end he used listView.focus(row); for selecting an item, but this stuff wont wok correctly. If you made some selection with the help of keys you'll get at least two selected items. So, I think it's better to use listView.select(row); instead.

Have a nice code :)