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