001package co.codewizards.cloudstore.core.progress; 002 003/** 004 * This is the adaption of the Eclipse SubProgressMonitor to {@link ProgressMonitor}. 005 * The whole class is a copy of the Eclipse SubProgressMonitor. 006 * <br><br> 007 * A progress monitor that uses a given amount of work ticks 008 * from a parent monitor. It can be used as follows: 009 * <pre> 010 * try { 011 * pm.beginTask("Main Task", 100); 012 * doSomeWork(pm, 30); 013 * SubProgressMonitor subMonitor= new SubProgressMonitor(pm, 40); 014 * try { 015 * subMonitor.beginTask("", 300); 016 * doSomeWork(subMonitor, 300); 017 * } finally { 018 * subMonitor.done(); 019 * } 020 * doSomeWork(pm, 30); 021 * } finally { 022 * pm.done(); 023 * } 024 * </pre> 025 * <p> 026 * This class can be used without OSGi running. 027 * </p><p> 028 * This class may be instantiated or subclassed by clients. 029 * </p> 030 * 031 * @author Marius Heinzmann [marius<at>NightLabs<dot>de] 032 */ 033public class SubProgressMonitor extends ProgressMonitorDelegator { 034 035 /** 036 * Style constant indicating that calls to <code>subTask</code> 037 * should not have any effect. 038 * 039 * @see #SubProgressMonitor(IProgressMonitor,int,int) 040 */ 041 public static final int SUPPRESS_SUBTASK_LABEL = 1 << 1; 042 /** 043 * Style constant indicating that the main task label 044 * should be prepended to the subtask label. 045 * 046 * @see #SubProgressMonitor(IProgressMonitor,int,int) 047 */ 048 public static final int PREPEND_MAIN_LABEL_TO_SUBTASK = 1 << 2; 049 050 private int parentTicks = 0; 051 private double sentToParent = 0.0; 052 private double scale = 0.0; 053 private int nestedBeginTasks = 0; 054 private boolean usedUp = false; 055 private boolean hasSubTask = false; 056 private int style; 057 private String mainTaskLabel; 058 059 /** 060 * Creates a new sub-progress monitor for the given monitor. The sub 061 * progress monitor uses the given number of work ticks from its 062 * parent monitor. 063 * 064 * @param monitor the parent progress monitor 065 * @param ticks the number of work ticks allocated from the 066 * parent monitor 067 */ 068 public SubProgressMonitor(ProgressMonitor wrappedMonitor, int ticks) { 069 this(wrappedMonitor, ticks, 0); 070 } 071 072 /** 073 * Creates a new sub-progress monitor for the given monitor. The sub 074 * progress monitor uses the given number of work ticks from its 075 * parent monitor. 076 * 077 * @param monitor the parent progress monitor 078 * @param ticks the number of work ticks allocated from the 079 * parent monitor 080 * @param style one of 081 * <ul> 082 * <li> <code>SUPPRESS_SUBTASK_LABEL</code> </li> 083 * <li> <code>PREPEND_MAIN_LABEL_TO_SUBTASK</code> </li> 084 * </ul> 085 * @see #SUPPRESS_SUBTASK_LABEL 086 * @see #PREPEND_MAIN_LABEL_TO_SUBTASK 087 */ 088 public SubProgressMonitor(ProgressMonitor wrappedMonitor, int ticks, int style) { 089 super(wrappedMonitor); 090 this.parentTicks = ticks; 091 this.style = style; 092 } 093 094 /* (Intentionally not javadoc'd) 095 * Implements the method <code>IProgressMonitor.beginTask</code>. 096 * 097 * Starts a new main task. Since this progress monitor is a sub 098 * progress monitor, the given name will NOT be used to update 099 * the progress bar's main task label. That means the given 100 * string will be ignored. If style <code>PREPEND_MAIN_LABEL_TO_SUBTASK 101 * <code> is specified, then the given string will be prepended to 102 * every string passed to <code>subTask(String)</code>. 103 */ 104 @Override 105 public synchronized void beginTask(String name, int totalWork) { 106 nestedBeginTasks++; 107 // Ignore nested begin task calls. 108 if (nestedBeginTasks > 1) { 109 return; 110 } 111 // be safe: if the argument would cause math errors (zero or 112 // negative), just use 0 as the scale. This disables progress for 113 // this submonitor. 114 scale = totalWork <= 0 ? 0 : (double) parentTicks / (double) totalWork; 115 if ((style & PREPEND_MAIN_LABEL_TO_SUBTASK) != 0) { 116 mainTaskLabel = name; 117 } 118 } 119 120 @Override 121 public synchronized void done() { 122 // Ignore if more done calls than beginTask calls or if we are still 123 // in some nested beginTasks 124 if (nestedBeginTasks == 0 || --nestedBeginTasks > 0) 125 return; 126 // Send any remaining ticks and clear out the subtask text 127 double remaining = parentTicks - sentToParent; 128 if (remaining > 0) 129 super.internalWorked(remaining); 130 //clear the sub task if there was one 131 if (hasSubTask) 132 subTask(""); 133 sentToParent = 0; 134 } 135 136 @Override 137 public synchronized void internalWorked(double work) { 138 if (usedUp || nestedBeginTasks != 1) { 139 return; 140 } 141 142 double realWork = scale * work; 143 super.internalWorked(realWork); 144 sentToParent += realWork; 145 if (sentToParent >= parentTicks) { 146 usedUp = true; 147 } 148 } 149 150 @Override 151 public synchronized void subTask(String name) { 152 if ((style & SUPPRESS_SUBTASK_LABEL) != 0) { 153 return; 154 } 155 hasSubTask = true; 156 String label = name; 157 if ((style & PREPEND_MAIN_LABEL_TO_SUBTASK) != 0 && mainTaskLabel != null && mainTaskLabel.length() > 0) { 158 label = mainTaskLabel + ' ' + label; 159 } 160 super.subTask(label); 161 } 162 163 @Override 164 public void worked(int work) { 165 internalWorked(work); 166 } 167 168}