tikhomirov@148: /*
tikhomirov@425: * Copyright (c) 2011-2012 TMate Software Ltd
tikhomirov@148: *
tikhomirov@148: * This program is free software; you can redistribute it and/or modify
tikhomirov@148: * it under the terms of the GNU General Public License as published by
tikhomirov@148: * the Free Software Foundation; version 2 of the License.
tikhomirov@148: *
tikhomirov@148: * This program is distributed in the hope that it will be useful,
tikhomirov@148: * but WITHOUT ANY WARRANTY; without even the implied warranty of
tikhomirov@148: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
tikhomirov@148: * GNU General Public License for more details.
tikhomirov@148: *
tikhomirov@148: * For information on how to redistribute this software under
tikhomirov@148: * the terms of a license other than GNU General Public License
tikhomirov@148: * contact TMate Software at support@hg4j.com
tikhomirov@148: */
tikhomirov@148: package org.tmatesoft.hg.util;
tikhomirov@148:
tikhomirov@148: /**
tikhomirov@148: * Mix-in to report progress of a long-running operation
tikhomirov@148: *
tikhomirov@148: * @author Artem Tikhomirov
tikhomirov@148: * @author TMate Software Ltd.
tikhomirov@148: */
tikhomirov@148: public interface ProgressSupport {
tikhomirov@148:
tikhomirov@215: // -1 for unspecified?
tikhomirov@215: public void start(int totalUnits);
tikhomirov@425: public void worked(int units); // fraction of totalUnits from #start(int)
tikhomirov@215: // XXX have to specify whether PS implementors may expect #done regardless of job completion (i.e. in case of cancellation)
tikhomirov@148: public void done();
tikhomirov@148:
tikhomirov@148: static class Factory {
tikhomirov@148:
tikhomirov@148: /**
tikhomirov@148: * @param target object that might be capable to report progress. Can be null
tikhomirov@148: * @return support object extracted from target or an empty, no-op implementation
tikhomirov@148: */
tikhomirov@148: public static ProgressSupport get(Object target) {
tikhomirov@356: ProgressSupport ps = Adaptable.Factory.getAdapter(target, ProgressSupport.class, null);
tikhomirov@356: if (ps != null) {
tikhomirov@356: return ps;
tikhomirov@148: }
tikhomirov@148: return new ProgressSupport() {
tikhomirov@215: public void start(int totalUnits) {
tikhomirov@148: }
tikhomirov@148: public void worked(int units) {
tikhomirov@148: }
tikhomirov@148: public void done() {
tikhomirov@148: }
tikhomirov@148: };
tikhomirov@148: }
tikhomirov@148: }
tikhomirov@215:
tikhomirov@215: class Sub implements ProgressSupport {
tikhomirov@425: private int perChildWorkUnitMultiplier; // to multiply child ps units
tikhomirov@425: private int perChildWorkUnitDivisor; // to scale down to parent ps units
tikhomirov@425: private int unitsConsumed; // parent ps units consumed so far
tikhomirov@425: private int fraction = 0; // leftovers of previous not completely consumed work units
tikhomirov@215: private final ProgressSupport ps;
tikhomirov@425: private final int psUnits; // total parent ps units
tikhomirov@215:
tikhomirov@215: public Sub(ProgressSupport parent, int parentUnits) {
tikhomirov@215: if (parent == null) {
tikhomirov@215: throw new IllegalArgumentException();
tikhomirov@215: }
tikhomirov@215: ps = parent;
tikhomirov@215: psUnits = parentUnits;
tikhomirov@215: }
tikhomirov@215:
tikhomirov@215: public void start(int totalUnits) {
tikhomirov@425: // perChildWorkUnit = (psUnits*100) / totalUnits;
tikhomirov@425: perChildWorkUnitDivisor = 10 * totalUnits;
tikhomirov@425: perChildWorkUnitMultiplier = psUnits * perChildWorkUnitDivisor / totalUnits;
tikhomirov@425:
tikhomirov@215: }
tikhomirov@215:
tikhomirov@215: public void worked(int worked) {
tikhomirov@425: int x = fraction + worked * perChildWorkUnitMultiplier;
tikhomirov@425: int u = x / perChildWorkUnitDivisor;
tikhomirov@425: fraction = x % perChildWorkUnitDivisor;
tikhomirov@425: if (u > 0) {
tikhomirov@425: ps.worked(u);
tikhomirov@425: unitsConsumed += u;
tikhomirov@215: }
tikhomirov@215: }
tikhomirov@215:
tikhomirov@215: public void done() {
tikhomirov@425: ps.worked(psUnits - unitsConsumed);
tikhomirov@215: }
tikhomirov@215: }
tikhomirov@425:
tikhomirov@215: interface Target {
tikhomirov@215: T set(ProgressSupport ps);
tikhomirov@215: }
tikhomirov@148: }