001package jmri;
002
003/**
004 * Represent a single visible Variable Light on the physical layout.
005 * <p>
006 * Each Light may have one or more control mechanisms. Control mechanism types
007 * are defined here. If a Light has any controls, the information is contained
008 * in LightControl objects, which are referenced via that Light.
009 * <p>
010 * Lights have a state and an intensity.
011 * <p>
012 * The intensity of the hardware output is represented by the range from 0.0 to
013 * 1.0, with 1.0 being brightest.
014 * <p>
015 * The primary states are:
016 * <ul>
017 * <li>ON, corresponding to maximum intensity
018 * <li>INTERMEDIATE, some value between maximum and minimum
019 * <li>OFF, corresponding to minimum intensity
020 * </ul>
021 * The underlying hardware may provide just the ON/OFF two levels, or have a
022 * semi-continuous intensity setting with some number of steps.
023 * <p>
024 * The light has a TargetIntensity property which can be set directly. In
025 * addition, it has a CurrentIntensity property which may differ from
026 * TargetIntensity while the Light is being moved from one intensity to another.
027 * <p>
028 * Intensity is limited by MinIntensity and MaxIntensity parameters. Setting the
029 * state to ON sets the TargetIntensity to MinIntensity, and to OFF sets the
030 * TargetIntensity to MaxIntensity. Attempting to directly set the
031 * TargetIntensity outside the values of MinIntensity and MaxIntensity
032 * (inclusive) will result in the TargetIntensity being set to the relevant
033 * limit.
034 * <p>
035 * Because the actual light hardware has only finite resolution, the intensity
036 * value is mapped to the nearest setting. For example, in the special case of a
037 * two-state (on/off) Light, setting a TargetIntensity of more than 0.5 will
038 * turn the Light on, less than 0.5 will turn the light off.
039 * <p>
040 * Specific implementations will describe how the settings map to the particular
041 * hardware commands.
042 * <p>
043 * The transition rate is absolute; the intensity changes at a constant rate
044 * regardless of whether the change is a big one or a small one.
045 *
046 * <hr>
047 * This file is part of JMRI.
048 * <p>
049 * JMRI is free software; you can redistribute it and/or modify it under the
050 * terms of version 2 of the GNU General Public License as published by the Free
051 * Software Foundation. See the "COPYING" file for a copy of this license.
052 * <p>
053 * JMRI is distributed in the hope that it will be useful, but WITHOUT ANY
054 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
055 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
056 *
057 * @author Dave Duchamp Copyright (C) 2004, 2010
058 * @author Ken Cameron Copyright (C) 2008
059 * @author Bob Jacobsen Copyright (C) 2008
060 */
061public interface VariableLight extends Light, AnalogIO {
062
063    /** {@inheritDoc} */
064    @Override
065    @InvokeOnLayoutThread
066    default void requestUpdateFromLayout() {
067        // Do nothing
068    }
069
070    /** {@inheritDoc} */
071    @Override
072    default boolean isConsistentState() {
073        return (getState() == DigitalIO.ON)
074                || (getState() == DigitalIO.OFF)
075                || (getState() == INTERMEDIATE);
076    }
077    
078    /** {@inheritDoc} */
079    @Override
080    default boolean isConsistentValue() {
081        // Assume that the value is consistent if the state is consistent.
082        return isConsistentState();
083    }
084    
085    /**
086     * Set the intended new intensity value for the Light. If transitions are in
087     * use, they will be applied.
088     * <p>
089     * Bound property between 0 and 1.
090     * <p>
091     * A value of 0.0 corresponds to full off, and a value of 1.0 corresponds to
092     * full on.
093     * <p>
094     * Attempting to set a value below the MinIntensity property value will
095     * result in MinIntensity being set. Similarly, setting a value above
096     * MaxIntensity will result in MaxINtensity being set.
097     * <p>
098     * Setting the intensity to the value of the MinIntensity property will
099     * result in the Light going to the OFF state at the end of the transition.
100     * Similarly, setting the intensity to the MaxIntensity value will result in
101     * the Light going to the ON state at the end of the transition.
102     * <p>
103     * All others result in the INTERMEDIATE state.
104     * <p>
105     * Light implementations with isIntensityVariable false may not have their
106     * TargetIntensity set to values between MinIntensity and MaxIntensity,
107     * which would result in the INTERMEDIATE state, as that is invalid for
108     * them.
109     * <p>
110     * If a non-zero value is set in the transitionTime property, the state will
111     * be one of TRANSITIONTOFULLON, TRANSITIONHIGHER, TRANSITIONLOWER or
112     * TRANSITIONTOFULLOFF until the transition is complete.
113     *
114     * @param intensity the desired brightness
115     * @throws IllegalArgumentException when intensity is less than 0.0 or more
116     *                                  than 1.0
117     * @throws IllegalArgumentException if isIntensityVariable is false and the
118     *                                  new value is between MaxIntensity and
119     *                                  MinIntensity
120     */
121    @InvokeOnLayoutThread
122    void setTargetIntensity(double intensity);
123
124    /**
125     * Get the current intensity value. If the Light is currently transitioning,
126     * this may be either an intermediate or final value.
127     * <p>
128     * A value of 0.0 corresponds to full off, and a value of 1.0 corresponds to
129     * full on.
130     *
131     * @return the current brightness
132     */
133    double getCurrentIntensity();
134
135    /**
136     * Get the target intensity value for the current transition, if any. If the
137     * Light is not currently transitioning, this is the current intensity
138     * value.
139     * <p>
140     * A value of 0.0 corresponds to full off, and a value of 1.0 corresponds to
141     * full on.
142     * <p>
143     * Bound property
144     *
145     * @return the desired brightness
146     */
147    double getTargetIntensity();
148
149    /**
150     * Set the value of the maxIntensity property.
151     * <p>
152     * Bound property between 0 and 1.
153     * <p>
154     * A value of 0.0 corresponds to full off, and a value of 1.0 corresponds to
155     * full on.
156     *
157     * @param intensity the maximum brightness
158     * @throws IllegalArgumentException when intensity is less than 0.0 or more
159     *                                  than 1.0
160     * @throws IllegalArgumentException when intensity is not greater than the
161     *                                  current value of the minIntensity
162     *                                  property
163     */
164    @InvokeOnLayoutThread
165    void setMaxIntensity(double intensity);
166
167    /**
168     * Get the current value of the maxIntensity property.
169     * <p>
170     * A value of 0.0 corresponds to full off, and a value of 1.0 corresponds to
171     * full on.
172     *
173     * @return the maximum brightness
174     */
175    double getMaxIntensity();
176
177    /**
178     * Set the value of the minIntensity property.
179     * <p>
180     * Bound property between 0 and 1.
181     * <p>
182     * A value of 0.0 corresponds to full off, and a value of 1.0 corresponds to
183     * full on.
184     *
185     * @param intensity the minimum brightness
186     * @throws IllegalArgumentException when intensity is less than 0.0 or more
187     *                                  than 1.0
188     * @throws IllegalArgumentException when intensity is not less than the
189     *                                  current value of the maxIntensity
190     *                                  property
191     */
192    @InvokeOnLayoutThread
193    void setMinIntensity(double intensity);
194
195    /**
196     * Get the current value of the minIntensity property.
197     * <p>
198     * A value of 0.0 corresponds to full off, and a value of 1.0 corresponds to
199     * full on.
200     *
201     * @return the minimum brightness
202     */
203    double getMinIntensity();
204
205    /**
206     * Can the Light change its intensity setting slowly?
207     * <p>
208     * If true, this Light supports a non-zero value of the transitionTime
209     * property, which controls how long the Light will take to change from one
210     * intensity level to another.
211     * <p>
212     * Unbound property
213     *
214     * @return true if brightness can fade between two states; false otherwise
215     */
216    boolean isTransitionAvailable();
217
218    /**
219     * Set the fast-clock duration for a transition from full ON to full OFF or
220     * vice-versa.
221     * <p>
222     * Note there is no guarantee of how this scales when other changes in
223     * intensity take place. In particular, some Light implementations will
224     * change at a constant fraction per fastclock minute and some will take a
225     * fixed duration regardless of the size of the intensity change.
226     * <p>
227     * Bound property
228     * @param minutes time to fade
229     * @throws IllegalArgumentException if isTransitionAvailable() is false and
230     *                                  minutes is not 0.0
231     * @throws IllegalArgumentException if minutes is negative
232     */
233    @InvokeOnLayoutThread
234    void setTransitionTime(double minutes);
235
236    /**
237     * Get the number of fastclock minutes taken by a transition from full ON to
238     * full OFF or vice versa.
239     *
240     * @return 0.0 if the output intensity transition is instantaneous
241     */
242    double getTransitionTime();
243
244    /**
245     * Convenience method for checking if the intensity of the light is
246     * currently changing due to a transition.
247     * <p>
248     * Bound property so that listeners can conveniently learn when the
249     * transition is over.
250     *
251     * @return true if light is between two states; false otherwise
252     */
253    boolean isTransitioning();
254
255}