001/*
002 * This file is part of McIDAS-V
003 *
004 * Copyright 2007-2024
005 * Space Science and Engineering Center (SSEC)
006 * University of Wisconsin - Madison
007 * 1225 W. Dayton Street, Madison, WI 53706, USA
008 * https://www.ssec.wisc.edu/mcidas/
009 * 
010 * All Rights Reserved
011 * 
012 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and
013 * some McIDAS-V source code is based on IDV and VisAD source code.  
014 * 
015 * McIDAS-V is free software; you can redistribute it and/or modify
016 * it under the terms of the GNU Lesser Public License as published by
017 * the Free Software Foundation; either version 3 of the License, or
018 * (at your option) any later version.
019 * 
020 * McIDAS-V is distributed in the hope that it will be useful,
021 * but WITHOUT ANY WARRANTY; without even the implied warranty of
022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
023 * GNU Lesser Public License for more details.
024 * 
025 * You should have received a copy of the GNU Lesser Public License
026 * along with this program.  If not, see https://www.gnu.org/licenses/.
027 */
028
029package edu.wisc.ssec.mcidasv.display.hydra;
030
031import java.rmi.RemoteException;
032
033import ucar.unidata.util.LogUtil;
034
035import visad.CellImpl;
036import visad.ConstantMap;
037import visad.DataReference;
038import visad.DataReferenceImpl;
039import visad.Display;
040import visad.Gridded1DSet;
041import visad.Gridded2DSet;
042import visad.LocalDisplay;
043import visad.Real;
044import visad.RealTupleType;
045import visad.RealType;
046import visad.VisADException;
047
048import edu.wisc.ssec.mcidasv.data.hydra.GrabLineRendererJ3D;
049
050    public class DragLine extends CellImpl {
051        
052        private final String selectorId = hashCode() + "_selector";
053        private final String lineId = hashCode() + "_line";
054        private final String controlId;
055
056        private ConstantMap[] mappings = new ConstantMap[5];
057
058        private DataReference line;
059
060        private DataReference selector;
061
062        private RealType domainType;
063
064        private RealTupleType tupleType;
065
066        private LocalDisplay display;
067
068        private float[] YRANGE;
069
070        protected float lastSelectedValue;
071
072        public DragLine(Gridded1DSet domain, RealType domainType, RealType rangeType,
073            final float lastSelectedValue, LocalDisplay display, final String controlId, 
074            final ConstantMap[] color, float[] YRANGE) throws Exception 
075        {
076            if (controlId == null)
077                throw new NullPointerException("must provide a non-null control ID");
078            if (color == null)
079                throw new NullPointerException("must provide a non-null color");
080
081            this.controlId = controlId;
082            this.YRANGE = YRANGE;
083            this.display = display;
084            this.domainType = domainType;
085    
086
087            for (int i = 0; i < color.length; i++) {
088                mappings[i] = (ConstantMap)color[i].clone();
089            }
090            mappings[4] = new ConstantMap(-0.5, Display.YAxis);
091
092
093            tupleType = new RealTupleType(domainType, rangeType);
094
095            selector = new DataReferenceImpl(selectorId);
096            line = new DataReferenceImpl(lineId);
097            
098            display.addReferences(new GrabLineRendererJ3D(domain), new DataReference[] { selector }, new ConstantMap[][] { mappings });
099            display.addReference(line, cloneMappedColor(color));
100
101            addReference(selector);
102        }
103
104        private static ConstantMap[] cloneMappedColor(final ConstantMap[] color) throws Exception {
105            assert color != null && color.length >= 3 : color;
106            return new ConstantMap[] { 
107                (ConstantMap)color[0].clone(),
108                (ConstantMap)color[1].clone(),
109                (ConstantMap)color[2].clone(),
110            };
111        }
112
113        public void annihilate() {
114            try {
115                display.removeReference(selector);
116                display.removeReference(line);
117            } catch (Exception e) {
118                LogUtil.logException("DragLine.annihilate", e);
119            }
120        }
121
122        public String getControlId() {
123            return controlId;
124        }
125
126        /**
127         * Handles drag and drop updates.
128         */
129        public void doAction() throws VisADException, RemoteException {
130            setSelectedValue(getSelectedValue());
131        }
132
133        public float getSelectedValue() {
134            float val = (float)display.getDisplayRenderer().getDirectAxisValue(domainType);
135            if (Float.isNaN(val))
136                val = lastSelectedValue;
137            return val;
138        }
139
140        public void setSelectedValue(final float val) throws VisADException,
141            RemoteException 
142        {
143            // don't do work for stupid values
144            if ((Float.isNaN(val)) 
145                || (selector.getThing() != null && val == lastSelectedValue))
146                return;
147
148            line.setData(new Gridded2DSet(tupleType,
149                new float[][] { { val, val }, { YRANGE[0], YRANGE[1] } }, 2));
150
151            selector.setData(new Real(domainType, val));
152            lastSelectedValue = val;
153            this.update();
154        }
155
156        //- applications can extend and override
157        public void update() {
158
159        }
160    }