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: }