/*
* Copyright (C) 2010 Brockmann Consult GmbH (info@brockmann-consult.de)
*
* 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/
*/
package org.esa.snap.rcp.pixelinfo;
import org.esa.snap.ui.product.ProductSceneView;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
/**
* @author Marco Zuehlke
* @version $Revision$ $Date$
* @since BEAM 4.5.2
*/
public class PixelInfoUpdateService {
private final PixelInfoViewModelUpdater modelUpdater;
private final ScheduledExecutorService scheduledExecutorService;
private ScheduledFuture<?> updaterFuture;
private PixelInfoState state;
private boolean needUpdate;
private int numUnchangedStates;
private Runnable updaterRunnable;
public PixelInfoUpdateService(PixelInfoViewModelUpdater modelUpdater) {
this.modelUpdater = modelUpdater;
this.scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
state = PixelInfoState.INVALID;
updaterRunnable = new UpdaterRunnable();
}
synchronized void updateState(ProductSceneView view, int pixelX, int pixelY, int level, boolean pixelPosValid) {
if (!state.equals(view, pixelX, pixelY, level, pixelPosValid)) {
state = new PixelInfoState(view, pixelX, pixelY, level, pixelPosValid);
needUpdate = true;
assertTimerStarted();
}
}
synchronized void requestUpdate() {
if (state == PixelInfoState.INVALID) {
return;
}
needUpdate = true;
assertTimerStarted();
}
synchronized void clearState() {
state = PixelInfoState.INVALID;
}
private void assertTimerStarted() {
if (updaterFuture == null) {
updaterFuture = scheduledExecutorService.scheduleAtFixedRate(updaterRunnable, 100, 100, TimeUnit.MILLISECONDS);
}
}
private synchronized void stopTimer() {
if (updaterFuture != null) {
updaterFuture.cancel(true);
updaterFuture = null;
}
clearState();
}
private class UpdaterRunnable implements Runnable {
@Override
public void run() {
if (state == PixelInfoState.INVALID) {
return;
}
if (needUpdate) {
numUnchangedStates = 0;
needUpdate = false;
try {
modelUpdater.update(state);
} catch (Throwable ignored) {
}
} else {
numUnchangedStates++;
if (numUnchangedStates > 100) {
stopTimer();
}
}
}
}
}