Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/javax/swing/DefaultBoundedRangeModel.java
38829 views
/*1* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package javax.swing;2627import javax.swing.event.*;28import java.io.Serializable;29import java.util.EventListener;3031/**32* A generic implementation of BoundedRangeModel.33* <p>34* <strong>Warning:</strong>35* Serialized objects of this class will not be compatible with36* future Swing releases. The current serialization support is37* appropriate for short term storage or RMI between applications running38* the same version of Swing. As of 1.4, support for long term storage39* of all JavaBeans™40* has been added to the <code>java.beans</code> package.41* Please see {@link java.beans.XMLEncoder}.42*43* @author David Kloba44* @author Hans Muller45* @see BoundedRangeModel46*/47public class DefaultBoundedRangeModel implements BoundedRangeModel, Serializable48{49/**50* Only one <code>ChangeEvent</code> is needed per model instance since the51* event's only (read-only) state is the source property. The source52* of events generated here is always "this".53*/54protected transient ChangeEvent changeEvent = null;5556/** The listeners waiting for model changes. */57protected EventListenerList listenerList = new EventListenerList();5859private int value = 0;60private int extent = 0;61private int min = 0;62private int max = 100;63private boolean isAdjusting = false;646566/**67* Initializes all of the properties with default values.68* Those values are:69* <ul>70* <li><code>value</code> = 071* <li><code>extent</code> = 072* <li><code>minimum</code> = 073* <li><code>maximum</code> = 10074* <li><code>adjusting</code> = false75* </ul>76*/77public DefaultBoundedRangeModel() {78}798081/**82* Initializes value, extent, minimum and maximum. Adjusting is false.83* Throws an <code>IllegalArgumentException</code> if the following84* constraints aren't satisfied:85* <pre>86* min <= value <= value+extent <= max87* </pre>88*/89public DefaultBoundedRangeModel(int value, int extent, int min, int max)90{91if ((max >= min) &&92(value >= min) &&93((value + extent) >= value) &&94((value + extent) <= max)) {95this.value = value;96this.extent = extent;97this.min = min;98this.max = max;99}100else {101throw new IllegalArgumentException("invalid range properties");102}103}104105106/**107* Returns the model's current value.108* @return the model's current value109* @see #setValue110* @see BoundedRangeModel#getValue111*/112public int getValue() {113return value;114}115116117/**118* Returns the model's extent.119* @return the model's extent120* @see #setExtent121* @see BoundedRangeModel#getExtent122*/123public int getExtent() {124return extent;125}126127128/**129* Returns the model's minimum.130* @return the model's minimum131* @see #setMinimum132* @see BoundedRangeModel#getMinimum133*/134public int getMinimum() {135return min;136}137138139/**140* Returns the model's maximum.141* @return the model's maximum142* @see #setMaximum143* @see BoundedRangeModel#getMaximum144*/145public int getMaximum() {146return max;147}148149150/**151* Sets the current value of the model. For a slider, that152* determines where the knob appears. Ensures that the new153* value, <I>n</I> falls within the model's constraints:154* <pre>155* minimum <= value <= value+extent <= maximum156* </pre>157*158* @see BoundedRangeModel#setValue159*/160public void setValue(int n) {161n = Math.min(n, Integer.MAX_VALUE - extent);162163int newValue = Math.max(n, min);164if (newValue + extent > max) {165newValue = max - extent;166}167setRangeProperties(newValue, extent, min, max, isAdjusting);168}169170171/**172* Sets the extent to <I>n</I> after ensuring that <I>n</I>173* is greater than or equal to zero and falls within the model's174* constraints:175* <pre>176* minimum <= value <= value+extent <= maximum177* </pre>178* @see BoundedRangeModel#setExtent179*/180public void setExtent(int n) {181int newExtent = Math.max(0, n);182if(value + newExtent > max) {183newExtent = max - value;184}185setRangeProperties(value, newExtent, min, max, isAdjusting);186}187188189/**190* Sets the minimum to <I>n</I> after ensuring that <I>n</I>191* that the other three properties obey the model's constraints:192* <pre>193* minimum <= value <= value+extent <= maximum194* </pre>195* @see #getMinimum196* @see BoundedRangeModel#setMinimum197*/198public void setMinimum(int n) {199int newMax = Math.max(n, max);200int newValue = Math.max(n, value);201int newExtent = Math.min(newMax - newValue, extent);202setRangeProperties(newValue, newExtent, n, newMax, isAdjusting);203}204205206/**207* Sets the maximum to <I>n</I> after ensuring that <I>n</I>208* that the other three properties obey the model's constraints:209* <pre>210* minimum <= value <= value+extent <= maximum211* </pre>212* @see BoundedRangeModel#setMaximum213*/214public void setMaximum(int n) {215int newMin = Math.min(n, min);216int newExtent = Math.min(n - newMin, extent);217int newValue = Math.min(n - newExtent, value);218setRangeProperties(newValue, newExtent, newMin, n, isAdjusting);219}220221222/**223* Sets the <code>valueIsAdjusting</code> property.224*225* @see #getValueIsAdjusting226* @see #setValue227* @see BoundedRangeModel#setValueIsAdjusting228*/229public void setValueIsAdjusting(boolean b) {230setRangeProperties(value, extent, min, max, b);231}232233234/**235* Returns true if the value is in the process of changing236* as a result of actions being taken by the user.237*238* @return the value of the <code>valueIsAdjusting</code> property239* @see #setValue240* @see BoundedRangeModel#getValueIsAdjusting241*/242public boolean getValueIsAdjusting() {243return isAdjusting;244}245246247/**248* Sets all of the <code>BoundedRangeModel</code> properties after forcing249* the arguments to obey the usual constraints:250* <pre>251* minimum <= value <= value+extent <= maximum252* </pre>253* <p>254* At most, one <code>ChangeEvent</code> is generated.255*256* @see BoundedRangeModel#setRangeProperties257* @see #setValue258* @see #setExtent259* @see #setMinimum260* @see #setMaximum261* @see #setValueIsAdjusting262*/263public void setRangeProperties(int newValue, int newExtent, int newMin, int newMax, boolean adjusting)264{265if (newMin > newMax) {266newMin = newMax;267}268if (newValue > newMax) {269newMax = newValue;270}271if (newValue < newMin) {272newMin = newValue;273}274275/* Convert the addends to long so that extent can be276* Integer.MAX_VALUE without rolling over the sum.277* A JCK test covers this, see bug 4097718.278*/279if (((long)newExtent + (long)newValue) > newMax) {280newExtent = newMax - newValue;281}282283if (newExtent < 0) {284newExtent = 0;285}286287boolean isChange =288(newValue != value) ||289(newExtent != extent) ||290(newMin != min) ||291(newMax != max) ||292(adjusting != isAdjusting);293294if (isChange) {295value = newValue;296extent = newExtent;297min = newMin;298max = newMax;299isAdjusting = adjusting;300301fireStateChanged();302}303}304305306/**307* Adds a <code>ChangeListener</code>. The change listeners are run each308* time any one of the Bounded Range model properties changes.309*310* @param l the ChangeListener to add311* @see #removeChangeListener312* @see BoundedRangeModel#addChangeListener313*/314public void addChangeListener(ChangeListener l) {315listenerList.add(ChangeListener.class, l);316}317318319/**320* Removes a <code>ChangeListener</code>.321*322* @param l the <code>ChangeListener</code> to remove323* @see #addChangeListener324* @see BoundedRangeModel#removeChangeListener325*/326public void removeChangeListener(ChangeListener l) {327listenerList.remove(ChangeListener.class, l);328}329330331/**332* Returns an array of all the change listeners333* registered on this <code>DefaultBoundedRangeModel</code>.334*335* @return all of this model's <code>ChangeListener</code>s336* or an empty337* array if no change listeners are currently registered338*339* @see #addChangeListener340* @see #removeChangeListener341*342* @since 1.4343*/344public ChangeListener[] getChangeListeners() {345return listenerList.getListeners(ChangeListener.class);346}347348349/**350* Runs each <code>ChangeListener</code>'s <code>stateChanged</code> method.351*352* @see #setRangeProperties353* @see EventListenerList354*/355protected void fireStateChanged()356{357Object[] listeners = listenerList.getListenerList();358for (int i = listeners.length - 2; i >= 0; i -=2 ) {359if (listeners[i] == ChangeListener.class) {360if (changeEvent == null) {361changeEvent = new ChangeEvent(this);362}363((ChangeListener)listeners[i+1]).stateChanged(changeEvent);364}365}366}367368369/**370* Returns a string that displays all of the371* <code>BoundedRangeModel</code> properties.372*/373public String toString() {374String modelString =375"value=" + getValue() + ", " +376"extent=" + getExtent() + ", " +377"min=" + getMinimum() + ", " +378"max=" + getMaximum() + ", " +379"adj=" + getValueIsAdjusting();380381return getClass().getName() + "[" + modelString + "]";382}383384/**385* Returns an array of all the objects currently registered as386* <code><em>Foo</em>Listener</code>s387* upon this model.388* <code><em>Foo</em>Listener</code>s389* are registered using the <code>add<em>Foo</em>Listener</code> method.390* <p>391* You can specify the <code>listenerType</code> argument392* with a class literal, such as <code><em>Foo</em>Listener.class</code>.393* For example, you can query a <code>DefaultBoundedRangeModel</code>394* instance <code>m</code>395* for its change listeners396* with the following code:397*398* <pre>ChangeListener[] cls = (ChangeListener[])(m.getListeners(ChangeListener.class));</pre>399*400* If no such listeners exist,401* this method returns an empty array.402*403* @param listenerType the type of listeners requested;404* this parameter should specify an interface405* that descends from <code>java.util.EventListener</code>406* @return an array of all objects registered as407* <code><em>Foo</em>Listener</code>s408* on this model,409* or an empty array if no such410* listeners have been added411* @exception ClassCastException if <code>listenerType</code> doesn't412* specify a class or interface that implements413* <code>java.util.EventListener</code>414*415* @see #getChangeListeners416*417* @since 1.3418*/419public <T extends EventListener> T[] getListeners(Class<T> listenerType) {420return listenerList.getListeners(listenerType);421}422}423424425