tikhomirov@148: /* tikhomirov@148: * Copyright (c) 2011 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@148: public void worked(int units); 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@215: private final ProgressSupport ps; tikhomirov@215: private int total; tikhomirov@215: private int units; tikhomirov@215: private int psUnits; 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@215: total = totalUnits; tikhomirov@215: } tikhomirov@215: tikhomirov@215: public void worked(int worked) { tikhomirov@215: // FIXME fine-grained subprogress report. now only report at about 50% tikhomirov@215: if (psUnits > 1 && units < total/2 && units+worked > total/2) { tikhomirov@215: ps.worked(psUnits/2); tikhomirov@215: psUnits -= psUnits/2; tikhomirov@215: } tikhomirov@215: units += worked; tikhomirov@215: } tikhomirov@215: tikhomirov@215: public void done() { tikhomirov@215: ps.worked(psUnits); tikhomirov@215: } tikhomirov@215: } tikhomirov@215: tikhomirov@215: interface Target { tikhomirov@215: T set(ProgressSupport ps); tikhomirov@215: } tikhomirov@148: }