QML(Qt)のListViewにスクロールバーを追加してみる Part2

QML(Qt)のListViewにスクロールバーを追加してみる」で、作ったものを拡張した感じです。

/// ポイント ///
・キーボード操作で一番上や下とかページ送り
・バーが表示されるエリアをクリックすると一気に移動する。
 キーボードなしでも一気に一番上や下にいけるように。
・currentItemIndexを変更するとバーが表示される。
 元の作りだとマウスのスクロール機能使ってる時か慣性スクロールしてる時しかでない。


GooleCodeにコード置いてあります。
ListViewBaseエレメント」のコード


import QtQuick 1.0

ListView {
    id: _root
    x: 0
    y: 0
    width: parent.width
    height: parent.height
    clip: true

    property bool loading: (count < 1)

    property bool alwaysViewing: false                      // スクロールバーを常に表示するか
    property alias scrollBarVisible: _scrollBarBase.visible // 表示するか
    property alias scrollBarBaseColor: _scrollBarBase.color // ベース色
    property alias scrollBarColor: _scrollBar.color         // 色
    property real scrollBarOpacity: 0.8                     // 透過率

    property real density: 1.0

    Rectangle {
        id: _scrollBarBase
        width: 25 * _root.density
        anchors.top: parent.top
        anchors.right: parent.right
        anchors.bottom: parent.bottom
        anchors.margins: 2
        color: "#22ffffff"
        radius: 2 * _root.density
        opacity: 0.01
        visible: (visibleArea.heightRatio < 1.0) | alwaysViewing

        Rectangle {
            id: _scrollBar
            anchors.horizontalCenter: parent.horizontalCenter
            y: parent.height * visibleArea.yPosition
            width: parent.width * 0.1
            radius: width * 0.5
            height: parent.height * visibleArea.heightRatio
            color: "#ffffff"
        }

        MouseArea{
            anchors.fill: parent
            onClicked: {
                var per = mouse.y / height;
                var index = 0;
                if(per < 0.1){
                    // 一番上へ
                    index = 0;
                }else if(per > 0.9){
                    // 一番下へ
                    index = count - 1;
                }else{
                    // 中間
                    var h = height * 0.1;
                    index = Math.floor((count) * ((mouse.y - h) / (height - 2 * h)));
                }
                positionViewAt(index, ListView.Beginning);
            }
        }
    }


    // 選択を変更した時にスクロールバーを表示する。
    onCurrentIndexChanged: {
        if(!movingVertically && !alwaysViewing){
            if(state !== "Visible"){
                state = "Visible";
                _scrollBarVisibleTimer.start();
            }else if(state === "Visible"){
                _scrollBarVisibleTimer.restart();
            }
        }
    }

    // 選択を変更したときのスクロールバーを消すためのタイマー
    Timer{
        id: _scrollBarVisibleTimer
        interval: 500
        repeat: false
        triggeredOnStart: false
        onTriggered:{
            state = "";
        }
    }

    // キー操作
    Keys.onPressed: {
        switch(event.key){
        case Qt.Key_Home:
            // 一番上へ
            positionViewAtBeginEnd(true);
            break;
        case Qt.Key_End:
            // 一番下へ
            positionViewAtBeginEnd(false);
            break;
        case Qt.Key_PageUp:
            // 上へ飛ぶ
            positionViewAtPageUpDown(false);
            break;
        case Qt.Key_PageDown:
            // 下へ飛ぶ
            positionViewAtPageUpDown(true);
            break;
        }
    }

    /////////////////////////////////////////////
    // 表示位置をコントロールする

    // 表示位置を最初と最後
    function positionViewAtBeginEnd(is_begin){
        if(is_begin){
            positionViewAtIndex(0, ListView.Beginning);
            currentIndex = 0;
        }else{
            positionViewAtIndex(count - 1, ListView.Beginning);
            currentIndex = count - 1;
        }
    }

    // 表示位置をページ移動
    function positionViewAtPageUpDown(is_down){
        // ヘッダとフッタの高さを考慮する
        var top = indexAt(1, contentY);
        var bottom = indexAt(1, contentY + height);
        if(top < 0){
            top = 0;
        }
        if(bottom <= top){
            bottom = count - 1;
        }
        if(is_down){
            // 下へ
            positionViewAt(currentIndex + (bottom - top), ListView.End);
        }else{
            // 上へ
            positionViewAt(currentIndex - (bottom - top), ListView.Beginning);
        }
    }

    // 表示位置を任意の位置へ移動
    function positionViewAt(index, mode){
        if(index < 0){
            index = 0;
        }else if(index >= count){
            index = count - 1;
        }
        positionViewAtIndex(index, mode);
        currentIndex = index;
    }

    // ステータス管理
    states: [
        State {
            name: "Visible"
            when: movingVertically | alwaysViewing
            PropertyChanges {
                target: _scrollBarBase
                opacity: scrollBarOpacity
            }
        }
    ]

    //アニメーション
    transitions:
        Transition {
            PropertyAnimation {
                easing.type: Easing.OutCubic
                target: _scrollBarBase
                properties: "opacity"
                duration: 300
            }
        }

}