Skip to content
Snippets Groups Projects
LunaIcon.qml 6.73 KiB
Newer Older
  • Learn to ignore specific revisions
  • samuel's avatar
    samuel committed
        Copyright (C) 2024 Samuel Jimenez <therealsamueljimenez@gmail.com>
              Ported the Luna Plasmoid to Plasma 6.
    
    
        Copyright 2016,2017 Bill Binder <dxtwjb@gmail.com>
    
        Copyright (C) 2011, 2012, 2013 Glad Deschrijver <glad.deschrijver@gmail.com>
    
        This program 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.
    
        This program 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
        along with this program; if not, see <http://www.gnu.org/licenses/>.
    
    */
    
    
    import "../code/shadowcalcs.js" as ShadowCalcs
    
    samuel's avatar
    samuel committed
    import Qt5Compat.GraphicalEffects
    import QtQuick 2.1
    import org.kde.ksvg as KSvg
    import org.kde.plasma.core as PlasmaCore
    import org.kde.plasma.plasmoid
    
    wwjjbb's avatar
    wwjjbb committed
        id: lunaIcon
    
        property int phaseNumber: 0
    
    samuel's avatar
    samuel committed
        property int latitude: 90 //Degrees: 0=Equator, 90=North Pole, -90=South Pole
    
        property bool showShadow: true
    
        property bool transparentShadow: true
    
        property string lunarImage: ''
    
    samuel's avatar
    samuel committed
        property color diskColor: '#ffffff'
    
        property int lunarImageTweak: 0
    
    dxtwjb's avatar
    dxtwjb committed
        property bool showGrid: false
        property bool showTycho: false
        property bool showCopernicus: false
    
        // Degrees. 0= new moon, 90= first quarter, 180= full moon, 270= third quarter
        property int theta: 45
    
    
    samuel's avatar
    samuel committed
        KSvg.Svg {
    
    wwjjbb's avatar
    wwjjbb committed
            id: lunaSvg
    
    samuel's avatar
    samuel committed
    
            imagePath: lunarImage === '' ? '' : Qt.resolvedUrl("../data/" + lunarImage)
    
    wwjjbb's avatar
    wwjjbb committed
        }
    
    
    samuel's avatar
    samuel committed
        KSvg.SvgItem {
    
    wwjjbb's avatar
    wwjjbb committed
            id: lunaSvgItem
    
    samuel's avatar
    samuel committed
            visible: false
    
            anchors.centerIn: parent
    
            width: Math.min(parent.width, parent.height)
            height: Math.min(parent.width, parent.height)
    
    wwjjbb's avatar
    wwjjbb committed
            svg: lunaSvg
    
            // Rotation to compensate the moon's image basic position to a north pole view
            // FIXME: Somehow it does not work when applied to OpacityMask or Blend
    
    wwjjbb's avatar
    wwjjbb committed
            transformOrigin: Item.Center
    
    samuel's avatar
    samuel committed
            rotation: -lunarImageTweak
    
    wwjjbb's avatar
    wwjjbb committed
        }
    
    
        Canvas {
            id: shadow
    
            property int latitude: lunaIcon.latitude
    
            property int theta: lunaIcon.theta
    
            property bool showShadow: lunaIcon.showShadow
    
    dxtwjb's avatar
    dxtwjb committed
            property string lunarImage: lunaIcon.lunarImage
    
    samuel's avatar
    samuel committed
            property string diskColor: lunaIcon.diskColor
    
    dxtwjb's avatar
    dxtwjb committed
            property bool showGrid: lunaIcon.showGrid
            property bool showTycho: lunaIcon.showTycho
            property bool showCopernicus: lunaIcon.showCopernicus
    
    samuel's avatar
    samuel committed
            function radians(deg) {
                return deg / 180 * Math.PI;
            }
    
            function marker(radius, latitude, longitude) {
                var dy = radius * Math.sin(radians(latitude));
                var dx = radius * Math.cos(radians(latitude)) * Math.sin(radians(longitude));
                // console.log("dx: " + dx.toString());
                // console.log("dy: " + dy.toString());
                context.beginPath();
                context.strokeStyle = "#FF0000";
                context.arc(dx, -dy, 5, 0, 2 * Math.PI);
                context.moveTo(dx - 5, -dy - 5);
                context.lineTo(dx + 5, -dy + 5);
                context.moveTo(dx - 5, -dy + 5);
                context.lineTo(dx + 5, -dy - 5);
                context.stroke();
            }
    
            function grid(radius) {
                context.beginPath();
                context.strokeStyle = "#FF4040";
                context.moveTo(0, -radius);
                context.lineTo(0, radius);
                context.moveTo(-radius, 0);
                context.lineTo(radius, 0);
                context.stroke();
                context.beginPath();
                context.strokeStyle = "#40FF40";
                for (var ll = 10; ll < 65; ll += 10) {
                    var dy = radius * Math.sin(radians(ll));
                    context.moveTo(-radius, dy);
                    context.lineTo(radius, dy);
                    context.moveTo(-radius, -dy);
                    context.lineTo(radius, -dy);
                }
                context.stroke();
            }
    
            width: lunaSvgItem.width
            height: lunaSvgItem.height
            visible: false
    
            anchors.centerIn: parent
            contextType: "2d"
    
            onLatitudeChanged: requestPaint()
    
            onThetaChanged: requestPaint()
    
    dxtwjb's avatar
    dxtwjb committed
            onLunarImageChanged: requestPaint()
    
    samuel's avatar
    samuel committed
            onDiskColorChanged: requestPaint()
    
    dxtwjb's avatar
    dxtwjb committed
            onShowGridChanged: requestPaint()
            onShowTychoChanged: requestPaint()
            onShowCopernicusChanged: requestPaint()
    
    samuel's avatar
    samuel committed
            onPaint: {
                context.reset();
                context.globalAlpha = 0.9;
                context.fillStyle = '#000000';
                var ct = Math.cos(theta / 180 * Math.PI);
                var radius = ShadowCalcs.setup(Math.floor(shadow.height / 2));
                context.translate(radius, radius);
                // These two determine which side of the center meridian to draw
    
                // the two arcs enclosing the shadow area.
    
    samuel's avatar
    samuel committed
                var terminator = (theta <= 180) ? 1 : -1;
                var edge = (theta <= 180) ? -1 : 1;
    
    dxtwjb's avatar
    dxtwjb committed
                if (lunarImage === '') {
    
    samuel's avatar
    samuel committed
                    context.beginPath();
                    context.fillStyle = diskColor;
                    context.arc(0, 0, radius, 0, 2 * Math.PI);
                    context.closePath();
                    context.fill();
    
    dxtwjb's avatar
    dxtwjb committed
                }
    
    samuel's avatar
    samuel committed
                    context.beginPath();
                    context.fillStyle = '#000000';
                    context.moveTo(ShadowCalcs.get(-radius), -radius);
                    for (var z = -radius; z < radius; z++) {
                        context.lineTo(terminator * ShadowCalcs.get(z) * ct, z);
                    }
                    for (var z = radius; z > -radius; z--) {
                        context.lineTo(edge * ShadowCalcs.get(z), z);
                    }
                    context.closePath();
                    context.stroke();
                    context.fill();
                } else {
                    // Calibration markers
                    if (showGrid)
                        grid(radius);
    
                    // Tycho
                    if (showTycho)
                        marker(radius, -43, -11.5);
    
                    // Copernicus
                    if (showCopernicus)
                        marker(radius, 9.6, -20);
    
    samuel's avatar
    samuel committed
        // Shadow acts as a transparency mask
    
        OpacityMask {
            anchors.fill: lunaSvgItem
            source: lunaSvgItem
            maskSource: shadow
            invert: true
    
            rotation: latitude - 90
    
            visible: transparentShadow
        }
    
    
        // Shadow is printed on top of the moon image
        Blend {
            anchors.fill: lunaSvgItem
            source: lunaSvgItem
            foregroundSource: shadow
            rotation: latitude - 90
            mode: "normal"
            visible: !transparentShadow
        }
    
    samuel's avatar
    samuel committed