Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 2007 through 2024 David Berkman
*
* This file is part of the SmallMind Code Project.
*
* The SmallMind Code Project is free software, you can redistribute
* it and/or modify it under either, at your discretion...
*
* 1) The terms of GNU Affero General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* ...or...
*
* 2) The terms of the Apache License, Version 2.0.
*
* The SmallMind Code Project 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 or Apache License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* and the Apache License along with the SmallMind Code Project. If not, see
* or .
*
* Additional permission under the GNU Affero GPL version 3 section 7
* ------------------------------------------------------------------
* If you modify this Program, or any covered work, by linking or
* combining it with other code, such other code is not for that reason
* alone subject to any of the requirements of the GNU Affero GPL
* version 3.
*/
package org.smallmind.swing.slider;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import org.smallmind.nutsnbolts.util.WeakEventListenerList;
public class DefaultMultiThumbModel implements MultiThumbModel {
private final WeakEventListenerList listenerList = new WeakEventListenerList();
private final AdjustingDelayHandler adjustingDelayHandler;
private final LinkedList thumbList;
private int minimumValue = 0;
private int maximumValue = 100;
public DefaultMultiThumbModel () {
thumbList = new LinkedList();
new Thread(adjustingDelayHandler = new AdjustingDelayHandler(this)).start();
}
@Override
public synchronized int getMinimumValue () {
return minimumValue;
}
@Override
public synchronized void setMinimumValue (int minimumValue) {
this.minimumValue = minimumValue;
}
@Override
public synchronized int getMaximumValue () {
return maximumValue;
}
@Override
public synchronized void setMaximumValue (int maximumValue) {
this.maximumValue = maximumValue;
}
@Override
public synchronized void addThumb (int thumbValue) {
adjustingDelayHandler.purge();
thumbList.add(thumbValue);
fireThumbAdded(new ThumbEvent(this, ThumbEvent.EventType.ADD, thumbList.size() - 1, thumbValue, thumbValue, false));
}
@Override
public synchronized void removeThumb (int thumbIndex) {
int thumbValue;
adjustingDelayHandler.purge();
thumbValue = thumbList.remove(thumbIndex);
fireThumbRemoved(new ThumbEvent(this, ThumbEvent.EventType.REMOVE, thumbIndex, thumbValue, thumbValue, false));
}
@Override
public synchronized int getThumbCount () {
return thumbList.size();
}
@Override
public synchronized int[] getThumbValues () {
int[] thumbValues = new int[thumbList.size()];
int index = 0;
for (Integer thumbValue : thumbList) {
thumbValues[index++] = thumbValue;
}
Arrays.sort(thumbValues);
return thumbValues;
}
@Override
public synchronized int getThumbValue (int thumbIndex) {
return thumbList.get(thumbIndex);
}
@Override
public synchronized boolean moveThumb (int thumbIndex, int thumbValue) {
int currentValue;
currentValue = thumbList.set(thumbIndex, thumbValue);
fireThumbMoved(new ThumbEvent(this, ThumbEvent.EventType.MOVE, thumbIndex, currentValue, thumbValue, true));
adjustingDelayHandler.hold(thumbIndex, currentValue, thumbValue);
return true;
}
private synchronized void fireThumbAdded (ThumbEvent thumbEvent) {
for (ThumbListener thumbListener : listenerList) {
thumbListener.thumbAdded(thumbEvent);
}
}
private synchronized void fireThumbRemoved (ThumbEvent thumbEvent) {
for (ThumbListener thumbListener : listenerList) {
thumbListener.thumbRemoved(thumbEvent);
}
}
private synchronized void fireThumbMoved (ThumbEvent thumbEvent) {
for (ThumbListener thumbListener : listenerList) {
thumbListener.thumbMoved(thumbEvent);
}
}
@Override
public synchronized void addThumbListener (ThumbListener thumbListener) {
listenerList.addListener(thumbListener);
}
@Override
public synchronized void removeThumbListener (ThumbListener thumbListener) {
listenerList.removeListener(thumbListener);
}
private class AdjustingDelayHandler implements Runnable {
private final DefaultMultiThumbModel model;
private final CountDownLatch terminationLatch = new CountDownLatch(1);
private final CountDownLatch exitLatch = new CountDownLatch(1);
private final AtomicReference delayedMoveRef = new AtomicReference();
public AdjustingDelayHandler (DefaultMultiThumbModel model) {
this.model = model;
}
public synchronized void hold (int thumbIndex, int startingValue, int adjustingValue) {
DelayedMove delayedMove;
if ((delayedMove = delayedMoveRef.getAndSet(null)) != null) {
if (delayedMove.getThumbIndex() == thumbIndex) {
delayedMove.setAdjustingValue(adjustingValue);
delayedMove.setTimestamp(System.currentTimeMillis());
delayedMoveRef.set(delayedMove);
} else {
fireThumbMoved(new ThumbEvent(model, ThumbEvent.EventType.MOVE, delayedMove.getThumbIndex(), delayedMove.getStartingValue(), delayedMove.getAdjustingValue(), false));
delayedMoveRef.set(new DelayedMove(System.currentTimeMillis(), thumbIndex, startingValue, adjustingValue));
}
} else {
delayedMoveRef.set(new DelayedMove(System.currentTimeMillis(), thumbIndex, startingValue, adjustingValue));
}
}
public synchronized void purge () {
DelayedMove delayedMove;
if ((delayedMove = delayedMoveRef.getAndSet(null)) != null) {
fireThumbMoved(new ThumbEvent(model, ThumbEvent.EventType.MOVE, delayedMove.getThumbIndex(), delayedMove.getStartingValue(), delayedMove.getAdjustingValue(), false));
}
}
public void finish ()
throws InterruptedException {
terminationLatch.countDown();
exitLatch.await();
}
@Override
public void run () {
try {
while (!terminationLatch.await(300, TimeUnit.MILLISECONDS)) {
DelayedMove delayedMove;
if ((delayedMove = delayedMoveRef.get()) != null) {
if (System.currentTimeMillis() - delayedMove.getTimestamp() > 300) {
purge();
}
}
}
} catch (InterruptedException interruptedException) {
terminationLatch.countDown();
} finally {
exitLatch.countDown();
}
}
}
private static class DelayedMove {
private final int thumbIndex;
private final int startingValue;
private long timestamp;
private int adjustingValue;
private DelayedMove (long timestamp, int thumbIndex, int startingValue, int adjustingValue) {
this.timestamp = timestamp;
this.thumbIndex = thumbIndex;
this.startingValue = startingValue;
this.adjustingValue = adjustingValue;
}
public long getTimestamp () {
return timestamp;
}
public void setTimestamp (long timestamp) {
this.timestamp = timestamp;
}
public int getThumbIndex () {
return thumbIndex;
}
public int getStartingValue () {
return startingValue;
}
public int getAdjustingValue () {
return adjustingValue;
}
public void setAdjustingValue (int adjustingValue) {
this.adjustingValue = adjustingValue;
}
}
}