DropItem.qml 5.6 KB
/*
    This file is part of Gabriel's QML_Custom_Components

    QML_Custom_Components is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    QML_Custom_Components is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License.
    If not, see <http://www.gnu.org/licenses/>.

    DropItem v0.1
    Updated: 10/09/2015 by: Gabriel F.
    contactMe: http://gaf.impa.br/contact/ or http://www.gabrieldesign.com.br
    watch the video working at: https://youtu.be/CxxuIpKmMmc

    To use, include the file in project and add the following code somewhere in qml:

    DropItem {
        id: menuItem_A
        anchors.leftMargin: parent.width*0.05
        anchors.left: parent.left
        width: parent.width*0.25
        height: width
        anchors.bottom: parent.top
        peekText: "CLICK ME!"
    }

*/

import QtQuick 2.4
import QtGraphicalEffects 1.0

Item {

    property int    prePeek: -height*0.15
    property int    peek: -height*0.3
    property int    drop: -height*1.1
    property int    time: 1000

    /* // Under developmente // Not functional
    property bool   useSide: false
    property bool   useBottom: false
    property bool   useLeft: false
    */

    property string image: "qrc:/faceWhite.svg"
    property string peekText: "CLICK ME!"
    property var    openClickedCallback: function() { console.log("Clicked the smile button!") }

    property bool fallen: false

    NumberAnimation {
        id: peekAnimation
        target: menuItem01
        property: "anchors.bottomMargin"
        duration: time
        easing.type: Easing.OutElastic
        easing.amplitude: 1
        to: peek
    }

    NumberAnimation {
        id: reverseAnimation
        target: menuItem01
        property: "anchors.bottomMargin"
        duration: time
        easing.type: Easing.OutElastic
        easing.amplitude: 1
        to: prePeek

        onStarted: { showAnimation.start() }
        onStopped: { fallen = false }
    }

    NumberAnimation {
        id: dropAnimation
        target: menuItem01
        property: "anchors.bottomMargin"
        duration: time
        easing.type: Easing.OutElastic
        easing.amplitude: 1
        to: drop

        onStarted: { hideAnimation.start(); }
        onStopped: { fallen = true }
    }

    NumberAnimation {
        id: hideAnimation
        target: menuLabel01
        property: "opacity"
        duration: time/2
        easing.type: Easing.Linear
        easing.amplitude: 1
        to: 0.0
    }

    NumberAnimation {
        id: showAnimation
        target: menuLabel01
        property: "opacity"
        duration: time/2
        easing.type: Easing.Linear
        easing.amplitude: 1
        to: 1.0
    }

    Item {
        id: shadow
        width: menuItem01.width*1.3
        height: menuItem01.height*1.3
        anchors.centerIn: menuItem01
        Rectangle {
            width: menuItem01.width
            height: menuItem01.height
            radius: height*0.1
            color: "#000000"
            anchors.centerIn: parent
        }
        visible: false
    }

    FastBlur {
        anchors.fill: shadow
        source: shadow
        radius: 16
    }

    Rectangle {
        id: menuItem01
        width: parent.width
        height: parent.height
        color: "#000000"
        radius: height*0.1
        gradient: Gradient {
            GradientStop {
                position: 0.00;
                color: "#000000";
            }
            GradientStop {
                position: 1.00;
                color: "#535353";
            }
        }
        anchors.bottom: parent.bottom
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.bottomMargin: prePeek

        Image {
            id: menuImage
            source: image
            anchors.centerIn: parent
            width: parent.width*0.5
            height: width
            sourceSize.height: height
            sourceSize.width: width
        }

        Text {
            id: menuLabel01
            anchors.bottom: parent.bottom
            width: parent.width
            wrapMode: Text.WordWrap
            font.pixelSize: Math.abs(peek*0.4)
            color: "white"
            text: peekText
            font.bold: true
            horizontalAlignment: Text.AlignHCenter
        }

        Timer {
            id: menuMouseTimer
            interval: 500; running: true; repeat: true
            onTriggered: {
                if (!menuItemMouse.containsMouse && !peekAnimation.running) {
                    reverseAnimation.start()
                    menuMouseTimer.stop()
                }
            }
        }

        MouseArea {
            id: menuItemMouse
            width: parent.width*1.1
            height: (Math.abs(drop) + parent.height)*1.1
            anchors.horizontalCenter: parent.horizontalCenter
            anchors.bottom: parent.bottom
            anchors.bottomMargin: -parent.height*0.1
            hoverEnabled: true
            onEntered: { peekAnimation.start(); menuMouseTimer.start() }
            onExited:  { reverseAnimation.start() }
            onClicked: {
                if (!fallen) {
                    dropAnimation.start()
                } else {
                    openClickedCallback()
                }
            }
        }
    }

}