License text

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER 
 * Copyright  2008, 2010 Oracle and/or its affiliates.  All rights reserved. 
 * Use is subject to license terms.
 * 
 * This file is available and licensed under the following license:
 * 
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met: 
 * 
 *   * Redistributions of source code must retain the above copyright notice, 
 *     this list of conditions and the following disclaimer. 
 *
 *   * Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *
 *   * Neither the name of Oracle Corporation nor the names of its contributors 
 *     may be used to endorse or promote products derived from this software 
 *     without specific prior written permission. 
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

    

package com.sun.list;

import javafx.scene.CustomNode;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.scene.Group;
import javafx.scene.input.MouseEvent;
import javafx.scene.Node;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseButton;

import com.sun.list.ListModal;
/**
 * @author Raghu Nair
 */
public class ListView extends CustomNode{
    public var listWidth: Number;
    public var listHeight: Number;
    var items: ListItem[];
    public var factory:ListItemFactory;
    public var selectedItem:ListModal;

    public-read var focusedListItem: ListItem on replace oldVal{
        oldVal.isFocused = false;
        focusedListItem.isFocused = true;
        focusedListItem.requestFocus();
    };

    public-read var selectedIndex: Integer = 0;
    var draggedListItem: ListItem;
    public var inset: Number = 5;
    public var slotWidth: Number = listWidth - inset / 2.0;
    public var slotHeight: Number = 20;
    public var hSlotGap: Number = 1;
    public var actionOnSelect:function():Void;
    var itemsGroup: Group;
    var dragStart: Number;
    var velocity: Number;
    var friction: Number = 0.7;
    var minY: Number = 0;
    var maxY: Number = 0;
    var origY: Number;
    var vGap: Number = 0;
    var listViewMaxY: Number = bind maxY + 20;

    public var listItems: ListModal[] on replace {
        var listItem: ListItem;
        delete items;
        items = for(i in [0..listItems.size() - 1]) {
            listItem = factory.create();
            listItem.item   =  listItems[i];
//            println("setting item {listItem.item}");
            listItem.width  = slotWidth - 1;
            listItem.height = slotHeight;
            listItem.translateX = (inset / 2.0);
            listItem.translateY = (slotHeight * i);

            if (listItems[i].selected == true)
            {
                selectedItem = listItems[i];
            }
            listItem.onKeyPressed = function (ke: KeyEvent) {
                    if (ke.code == KeyCode.VK_DOWN or ke.code == KeyCode.VK_TAB ) {
                        if (i < items.size() - 1) {
                            focusedListItem = items[i+1];
                            var slotMaxY = items[i+1].boundsInParent.maxY;
                            var slotMinY = items[i+1].boundsInParent.minY;
                            if( slotMaxY > listHeight) {
                                itemsGroup.translateY = listHeight - slotMaxY;
                            }
                        } else if (i == items.size() - 1) {
                            var slotMinY = items[0].boundsInParent.minY;
                            items[0].requestFocus();
                            itemsGroup.translateY = slotMinY;

                        }
                    } else if (ke.code == KeyCode.VK_UP) {
                        if (i > 0) {
                            focusedListItem = items[i-1];
                            var slotMinY = items[i - 1].localToScene(items[i - 1].boundsInLocal).minY;
                            var thisMinY = localToScene(boundsInLocal).minY;
                            if( thisMinY > slotMinY) {
                                itemsGroup.translateY += thisMinY - slotMinY;
                            }
                        } else if (i == 0) {
                            items[items.size() - 1].requestFocus();
                            var slotMaxY = items[items.size() - 1].boundsInParent.maxY;
                            itemsGroup.translateY = listHeight - slotMaxY;
                        }
                    }
                }
                listItem.onMousePressed = function(me: MouseEvent):Void{
                    selectedIndex = i;
                    focusedListItem = items[i];
                        if ( actionOnSelect != null ){
                            if (me.button == MouseButton.SECONDARY)
                            {
                                actionOnSelect();
                            }
                        }
                }
                listItem.onMouseClicked = function(me: MouseEvent):Void{
                    selectedIndex = i;
                    focusedListItem = items[i];
                        if ( actionOnSelect != null ){

                            if (me.clickCount > 1)
                            {
                                actionOnSelect();
                            }
                        }
                }
                listItem;
        }

    }


    


    public override function create(): Node {

        itemsGroup = Group {
            content: bind [
                items,
                ]
        };
        var group = Group {
            content: bind[itemsGroup]
            onMouseDragged: function(e:MouseEvent):Void {
                var newY = origY + e.dragY;

                if(itemsGroup.boundsInLocal.height <= listHeight)
                    return;
                if ( newY > 0 ) {
                    newY = newY * 0.3;

                } else {
                    if ( newY < - (itemsGroup.boundsInLocal.height - listHeight) ){
                        itemsGroup.translateY = -(itemsGroup.boundsInLocal.height - listHeight);
                    }
                    else {
                        itemsGroup.translateY = newY;
                    }
                }

            }
            clip: Rectangle {
                width: listWidth
                height: listHeight
            }
        }
        return group;
    }
}