? progress/src/org/netbeans/spi ? progressui/test Index: progress/manifest.mf =================================================================== RCS file: /cvs/core/progress/manifest.mf,v retrieving revision 1.10 diff -r1.10 manifest.mf 5a6 > OpenIDE-Module-Needs: org.netbeans.spi.progress.ProgressUIWorkerProvider Index: progress/api/doc/changes/apichanges.xml =================================================================== RCS file: /cvs/core/progress/api/doc/changes/apichanges.xml,v retrieving revision 1.7 diff -r1.7 apichanges.xml 86a87,100 > Split APi and implementation of progress compoennt > > > > > >

> Split the implementation and APIs of progress component. >

>
> > > > Index: progress/nbproject/project.properties =================================================================== RCS file: /cvs/core/progress/nbproject/project.properties,v retrieving revision 1.9 diff -r1.9 project.properties 21c21 < spec.version.base=1.6.0 --- > spec.version.base=1.7.0 Index: progress/nbproject/project.xml =================================================================== RCS file: /cvs/core/progress/nbproject/project.xml,v retrieving revision 1.9 diff -r1.9 project.xml 34c34 < --- > 42,57d41 < < org.openide.dialogs < < < < 6.2 < < < < org.openide.windows < < < < 6.2 < < 58a43,52 > > > unit > > org.netbeans.modules.progress.ui > > > > > Index: progress/src/org/netbeans/api/progress/ProgressHandle.java =================================================================== RCS file: /cvs/core/progress/src/org/netbeans/api/progress/ProgressHandle.java,v retrieving revision 1.6 diff -r1.6 ProgressHandle.java 29c29 < import org.netbeans.progress.module.InternalHandle; --- > import org.netbeans.progress.spi.InternalHandle; Index: progress/src/org/netbeans/api/progress/ProgressHandleFactory.java =================================================================== RCS file: /cvs/core/progress/src/org/netbeans/api/progress/ProgressHandleFactory.java,v retrieving revision 1.2 diff -r1.2 ProgressHandleFactory.java 24c24 < import org.netbeans.progress.module.InternalHandle; --- > import org.netbeans.progress.spi.InternalHandle; Index: progress/src/org/netbeans/api/progress/aggregate/AggregateProgressFactory.java =================================================================== RCS file: /cvs/core/progress/src/org/netbeans/api/progress/aggregate/AggregateProgressFactory.java,v retrieving revision 1.5 diff -r1.5 AggregateProgressFactory.java 24c24 < import org.netbeans.progress.module.InternalHandle; --- > import org.netbeans.progress.spi.InternalHandle; Index: progress/src/org/netbeans/progress/module/Controller.java =================================================================== RCS file: /cvs/core/progress/src/org/netbeans/progress/module/Controller.java,v retrieving revision 1.17 diff -r1.17 Controller.java 37,38c37,43 < import org.netbeans.progress.module.ui.StatusLineComponent; < import org.openide.windows.WindowManager; --- > import org.netbeans.progress.spi.InternalHandle; > import org.netbeans.progress.spi.ProgressEvent; > import org.netbeans.progress.spi.ProgressUIWorker; > import org.netbeans.progress.spi.ProgressUIWorkerProvider; > import org.netbeans.progress.spi.ProgressUIWorkerWithModel; > import org.netbeans.progress.spi.TaskModel; > import org.openide.util.Lookup; 75c80,82 < StatusLineComponent component = new StatusLineComponent(); --- > ProgressUIWorkerProvider prov = (ProgressUIWorkerProvider)Lookup.getDefault().lookup(ProgressUIWorkerProvider.class); > assert prov != null; > ProgressUIWorkerWithModel component = prov.getDefaultWorker(); 94c101 < void start(InternalHandle handle) { --- > public void start(InternalHandle handle) { 104c111 < void finish(InternalHandle handle) { --- > public void finish(InternalHandle handle) { 109c116 < void toIndeterminate(InternalHandle handle) { --- > public void toIndeterminate(InternalHandle handle) { 114c121 < void toDeterminate(InternalHandle handle) { --- > public void toDeterminate(InternalHandle handle) { 119c126 < void progress(InternalHandle handle, String msg, --- > public void progress(InternalHandle handle, String msg, 125c132 < ProgressEvent snapshot(InternalHandle handle, String msg, --- > public ProgressEvent snapshot(InternalHandle handle, String msg, 131c138 < void explicitSelection(InternalHandle handle, int units, int percentage, long estimate) { --- > public void explicitSelection(InternalHandle handle, int units, int percentage, long estimate) { 143c150 < void displayNameChange(InternalHandle handle, int units, int percentage, long estimate, String display) { --- > public void displayNameChange(InternalHandle handle, int units, int percentage, long estimate, String display) { Index: progress/src/org/netbeans/progress/module/InternalHandle.java =================================================================== RCS file: progress/src/org/netbeans/progress/module/InternalHandle.java diff -N progress/src/org/netbeans/progress/module/InternalHandle.java 1,344d0 < /* < * The contents of this file are subject to the terms of the Common Development < * and Distribution License (the License). You may not use this file except in < * compliance with the License. < * < * You can obtain a copy of the License at http://www.netbeans.org/cddl.html < * or http://www.netbeans.org/cddl.txt. < * < * When distributing Covered Code, include this CDDL Header Notice in each file < * and include the License file at http://www.netbeans.org/cddl.txt. < * If applicable, add the following below the CDDL Header, with the fields < * enclosed by brackets [] replaced by your own identifying information: < * "Portions Copyrighted [year] [name of copyright owner]" < * < * The Original Software is NetBeans. The Initial Developer of the Original < * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun < * Microsystems, Inc. All Rights Reserved. < */ < < < package org.netbeans.progress.module; < < import java.awt.event.ActionEvent; < import java.util.ArrayList; < import java.util.Collection; < import java.util.Collections; < import java.util.List; < import java.util.logging.Level; < import java.util.logging.Logger; < import javax.swing.Action; < import javax.swing.JComponent; < import javax.swing.JProgressBar; < import javax.swing.SwingUtilities; < import org.netbeans.progress.module.ui.NbProgressBar; < import org.openide.util.Cancellable; < < /** < * Instances provided by the ProgressHandleFactory allow the users of the API to < * notify the progress bar UI about changes in the state of the running task. < * @author Milos Kleint (mkleint@netbeans.org) < */ < public final class InternalHandle { < < private String displayName; < private boolean allowCancel; < private boolean allowBackground; < private boolean customPlaced = false; < private int state; < private int totalUnits; < private int currentUnit; < private long initialEstimate; < private long timeStarted; < private long timeLastProgress; < private String lastMessage; < private final Cancellable cancelable; < private final Action viewAction; < private final boolean userInitiated; < private int initialDelay = Controller.INITIAL_DELAY; < private Controller controller; < < public static final int STATE_INITIALIZED = 0; < public static final int STATE_RUNNING = 1; < public static final int STATE_FINISHED = 2; < public static final int STATE_REQUEST_STOP = 3; < < public static final int NO_INCREASE = -2; < < < < /** Creates a new instance of ProgressHandle */ < public InternalHandle(String displayName, < Cancellable cancel, < boolean userInitiated, < Action view) { < this.displayName = displayName; < this.userInitiated = userInitiated; < state = STATE_INITIALIZED; < totalUnits = 0; < lastMessage = null; < cancelable = cancel; < viewAction = view; < } < < public String getDisplayName() { < return displayName; < } < < /** < * XXX - called from UI, threading < */ < public synchronized int getState() { < return state; < } < < public boolean isAllowCancel() { < return cancelable != null && !isCustomPlaced(); < } < < public boolean isAllowView() { < return viewAction != null && !isCustomPlaced(); < } < < < public boolean isCustomPlaced() { < return customPlaced; < } < < public boolean isUserInitialized() { < return userInitiated; < } < < private int getCurrentUnit() { < return currentUnit; < } < < public int getTotalUnits() { < return totalUnits; < } < < public void setInitialDelay(int millis) { < if (state != STATE_INITIALIZED) { < Logger.getAnonymousLogger().warning("Setting ProgressHandle.setInitialDelay() after the task is started has no effect"); //NOI18N < return; < } < initialDelay = millis; < } < < public int getInitialDelay() { < return initialDelay; < } < < public synchronized void toIndeterminate() { < if (state != STATE_RUNNING && state != STATE_REQUEST_STOP) { < assert false : "cannot switch to indeterminate mode when not running"; < } < totalUnits = 0; < currentUnit = 0; < initialEstimate = -1; < timeLastProgress = System.currentTimeMillis(); < controller.toIndeterminate(this); < } < < public synchronized void toDeterminate(int workunits, long estimate) { < if (state != STATE_RUNNING && state != STATE_REQUEST_STOP) { < assert false : "cannot switch to determinate mode when not running"; < } < if (workunits < 0) { < throw new IllegalArgumentException("number of workunits cannot be negative"); < } < totalUnits = workunits; < currentUnit = 0; < initialEstimate = estimate; < timeLastProgress = System.currentTimeMillis(); < controller.toDeterminate(this); < } < < /** < * start the progress indication for a task with known number of steps and known < * time estimate for completing the task. < * < * @param message < * @param workunits < * @param estimate estimated time to process the task in seconds < */ < public synchronized void start(String message, int workunits, long estimate) { < if (state != STATE_INITIALIZED) { < throw new IllegalStateException("Cannot call start twice on a handle"); < } < if (workunits < 0) { < throw new IllegalArgumentException("number of workunits cannot be negative"); < } < totalUnits = workunits; < currentUnit = 0; < if (message != null) { < lastMessage = message; < } < state = STATE_RUNNING; < initialEstimate = estimate; < timeStarted = System.currentTimeMillis(); < timeLastProgress = timeStarted; < < if (! customPlaced) { < controller = Controller.getDefault(); < } < < controller.start(this); < } < < /** < * finish the task, remove the task's component from the progress bar UI. < */ < public synchronized void finish() { < if (state == STATE_INITIALIZED) { < throw new IllegalStateException("Cannot finish not a started task"); < } < if (state == STATE_FINISHED) { < return; < } < state = STATE_FINISHED; < currentUnit = totalUnits; < < controller.finish(this); < } < < < /** < * < * @param message < * @param workunit < */ < public synchronized void progress(String message, int workunit) { < if (state != STATE_RUNNING && state != STATE_REQUEST_STOP) { < return; < } < < if (workunit != NO_INCREASE) { < if (workunit < currentUnit) { < throw new IllegalArgumentException("Cannot decrease processed workunit count to lower value than before"); < } < if (workunit > totalUnits) { < // seems to be the by far most frequently abused contract. Record it to log file and safely handle the case < Logger.getAnonymousLogger().log(Level.WARNING, < "Cannot process more work than scheduled. " + < "Progress handle with name \"" + getDisplayName() + "\" has requested progress to workunit no." + workunit + < " but the total number of workunits is " + totalUnits + ". That means the progress bar UI will not display real progress and will stay at 100%.", < new IllegalArgumentException() < ); < workunit = totalUnits; < } < currentUnit = workunit; < } < if (message != null) { < lastMessage = message; < } < timeLastProgress = System.currentTimeMillis(); < < controller.progress(this, message, currentUnit, < totalUnits > 0 ? getPercentageDone() : -1, < (initialEstimate == -1 ? -1 : calculateFinishEstimate())); < } < < < // XXX - called from UI, threading < < public void requestCancel() { < if (!isAllowCancel()) { < return; < } < synchronized (this) { < state = STATE_REQUEST_STOP; < } < // do not call in synchronized block because it can take a long time to process, < /// and it could slow down UI. < //TODO - call in some other thread, not AWT? what is the cancel() contract? < cancelable.cancel(); < synchronized (this) { < requestStateSnapshot(); < } < } < < ///XXX - called from UI, threading < public void requestView() { < if (!isAllowView()) { < return; < } < viewAction.actionPerformed(new ActionEvent(viewAction, ActionEvent.ACTION_PERFORMED, "performView")); < } < < // XXX - called from UI, threading < public synchronized void requestExplicitSelection() { < timeLastProgress = System.currentTimeMillis(); < controller.explicitSelection(this, currentUnit, < totalUnits > 0 ? getPercentageDone() : -1, < (initialEstimate == -1 ? -1 : calculateFinishEstimate())); < } < < public synchronized void requestDisplayNameChange(String newDisplayName) { < displayName = newDisplayName; < if (state == STATE_INITIALIZED) { < return; < } < timeLastProgress = System.currentTimeMillis(); < controller.displayNameChange(this, currentUnit, < totalUnits > 0 ? getPercentageDone() : -1, < (initialEstimate == -1 ? -1 : calculateFinishEstimate()), newDisplayName); < } < < // XXX - called from UI, threading < public synchronized ProgressEvent requestStateSnapshot() { < timeLastProgress = System.currentTimeMillis(); < return controller.snapshot(this, lastMessage, currentUnit, < totalUnits > 0 ? getPercentageDone() : -1, < (initialEstimate == -1 ? -1 : calculateFinishEstimate())); < } < < /** < * have the component in custom location, don't include in the status bar. < */ < public synchronized JComponent extractComponent() { < if (customPlaced) { < throw new IllegalStateException("Cannot retrieve progress component multiple times"); < } < if (state != STATE_INITIALIZED) { < throw new IllegalStateException("You can request custom placement of progress component only before starting the task"); < } < customPlaced = true; < ProgressUIWorker comp = new NbProgressBar(); < controller = new Controller(comp); < return (JComponent)comp; < } < < < long calculateFinishEstimate() { < < // we are interested in seconds only < double durationSoFar = ((double)(System.currentTimeMillis() - timeStarted)) / 1000; < if (initialEstimate == -1) { < // we don't have an initial estimate, calculate by real-life data only < return (long)(durationSoFar * (totalUnits - currentUnit) / totalUnits); < } else { < // in the begining give the initial estimate more weight than in the end. < // should give us more smooth estimates < long remainingUnits = (totalUnits - currentUnit); < double remainingPortion = (double)remainingUnits / (double)totalUnits; < double currentEstimate = (double)durationSoFar / (double)currentUnit * totalUnits; < long retValue = (long)(((initialEstimate * remainingUnits * remainingPortion) < + (currentEstimate * remainingUnits * (1 - remainingPortion))) < / totalUnits); < return retValue; < } < } < /** < *public because of tests. < */ < public int getPercentageDone() { < return (int)((long)currentUnit * 100 / (long)totalUnits); < } < < long getTimeStampStarted() { < return timeStarted; < } < < < } Index: progress/src/org/netbeans/progress/module/ProgressEvent.java =================================================================== RCS file: progress/src/org/netbeans/progress/module/ProgressEvent.java diff -N progress/src/org/netbeans/progress/module/ProgressEvent.java 1,126d0 < /* < * The contents of this file are subject to the terms of the Common Development < * and Distribution License (the License). You may not use this file except in < * compliance with the License. < * < * You can obtain a copy of the License at http://www.netbeans.org/cddl.html < * or http://www.netbeans.org/cddl.txt. < * < * When distributing Covered Code, include this CDDL Header Notice in each file < * and include the License file at http://www.netbeans.org/cddl.txt. < * If applicable, add the following below the CDDL Header, with the fields < * enclosed by brackets [] replaced by your own identifying information: < * "Portions Copyrighted [year] [name of copyright owner]" < * < * The Original Software is NetBeans. The Initial Developer of the Original < * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun < * Microsystems, Inc. All Rights Reserved. < */ < < < package org.netbeans.progress.module; < < /** < * < * @author Milos Kleint (mkleint@netbeans.org) < */ < public final class ProgressEvent { < < public static final int TYPE_START = 0; < public static final int TYPE_FINISH = 4; < public static final int TYPE_REQUEST_STOP = 3; < public static final int TYPE_PROGRESS = 1; < public static final int TYPE_SWITCH = 5; < < private InternalHandle source; < private long estimatedCompletion; < private int percentageDone; < private int workunitsDone; < private String message; < private int type; < private boolean watched; < private boolean switched; < private String displayName; < /** Creates a new instance of ProgressEvent < * @param type one of TYPE_START, TYPE_REQUEST_STOP, TYPE_FINISH, TYPE_SWITCHED < */ < public ProgressEvent(InternalHandle src, int type, boolean isWatched) { < source = src; < estimatedCompletion = -1; < percentageDone = -1; < workunitsDone = -1; < message = null; < this.type = type; < watched = isWatched; < switched = (type == TYPE_SWITCH); < } < /** < * @param percentage completed work percentage < * @param estimate estimate of completion in seconds < */ < public ProgressEvent(InternalHandle src, String msg, int units, int percentage, long estimate, boolean isWatched) { < this(src, TYPE_PROGRESS, isWatched); < workunitsDone = units; < percentageDone = percentage; < estimatedCompletion = estimate; < message = msg; < } < public ProgressEvent(InternalHandle src, String msg, int units, int percentage, long estimate, boolean isWatched, String displayName) { < this(src, msg, units, percentage, estimate, isWatched); < this.displayName = displayName; < } < < public InternalHandle getSource() { < return source; < } < < public long getEstimatedCompletion() { < return estimatedCompletion; < } < < public int getPercentageDone() { < return percentageDone; < } < < public int getWorkunitsDone() { < return workunitsDone; < } < < public String getMessage() { < return message; < } < < public int getType() { < return type; < } < < public boolean isWatched() { < return watched; < } < < /** < * used in controller, preserve dynamic message from earlier events < * if this one doesn't have it's own. < */ < void copyMessageFromEarlier(ProgressEvent last) { < if (message == null) { < message = last.getMessage(); < } < if (displayName == null) { < displayName = last.getDisplayName(); < } < } < < void markAsSwitched() { < switched = true; < } < < public boolean isSwitched() { < return switched; < } < < public String getDisplayName() { < return displayName; < } < < } Index: progress/src/org/netbeans/progress/module/ProgressListAction.java =================================================================== RCS file: /cvs/core/progress/src/org/netbeans/progress/module/ProgressListAction.java,v retrieving revision 1.5 diff -r1.5 ProgressListAction.java 25c25 < import org.netbeans.progress.module.ui.StatusLineComponent; --- > import org.netbeans.progress.spi.ProgressUIWorkerWithModel; 53c53 < ((StatusLineComponent)Controller.getDefault().getVisualComponent()).showPopup(); --- > ((ProgressUIWorkerWithModel)Controller.getDefault().getVisualComponent()).showPopup(); Index: progress/src/org/netbeans/progress/module/ProgressUIWorker.java =================================================================== RCS file: progress/src/org/netbeans/progress/module/ProgressUIWorker.java diff -N progress/src/org/netbeans/progress/module/ProgressUIWorker.java 1,30d0 < /* < * The contents of this file are subject to the terms of the Common Development < * and Distribution License (the License). You may not use this file except in < * compliance with the License. < * < * You can obtain a copy of the License at http://www.netbeans.org/cddl.html < * or http://www.netbeans.org/cddl.txt. < * < * When distributing Covered Code, include this CDDL Header Notice in each file < * and include the License file at http://www.netbeans.org/cddl.txt. < * If applicable, add the following below the CDDL Header, with the fields < * enclosed by brackets [] replaced by your own identifying information: < * "Portions Copyrighted [year] [name of copyright owner]" < * < * The Original Software is NetBeans. The Initial Developer of the Original < * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun < * Microsystems, Inc. All Rights Reserved. < */ < < package org.netbeans.progress.module; < < /** < * < * @author mkleint < */ < public interface ProgressUIWorker { < < void processProgressEvent(ProgressEvent event); < void processSelectedProgressEvent(ProgressEvent event); < } Index: progress/src/org/netbeans/progress/module/TaskModel.java =================================================================== RCS file: progress/src/org/netbeans/progress/module/TaskModel.java diff -N progress/src/org/netbeans/progress/module/TaskModel.java 1,147d0 < /* < * The contents of this file are subject to the terms of the Common Development < * and Distribution License (the License). You may not use this file except in < * compliance with the License. < * < * You can obtain a copy of the License at http://www.netbeans.org/cddl.html < * or http://www.netbeans.org/cddl.txt. < * < * When distributing Covered Code, include this CDDL Header Notice in each file < * and include the License file at http://www.netbeans.org/cddl.txt. < * If applicable, add the following below the CDDL Header, with the fields < * enclosed by brackets [] replaced by your own identifying information: < * "Portions Copyrighted [year] [name of copyright owner]" < * < * The Original Software is NetBeans. The Initial Developer of the Original < * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun < * Microsystems, Inc. All Rights Reserved. < */ < < < package org.netbeans.progress.module; < < import javax.swing.DefaultListModel; < import javax.swing.DefaultListSelectionModel; < import javax.swing.ListModel; < import javax.swing.ListSelectionModel; < import javax.swing.event.ListDataListener; < import javax.swing.event.ListSelectionListener; < < /** < * < * @author Milos Kleint (mkleint@netbeans.org) < */ < public class TaskModel { < private DefaultListSelectionModel selectionModel; < private DefaultListModel model; < private InternalHandle explicit; < /** Creates a new instance of TaskModel */ < public TaskModel() { < selectionModel = new DefaultListSelectionModel(); < model = new DefaultListModel(); < } < < < < public void addHandle(InternalHandle handle) { < model.addElement(handle); < if (handle.isUserInitialized() && explicit == null) { < selectionModel.setSelectionInterval(model.size() - 1, model.size() - 1); < } < } < < public void removeHandle(InternalHandle handle) { < if (explicit == handle) { < explicit = null; < } < int index = model.indexOf(handle); < if (selectionModel.getMinSelectionIndex() == index) { < // if we are removing the handle that is selected, do tricks with selection < // too figure out which one should be sleected now < changeSelection(index); < } < InternalHandle selectedHandle = getSelectedHandle(); < model.removeElement(handle); < if (selectedHandle != null) { < selectionModel.setSelectionInterval(model.indexOf(selectedHandle), model.indexOf(selectedHandle)); < } else { < //TODO what to do here? < selectionModel.clearSelection(); < } < < } < < /** < * if we are removing the handle that is selected, do tricks with selection < * too figure out which one should be sleected no < */ < private void changeSelection(int current) { < InternalHandle last = null; < for (int i = 0; i < model.size(); i++) { < if (current != i) { < InternalHandle handle = (InternalHandle)model.getElementAt(i); < if (handle.isUserInitialized()) { < last = handle; < } else if (last == null) { < last = handle; < } < } < } < if (last != null) { < selectionModel.setSelectionInterval(model.indexOf(last), model.indexOf(last)); < } else { < selectionModel.clearSelection(); < } < < } < < public void explicitlySelect(InternalHandle handle) { < explicit = handle; < int index = model.indexOf(explicit); < if (index == -1) { < //TODO what? < } < selectionModel.setSelectionInterval(index, index); < } < < public InternalHandle getExplicitSelection() { < return explicit; < } < < public int getSize() { < return model.size(); < } < < < public InternalHandle[] getHandles() { < InternalHandle[] handles = new InternalHandle[model.size()]; < model.copyInto(handles); < return handles; < } < < public InternalHandle getSelectedHandle() { < int select = selectionModel.getMinSelectionIndex(); < if (select != -1) { < if (select >= 0 && select < model.size()) { < return (InternalHandle)model.getElementAt(selectionModel.getMinSelectionIndex()); < } < } < return null; < } < < public void addListSelectionListener(ListSelectionListener listener) { < selectionModel.addListSelectionListener(listener); < } < < public void removeListSelectionListener(ListSelectionListener listener) { < selectionModel.removeListSelectionListener(listener); < } < < public void addListDataListener(ListDataListener listener) { < model.addListDataListener(listener); < } < < public void removeListDataListener(ListDataListener listener) { < model.removeListDataListener(listener); < } < } Index: progress/src/org/netbeans/progress/module/resources/Bundle.properties =================================================================== RCS file: /cvs/core/progress/src/org/netbeans/progress/module/resources/Bundle.properties,v retrieving revision 1.3 diff -r1.3 Bundle.properties 18c18 < OpenIDE-Module-Name=Progress API & UI --- > OpenIDE-Module-Name=Progress API Index: progress/src/org/netbeans/progress/module/ui/Bundle.properties =================================================================== RCS file: progress/src/org/netbeans/progress/module/ui/Bundle.properties diff -N progress/src/org/netbeans/progress/module/ui/Bundle.properties 1,28d0 < # The contents of this file are subject to the terms of the Common Development < # and Distribution License (the License). You may not use this file except in < # compliance with the License. < # < # You can obtain a copy of the License at http://www.netbeans.org/cddl.html < # or http://www.netbeans.org/cddl.txt. < # < # When distributing Covered Code, include this CDDL Header Notice in each file < # and include the License file at http://www.netbeans.org/cddl.txt. < # If applicable, add the following below the CDDL Header, with the fields < # enclosed by brackets [] replaced by your own identifying information: < # "Portions Copyrighted [year] [name of copyright owner]" < # < # The Original Software is NetBeans. The Initial Developer of the Original < # Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun < # Microsystems, Inc. All Rights Reserved. < < NbProgressBar.tooltip1={0} tasks running. Click for details. < NbProgressBar.tooltip2={0} task running. Click for details. < ListComponent.btnClose.tooltip=Click to cancel process < ListComponent.bar.tooltip=Click to watch the process < Cancel_Question=Are you sure you want to cancel {0}? < Cancel_Question_Title=Cancel Running Task < StatusLineComponent.ShowProcessList=Show Processes < StatusLineComponent.Cancel=Cancel Process < StatusLineComponent.View=Show Output < ListComponent.Watch=Watch Process < Index: progress/src/org/netbeans/progress/module/ui/ListComponent.java =================================================================== RCS file: progress/src/org/netbeans/progress/module/ui/ListComponent.java diff -N progress/src/org/netbeans/progress/module/ui/ListComponent.java 1,390d0 < /* < * The contents of this file are subject to the terms of the Common Development < * and Distribution License (the License). You may not use this file except in < * compliance with the License. < * < * You can obtain a copy of the License at http://www.netbeans.org/cddl.html < * or http://www.netbeans.org/cddl.txt. < * < * When distributing Covered Code, include this CDDL Header Notice in each file < * and include the License file at http://www.netbeans.org/cddl.txt. < * If applicable, add the following below the CDDL Header, with the fields < * enclosed by brackets [] replaced by your own identifying information: < * "Portions Copyrighted [year] [name of copyright owner]" < * < * The Original Software is NetBeans. The Initial Developer of the Original < * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun < * Microsystems, Inc. All Rights Reserved. < */ < < package org.netbeans.progress.module.ui; < < import java.awt.Color; < import java.awt.Component; < import java.awt.Cursor; < import java.awt.Dimension; < import java.awt.Font; < import java.awt.Image; < import java.awt.LayoutManager; < import java.awt.event.ActionEvent; < import java.awt.event.FocusListener; < import java.awt.event.KeyEvent; < import java.awt.event.MouseAdapter; < import java.awt.event.MouseEvent; < import javax.swing.AbstractAction; < import javax.swing.Action; < import javax.swing.BorderFactory; < import javax.swing.Icon; < import javax.swing.ImageIcon; < import javax.swing.JButton; < import javax.swing.JLabel; < import javax.swing.JPanel; < import javax.swing.JPopupMenu; < import javax.swing.KeyStroke; < import javax.swing.UIManager; < import org.netbeans.progress.module.InternalHandle; < import org.netbeans.progress.module.ProgressEvent; < import org.openide.DialogDisplayer; < import org.openide.NotifyDescriptor; < import org.openide.util.NbBundle; < import org.openide.util.Utilities; < < /** < * < * @author mkleint < */ < public class ListComponent extends JPanel { < private NbProgressBar bar; < private JLabel mainLabel; < private JLabel dynaLabel; < private JButton closeButton; < private InternalHandle handle; < private boolean watched; < private Action cancelAction; < private Color selectBgColor; < private Color selectFgColor; < private Color bgColor; < private Color fgColor; < private Color dynaFgColor; < private int mainHeight; < private int dynaHeight; < < /** Creates a new instance of ListComponent */ < public ListComponent(InternalHandle hndl) { < setFocusable(true); < setRequestFocusEnabled(true); < // setVerifyInputWhenFocusTarget(false); < mainLabel = new JLabel(); < dynaLabel = new JLabel(); < // in gtk, the panel is non-opague, meaning we cannot color background < // #59419 < setOpaque(true); < dynaLabel.setFont(dynaLabel.getFont().deriveFont((float) (dynaLabel.getFont().getSize() - 2))); < bar = new NbProgressBar(); < handle = hndl; < Color bg = UIManager.getColor("nbProgressBar.popupText.background"); < if (bg != null) { < setBackground(bg); < mainLabel.setBackground(bg); < dynaLabel.setBackground(bg); < } < bgColor = getBackground(); < Color dynaFg = UIManager.getColor("nbProgressBar.popupDynaText.foreground"); < if (dynaFg != null) { < dynaLabel.setForeground(dynaFg); < } < dynaFgColor = dynaLabel.getForeground(); < fgColor = UIManager.getColor("nbProgressBar.popupText.foreground"); < if (fgColor != null) { < mainLabel.setForeground(fgColor); < } < fgColor = mainLabel.getForeground(); < selectBgColor = UIManager.getColor("nbProgressBar.popupText.selectBackground"); < if (selectBgColor == null) { < selectBgColor = UIManager.getColor("List.selectionBackground"); < } < selectFgColor = UIManager.getColor("nbProgressBar.popupText.selectForeground"); < if (selectFgColor == null) { < selectFgColor = UIManager.getColor("List.selectionForeground"); < } < bar.setToolTipText(NbBundle.getMessage(ListComponent.class, "ListComponent.bar.tooltip")); < bar.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); < //start figure out height < mainLabel.setText("XYZ"); < dynaLabel.setText("XYZ"); < mainHeight = mainLabel.getPreferredSize().height; < dynaHeight = dynaLabel.getPreferredSize().height; < mainLabel.setText(null); < dynaLabel.setText(null); < //end figure out height < < setLayout(new CustomLayout()); < add(mainLabel); < add(bar); < MListener list = new MListener(); < if (handle.isAllowCancel()) { < cancelAction = new CancelAction(false); < closeButton = new JButton(cancelAction); < closeButton.setBorderPainted(false); < closeButton.setBorder(BorderFactory.createEmptyBorder()); < closeButton.setOpaque(false); < < closeButton.setToolTipText(NbBundle.getMessage(ListComponent.class, "ListComponent.btnClose.tooltip")); < add(closeButton); < if (handle.getState() != InternalHandle.STATE_RUNNING) { < closeButton.setEnabled(false); < } < } < add(dynaLabel); < setBorder(BorderFactory.createEmptyBorder()); < addMouseListener(list); < bar.addMouseListener(list); < mainLabel.addMouseListener(list); < dynaLabel.addMouseListener(list); < if (handle.isAllowCancel()) { < closeButton.addMouseListener(list); < } < < mainLabel.setText(handle.getDisplayName()); < NbProgressBar.setupBar(handle, bar); < addFocusListener(new FocusListener() { < public void focusGained(java.awt.event.FocusEvent e) { < if (!e.isTemporary()) { < setBackground(selectBgColor); < mainLabel.setBackground(selectBgColor); < dynaLabel.setBackground(selectBgColor); < mainLabel.setForeground(selectFgColor); < // TODO assuming now that dynalabel has always the same foreground color < // seems to be the case according to the spec < scrollRectToVisible(getBounds()); < } < } < < public void focusLost(java.awt.event.FocusEvent e) { < if (!e.isTemporary()) { < setBackground(bgColor); < mainLabel.setBackground(bgColor); < dynaLabel.setBackground(bgColor); < mainLabel.setForeground(fgColor); < // TODO assuming now that dynalabel has always the same foreground color < // seems to be the case according to the spec < < } < } < < }); < < } < < < Action getCancelAction() { < return cancelAction; < } < < InternalHandle getHandle() { < return handle; < } < < void processProgressEvent(ProgressEvent event) { < if (event.getType() == ProgressEvent.TYPE_PROGRESS || < event.getType() == ProgressEvent.TYPE_SWITCH) { < if (event.getSource() != handle) { < throw new IllegalStateException(); < } < if (event.isSwitched()) { < NbProgressBar.setupBar(event.getSource(), bar); < } < if (event.getWorkunitsDone() > 0) { < bar.setValue(event.getWorkunitsDone()); < } < bar.setString(StatusLineComponent.getBarString(event.getPercentageDone(), event.getEstimatedCompletion())); < if (event.getMessage() != null) { < dynaLabel.setText(event.getMessage()); < } < if (event.getSource().getState() == InternalHandle.STATE_REQUEST_STOP) { < closeButton.setEnabled(false); < } < if (event.getDisplayName() != null) { < mainLabel.setText(event.getDisplayName()); < } < } else { < throw new IllegalStateException(); < } < } < < void markAsActive(boolean sel) { < if (sel == watched) { < return; < } < watched = sel; < if (sel) { < mainLabel.setFont(mainLabel.getFont().deriveFont(Font.BOLD)); < } else { < mainLabel.setFont(mainLabel.getFont().deriveFont(Font.PLAIN)); < } < if (mainLabel.isVisible()) { < mainLabel.repaint(); < } < } < < private class MListener extends MouseAdapter { < public void mouseClicked(MouseEvent e) { < if (e.getSource() == bar) { < handle.requestExplicitSelection(); < // markAsSelected(true); < } < if (e.getClickCount() > 1 && (e.getSource() == mainLabel || e.getSource() == dynaLabel)) { < handle.requestView(); < } < if (e.getButton() != e.BUTTON1) { < showMenu(e); < } else { < ListComponent.this.requestFocus(); < } < < // System.out.println("list component requesting focus.."); < } < } < < private void showMenu(MouseEvent e) { < JPopupMenu popup = new JPopupMenu(); < //mark teh popup for the status line awt listener < popup.setName("progresspopup"); < popup.add(new ViewAction()); < popup.add(new WatchAction()); < popup.add(new CancelAction(true)); < popup.show((Component)e.getSource(), e.getX(), e.getY()); < } < < private class CancelAction extends AbstractAction { < CancelAction(boolean text) { < if (text) { < putValue(Action.NAME, NbBundle.getMessage(ListComponent.class, "StatusLineComponent.Cancel")); < putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0)); < } else { < Image icon = (Image)UIManager.get("nb.progress.cancel.icon"); < if (icon == null) { < // for custom L&F? < icon = Utilities.loadImage("org/netbeans/progress/module/resources/buton.png"); < } < putValue(Action.SMALL_ICON, new ImageIcon(icon)); < } < setEnabled(handle == null ? false : handle.isAllowCancel()); < } < < public void actionPerformed(ActionEvent actionEvent) { < if (handle.getState() == InternalHandle.STATE_RUNNING) { < String message = NbBundle.getMessage(ListComponent.class, "Cancel_Question", handle.getDisplayName()); < String title = NbBundle.getMessage(ListComponent.class, "Cancel_Question_Title"); < NotifyDescriptor dd = new NotifyDescriptor(message, title, < NotifyDescriptor.YES_NO_OPTION, < NotifyDescriptor.QUESTION_MESSAGE, null, null); < Object retType = DialogDisplayer.getDefault().notify(dd); < if (retType == NotifyDescriptor.YES_OPTION) { < handle.requestCancel(); < } < } < } < } < < private class ViewAction extends AbstractAction { < public ViewAction() { < putValue(Action.NAME, NbBundle.getMessage(ListComponent.class, "StatusLineComponent.View")); < setEnabled(handle == null ? false : handle.isAllowView()); < putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0)); < } < public void actionPerformed(ActionEvent actionEvent) { < if (handle != null) { < handle.requestView(); < } < } < } < < private class WatchAction extends AbstractAction { < public WatchAction() { < putValue(Action.NAME, NbBundle.getMessage(ListComponent.class, "ListComponent.Watch")); < putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0)); < setEnabled(true); < } < public void actionPerformed(ActionEvent actionEvent) { < if (handle != null) { < handle.requestExplicitSelection(); < } < } < } < < < private static final int UPPERMARGIN = 3; < private static final int LEFTMARGIN = 2; < private static final int BOTTOMMARGIN = 2; < private static final int BETWEENTEXTMARGIN = 3; < < static final int ITEM_WIDTH = 400; < < private class CustomLayout implements LayoutManager { < < /** < * If the layout manager uses a per-component string, < * adds the component comp to the layout, < * associating it < * with the string specified by name. < * < * @param name the string to be associated with the component < * @param comp the component to be added < */ < public void addLayoutComponent(String name, java.awt.Component comp) { < } < < /** < * Calculates the preferred size dimensions for the specified < * container, given the components it contains. < * @param parent the container to be laid out < * < * @see #minimumLayoutSize < */ < public Dimension preferredLayoutSize(java.awt.Container parent) { < int height = UPPERMARGIN + mainHeight + BETWEENTEXTMARGIN + dynaHeight + BOTTOMMARGIN; < return new Dimension(ITEM_WIDTH, height); < } < < /** < * < * Lays out the specified container. < * @param parent the container to be laid out < */ < public void layoutContainer(java.awt.Container parent) { < int parentWidth = parent.getWidth(); < int parentHeight = parent.getHeight(); < int offset = parentWidth - 18; < if (closeButton != null) { < closeButton.setBounds(offset, UPPERMARGIN, 18, mainHeight); < } < // have the bar approx 30 percent of the width < int barOffset = offset - (ITEM_WIDTH / 3); < bar.setBounds(barOffset, UPPERMARGIN, offset - barOffset, mainHeight); < mainLabel.setBounds(LEFTMARGIN, UPPERMARGIN, barOffset - LEFTMARGIN, mainHeight); < dynaLabel.setBounds(LEFTMARGIN, mainHeight + UPPERMARGIN + BETWEENTEXTMARGIN, < parentWidth - LEFTMARGIN, dynaHeight); < } < < /** < * < * Calculates the minimum size dimensions for the specified < * container, given the components it contains. < * @param parent the component to be laid out < * @see #preferredLayoutSize < */ < public Dimension minimumLayoutSize(java.awt.Container parent) { < return preferredLayoutSize(parent); < } < < /** < * Removes the specified component from the layout. < * @param comp the component to be removed < */ < public void removeLayoutComponent(java.awt.Component comp) { < } < < < } < } \ No newline at end of file Index: progress/src/org/netbeans/progress/module/ui/NbProgressBar.java =================================================================== RCS file: progress/src/org/netbeans/progress/module/ui/NbProgressBar.java diff -N progress/src/org/netbeans/progress/module/ui/NbProgressBar.java 1,116d0 < /* < * The contents of this file are subject to the terms of the Common Development < * and Distribution License (the License). You may not use this file except in < * compliance with the License. < * < * You can obtain a copy of the License at http://www.netbeans.org/cddl.html < * or http://www.netbeans.org/cddl.txt. < * < * When distributing Covered Code, include this CDDL Header Notice in each file < * and include the License file at http://www.netbeans.org/cddl.txt. < * If applicable, add the following below the CDDL Header, with the fields < * enclosed by brackets [] replaced by your own identifying information: < * "Portions Copyrighted [year] [name of copyright owner]" < * < * The Original Software is NetBeans. The Initial Developer of the Original < * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun < * Microsystems, Inc. All Rights Reserved. < */ < < package org.netbeans.progress.module.ui; < < import java.awt.Color; < import java.awt.Dimension; < import javax.swing.JProgressBar; < import javax.swing.UIManager; < import org.netbeans.progress.module.InternalHandle; < import org.netbeans.progress.module.ProgressUIWorker; < import org.netbeans.progress.module.ProgressEvent; < < < /** < * progress component, let just put the UI related issues here, update the state from outside < < * @author mkleint < */ < public class NbProgressBar extends JProgressBar implements ProgressUIWorker { < boolean isSetup = false; < boolean usedInStatusBar = false; < < /** Creates a new instance of NbProgressBar */ < public NbProgressBar() { < super(); < setOrientation(JProgressBar.HORIZONTAL); < setAlignmentX(0.5f); < setAlignmentY(0.5f); < Color fg = UIManager.getColor ("nbProgressBar.Foreground"); < if (fg != null) { < setForeground(fg); < } < Color bg = UIManager.getColor ("nbProgressBar.Background"); < if (bg != null) { < setBackground(bg); < } < } < < public void setUseInStatusBar(boolean use) { < usedInStatusBar = use; < } < < public Dimension getPreferredSize() { < Dimension supers = super.getPreferredSize(); < if (usedInStatusBar) { < supers.width = ListComponent.ITEM_WIDTH / 3; < } < return supers; < } < < < //--- these are used only when dealing with extracted component, when in status bar this is not used. < //------------------------------------ < < public void processProgressEvent(ProgressEvent event) { < if (event.getType() == ProgressEvent.TYPE_START || !isSetup || event.isSwitched()) { < setupBar(event.getSource(), this); < isSetup = true; < } < if (event.getType() == ProgressEvent.TYPE_PROGRESS) { < if (event.getWorkunitsDone() > 0) { < setValue(event.getWorkunitsDone()); < } < setString(StatusLineComponent.getBarString(event.getPercentageDone(), event.getEstimatedCompletion())); < } else if (event.getType() == ProgressEvent.TYPE_FINISH) { < boolean wasIndetermenite = isIndeterminate(); < setIndeterminate(false); < setMaximum(event.getSource().getTotalUnits()); < setValue(event.getSource().getTotalUnits()); < if (wasIndetermenite) { < setStringPainted(false); < } else { < setString(StatusLineComponent.getBarString(100, -1)); < } < } < } < < public void processSelectedProgressEvent(ProgressEvent event) { < // ignore we'return always processing just one selected component < } < < < static void setupBar(InternalHandle handle, NbProgressBar bar) { < int total = handle.getTotalUnits(); < if (total < 1) { < // macosx workaround.. < bar.setValue(bar.getMaximum()); < bar.setIndeterminate(true); < bar.setStringPainted(false); < } else { < bar.setStringPainted(true); < bar.setIndeterminate(false); < bar.setMaximum(total); < bar.setMinimum(0); < bar.setValue(0); < } < bar.setString(" "); < } < } \ No newline at end of file Index: progress/src/org/netbeans/progress/module/ui/PopupPane.java =================================================================== RCS file: progress/src/org/netbeans/progress/module/ui/PopupPane.java diff -N progress/src/org/netbeans/progress/module/ui/PopupPane.java 1,278d0 < /* < * The contents of this file are subject to the terms of the Common Development < * and Distribution License (the License). You may not use this file except in < * compliance with the License. < * < * You can obtain a copy of the License at http://www.netbeans.org/cddl.html < * or http://www.netbeans.org/cddl.txt. < * < * When distributing Covered Code, include this CDDL Header Notice in each file < * and include the License file at http://www.netbeans.org/cddl.txt. < * If applicable, add the following below the CDDL Header, with the fields < * enclosed by brackets [] replaced by your own identifying information: < * "Portions Copyrighted [year] [name of copyright owner]" < * < * The Original Software is NetBeans. The Initial Developer of the Original < * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun < * Microsystems, Inc. All Rights Reserved. < */ < < < package org.netbeans.progress.module.ui; < < import java.awt.Color; < import java.awt.Component; < import java.awt.Dimension; < import java.awt.Graphics; < import java.awt.GridLayout; < import java.awt.Insets; < import java.awt.Toolkit; < import java.awt.event.ActionEvent; < import java.awt.event.KeyEvent; < import java.util.HashSet; < import java.util.Iterator; < import javax.swing.AbstractAction; < import javax.swing.Action; < import javax.swing.BorderFactory; < import javax.swing.JComponent; < import javax.swing.JPanel; < import javax.swing.JScrollPane; < import javax.swing.KeyStroke; < import javax.swing.UIManager; < import javax.swing.border.Border; < import org.netbeans.progress.module.InternalHandle; < < /** < * < * @author mkleint < */ < public class PopupPane extends JScrollPane { < private JPanel view; < private HashSet listComponents; < /** Creates a new instance of PopupPane */ < private ListComponent selected; < < public PopupPane() { < listComponents = new HashSet(); < view = new JPanel(); < GridLayout grid = new GridLayout(0, 1); < grid.setHgap(0); < grid.setVgap(0); < view.setLayout(grid); < view.setBorder(BorderFactory.createEmptyBorder()); < setName("progresspopup"); //NOI18N < setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); < setViewportView(view); < setFocusable(true); < setRequestFocusEnabled(true); < < Action down = new MoveDownAction(); < getActionMap().put("Move-Down", down); < getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "Move-Down"); < getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "Move-Down"); < < Action up = new MoveUpAction(); < getActionMap().put("Move-Up", up); < getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "Move-Up"); < getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "Move-Up"); < Action cancel = new CancelAction(); < getActionMap().put("Cancel-Task", cancel); < getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), "Cancel-Task"); < getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), "Cancel-Task"); < < Action select = new SelectAction(); < getActionMap().put("select-task", select); < getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "select-task"); < getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "select-task"); < < < setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); < // addFocusListener(new FocusListener() { < // public void focusLost(java.awt.event.FocusEvent e) { < // System.out.println("popup focus gained temp?=" + e.isTemporary()); < // } < // < // public void focusGained(java.awt.event.FocusEvent e) { < // System.out.println("popup focus lost temporary?=" + e.isTemporary()); < // } < // < // }); < } < < public void addListComponent(ListComponent lst) { < listComponents.add(lst); < if (view.getComponentCount() > 0) { < JComponent previous = (JComponent)view.getComponent(view.getComponentCount() - 1); < previous.setBorder(new BottomLineBorder()); < } < lst.setBorder(BorderFactory.createEmptyBorder()); < view.add(lst); < if (listComponents.size() > 3) { < setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); < } else { < setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER); < } < } < < public void removeListComponent(InternalHandle handle) { < Iterator it = listComponents.iterator(); < while (it.hasNext()) { < ListComponent comp = (ListComponent)it.next(); < if (comp.getHandle() == handle) { < view.remove(comp); < it.remove(); < break; < } < } < if (listComponents.size() > 3) { < setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); < } else { < setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER); < } < } < < public Dimension getPreferredSize() { < int count = view.getComponentCount(); < int height = count > 0 ? view.getComponent(0).getPreferredSize().height : 0; < int offset = count > 3 ? height * 3 + 5 : (count * height) + 5; < // 22 is the width of the additional scrollbar < return new Dimension(count >3 ? ListComponent.ITEM_WIDTH + 22 < : ListComponent.ITEM_WIDTH + 2, offset); < } < < /** < * bold font is now used not only for explicitly selected items, but for any < * change in currently selected task. < */ < public void updateBoldFont(InternalHandle handle) { < Iterator it = listComponents.iterator(); < while (it.hasNext()) { < ListComponent comp = (ListComponent)it.next(); < comp.markAsActive(handle == comp.getHandle()); < } < } < < < < private static class BottomLineBorder implements Border { < private Insets ins = new Insets(0, 0, 1, 0); < private Color col = new Color(221, 229, 248); < < public BottomLineBorder () {} < < public Insets getBorderInsets(Component c) { < return ins; < } < < public boolean isBorderOpaque() { < return false; < } < < public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { < Color old = g.getColor(); < g.setColor(col); < g.drawRect(x, y + height - 2, width, 1); < g.setColor(old); < } < } < < private int findIndex(Component comp) { < Component[] comps = view.getComponents(); < for (int i = 0; i < comps.length; i++) { < if (comps[i] == comp) { < return i; < } < } < return -1; < } < < public void requestFocus() { < //#63666 - don't focus any of the tasks explicitly, wait for user action. < // if (view.getComponentCount() > 1) { < // if (selected == null || !selected.isDisplayable()) { < // selected = (ListComponent)view.getComponent(0); < // } < // selected.requestFocus(); < // } else { < super.requestFocus(); < // } < } < < private class MoveDownAction extends AbstractAction { < < MoveDownAction() { < } < < public void actionPerformed(ActionEvent actionEvent) { < int index = -1; < if (selected != null) { < index = findIndex(selected); < } < index = index + 1; < if (index >= PopupPane.this.view.getComponentCount()) { < index = 0; < } < selected = (ListComponent)PopupPane.this.view.getComponent(index); < selected.requestFocus(); < } < < } < < private class MoveUpAction extends AbstractAction { < < MoveUpAction() { < } < < public void actionPerformed(ActionEvent actionEvent) { < int index = PopupPane.this.view.getComponentCount(); < if (selected != null) { < index = findIndex(selected); < // selected.setBackground(new Color(249, 249, 249)); < } < index = index - 1; < if (index < 0) { < index = PopupPane.this.view.getComponentCount() - 1; < } < selected = (ListComponent)PopupPane.this.view.getComponent(index); < selected.requestFocus(); < // selected.setBackground(selectBgColor); < // selected.scrollRectToVisible(selected.getBounds()); < } < } < < private class CancelAction extends AbstractAction { < public CancelAction () {} < < public void actionPerformed(ActionEvent actionEvent) { < if (selected != null) { < Action act = selected.getCancelAction(); < if (act != null) { < act.actionPerformed(actionEvent); < } else { < Toolkit.getDefaultToolkit().beep(); < } < } < } < } < < private class SelectAction extends AbstractAction { < public SelectAction () {} < < public void actionPerformed(ActionEvent actionEvent) { < if (selected != null) { < selected.getHandle().requestExplicitSelection(); < } < } < } < < private class ViewAction extends AbstractAction { < public ViewAction () {} < < public void actionPerformed(ActionEvent actionEvent) { < if (selected != null) { < selected.getHandle().requestView(); < } < } < } < < } Index: progress/src/org/netbeans/progress/module/ui/StatusLineComponent.java =================================================================== RCS file: progress/src/org/netbeans/progress/module/ui/StatusLineComponent.java diff -N progress/src/org/netbeans/progress/module/ui/StatusLineComponent.java 1,464d0 < /* < * The contents of this file are subject to the terms of the Common Development < * and Distribution License (the License). You may not use this file except in < * compliance with the License. < * < * You can obtain a copy of the License at http://www.netbeans.org/cddl.html < * or http://www.netbeans.org/cddl.txt. < * < * When distributing Covered Code, include this CDDL Header Notice in each file < * and include the License file at http://www.netbeans.org/cddl.txt. < * If applicable, add the following below the CDDL Header, with the fields < * enclosed by brackets [] replaced by your own identifying information: < * "Portions Copyrighted [year] [name of copyright owner]" < * < * The Original Software is NetBeans. The Initial Developer of the Original < * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun < * Microsystems, Inc. All Rights Reserved. < */ < < < package org.netbeans.progress.module.ui; < import java.awt.AWTEvent; < import java.awt.Component; < import java.awt.Container; < import java.awt.Cursor; < import java.awt.Dimension; < import java.awt.FlowLayout; < import java.awt.Frame; < import java.awt.Point; < import java.awt.Rectangle; < import java.awt.Toolkit; < import java.awt.event.AWTEventListener; < import java.awt.event.ActionEvent; < import java.awt.event.ComponentAdapter; < import java.awt.event.ComponentEvent; < import java.awt.event.KeyEvent; < import java.awt.event.MouseAdapter; < import java.awt.event.MouseEvent; < import java.awt.event.MouseListener; < import java.awt.event.WindowEvent; < import java.awt.event.WindowStateListener; < import java.util.HashMap; < import java.util.Map; < import javax.swing.AbstractAction; < import javax.swing.Action; < import javax.swing.BorderFactory; < import javax.swing.JComponent; < import javax.swing.JLabel; < import javax.swing.JPanel; < import javax.swing.JPopupMenu; < import javax.swing.JSeparator; < import javax.swing.JWindow; < import javax.swing.KeyStroke; < import javax.swing.Popup; < import javax.swing.SwingUtilities; < import javax.swing.event.ListDataEvent; < import javax.swing.event.ListDataListener; < import javax.swing.event.ListSelectionEvent; < import javax.swing.event.ListSelectionListener; < import org.netbeans.progress.module.InternalHandle; < import org.netbeans.progress.module.ProgressUIWorker; < import org.netbeans.progress.module.ProgressEvent; < import org.netbeans.progress.module.ProgressListAction; < import org.netbeans.progress.module.TaskModel; < import org.openide.DialogDisplayer; < import org.openide.NotifyDescriptor; < import org.openide.util.NbBundle; < import org.openide.util.Utilities; < import org.openide.windows.WindowManager; < < < /** < * < * @author Milos Kleint (mkleint@netbeans.org) < */ < public class StatusLineComponent extends JPanel implements ProgressUIWorker { < private NbProgressBar bar; < private JLabel label; < private JSeparator separator; < private InternalHandle handle; < private boolean showingPopup = false; < private TaskModel model; < private MouseListener mouseListener; < private HideAWTListener hideListener; < private Popup popup; < private JWindow popupWindow; < private PopupPane pane; < private Map handleComponentMap; < private final int prefferedHeight; < /** Creates a new instance of StatusLineComponent */ < public StatusLineComponent() { < handleComponentMap = new HashMap(); < label = new JLabel(); < label.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); < bar = new NbProgressBar(); < bar.setUseInStatusBar(true); < // tricks to figure out correct height. < bar.setStringPainted(true); < bar.setString("XXX"); < label.setText("XXX"); < prefferedHeight = Math.max(label.getPreferredSize().height, bar.getPreferredSize().height) + 2; < < bar.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); < // setBorder(BorderFactory.createLineBorder(Color.BLUE, 1)); < FlowLayout flay = new FlowLayout(); < flay.setVgap(1); < flay.setHgap(5); < setLayout(flay); < // HACK - put smaller font inside the progress bar to keep < // the height of the progressbar constant for determinate and indeterminate bars < // Font fnt = UIManager.getFont("ProgressBar.font"); < // bar.setFont(fnt.deriveFont(fnt.getStyle(), fnt.getSize() - 3)); < < mouseListener = new MListener(); < label.addMouseListener(mouseListener); < bar.addMouseListener(mouseListener); < addMouseListener(mouseListener); < hideListener = new HideAWTListener(); < pane = new PopupPane(); < pane.getActionMap().put("HidePopup", new AbstractAction() { < public void actionPerformed(ActionEvent actionEvent) { < // System.out.println("escape pressed - hiding"); < hidePopup(); < } < }); < pane.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "HidePopup"); < pane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "HidePopup"); < separator = new JSeparator(JSeparator.VERTICAL); < separator.setPreferredSize(new Dimension(5, prefferedHeight)); < separator.setBorder(BorderFactory.createEmptyBorder(1, 0, 2, 0)); < } < < public Dimension getPreferredSize() { < Dimension retValue; < retValue = super.getPreferredSize(); < retValue.height = prefferedHeight; < return retValue; < } < < public Dimension getMinimumSize() { < Dimension retValue; < retValue = super.getMinimumSize(); < retValue.height = prefferedHeight; < return retValue; < } < < public Dimension getMaximumSize() { < Dimension retValue; < retValue = super.getMaximumSize(); < retValue.height = prefferedHeight; < return retValue; < } < < public void setModel(TaskModel mod) { < model = mod; < model.addListDataListener(new Listener()); < model.addListSelectionListener(new ListSelectionListener() { < public void valueChanged(ListSelectionEvent e) { < pane.updateBoldFont(model.getSelectedHandle()); < } < }); < } < < private void setTooltipForAll() { < int size = model.getSize(); < String key = "NbProgressBar.tooltip1"; //NOI18N < if (size == 1) { < key = "NbProgressBar.tooltip2"; //NOI18N < } < String text = NbBundle.getMessage(StatusLineComponent.class, key, new Integer(size)); < setToolTipText(text); < label.setToolTipText(text); < bar.setToolTipText(text); < } < < public void processProgressEvent(ProgressEvent event) { < if (event.getType() == ProgressEvent.TYPE_START) { < createListItem(event.getSource()); < } else if (event.getType() == ProgressEvent.TYPE_PROGRESS || < event.getType() == ProgressEvent.TYPE_SWITCH) { < ListComponent comp = (ListComponent)handleComponentMap.get(event.getSource()); < if (comp == null) { < createListItem(event.getSource()); < comp = (ListComponent)handleComponentMap.get(event.getSource()); < } < comp.processProgressEvent(event); < } else if (event.getType() == ProgressEvent.TYPE_FINISH) { < removeListItem(event.getSource()); < if (model.getSelectedHandle() != null && handle != model.getSelectedHandle()) { < initiateComponent(model.getSelectedHandle().requestStateSnapshot()); < } < } < < } < < public void processSelectedProgressEvent(ProgressEvent event) { < if (event.getType() == ProgressEvent.TYPE_START) { < initiateComponent(event); < return; < } else if (event.getType() == ProgressEvent.TYPE_FINISH) { < //happens only when there's no more handles. < hidePopup(); < removeAll(); < //#63393, 61940 fix - removeAll() just invalidates. seems to work without revalidate/repaint on some platforms, fail on others. < revalidate(); < repaint(); < return; < } else { < if (event.getSource() != handle || event.isSwitched()) { < initiateComponent(event); < } < if (event.getWorkunitsDone() > 0) { < bar.setValue(event.getWorkunitsDone()); < } < bar.setString(getBarString(event.getPercentageDone(), event.getEstimatedCompletion())); < if (event.getDisplayName() != null) { < label.setText(event.getDisplayName()); < } < } < } < < static String formatEstimate(long estimate) { < long minutes = estimate / 60; < long seconds = estimate - (minutes * 60); < return "" + minutes + (seconds < 10 ? ":0" : ":") + seconds; < } < < static String getBarString(int percentage, long estimatedCompletion) { < if (estimatedCompletion != -1) { < return formatEstimate(estimatedCompletion); < } < if (percentage != -1) { < return "" + percentage + "%"; < } < return ""; < } < < private void initiateComponent(ProgressEvent event) { < handle = event.getSource(); < boolean toShow = false; < label.setText(handle.getDisplayName()); < if (label.getParent() == null) { < add(label); < toShow = true; < } < NbProgressBar.setupBar(event.getSource(), bar); < if (bar.getParent() == null) { < add(bar); < toShow = true; < } < if (separator.getParent() == null) { < add(separator); < toShow = true; < } < if (toShow) { < revalidate(); < repaint(); < } < } < < private class Listener implements ListDataListener { < public void intervalAdded(ListDataEvent e) { < setTooltipForAll(); < } < < public void intervalRemoved(ListDataEvent e) { < setTooltipForAll(); < } < < < public void contentsChanged(ListDataEvent e) { < setTooltipForAll(); < } < } < < public void hidePopup() { < if (popupWindow != null) { < // popupWindow.getContentPane().removeAll(); < popupWindow.setVisible(false); < } < Toolkit.getDefaultToolkit().removeAWTEventListener(hideListener); < WindowManager.getDefault().getMainWindow().removeWindowStateListener(hideListener); < WindowManager.getDefault().getMainWindow().removeComponentListener(hideListener); < showingPopup = false; < } < < private void createListItem(InternalHandle handle) { < ListComponent comp; < if (handleComponentMap.containsKey(handle)) { < // happens when we click to display on popup and there is a < // new handle waiting in the queue. < comp = handleComponentMap.get(handle); < } else { < comp = new ListComponent(handle); < handleComponentMap.put(handle, comp); < } < pane.addListComponent(comp); < pane.updateBoldFont(model.getSelectedHandle()); < if (showingPopup) { < resizePopup(); < } < } < < private void removeListItem(InternalHandle handle) { < handleComponentMap.remove(handle); < pane.removeListComponent(handle); < pane.updateBoldFont(model.getSelectedHandle()); < if (showingPopup) { < resizePopup(); < } < } < < < public void showPopup() { < if (showingPopup) { < return; < } < InternalHandle[] handles = model.getHandles(); < if (handles.length == 0) { < // just in case.. < return; < } < showingPopup = true; < < // NOT using PopupFactory < // 1. on linux, creates mediumweight popup taht doesn't refresh behind visible glasspane < // 2. on mac, needs an owner frame otherwise hiding tooltip also hides the popup. (linux requires no owner frame to force heavyweight) < // 3. the created window is not focusable window < if (popupWindow == null) { < popupWindow = new JWindow(WindowManager.getDefault().getMainWindow()); < popupWindow.getContentPane().add(pane); < } < Toolkit.getDefaultToolkit().addAWTEventListener(hideListener, AWTEvent.MOUSE_EVENT_MASK); < WindowManager.getDefault().getMainWindow().addWindowStateListener(hideListener); < WindowManager.getDefault().getMainWindow().addComponentListener(hideListener); < resizePopup(); < popupWindow.setVisible(true); < pane.requestFocus(); < // System.out.println(" window focusable=" + popupWindow.isFocusableWindow()); < } < < private void resizePopup() { < popupWindow.pack(); < Point point = new Point(0,0); < SwingUtilities.convertPointToScreen(point, this); < Dimension dim = popupWindow.getSize(); < //#63265 < Rectangle usableRect = Utilities.getUsableScreenBounds(); < Point loc = new Point(point.x + this.getSize().width + 4 - dim.width , point.y - dim.height - 5); < if (! usableRect.contains(loc)) { < loc = new Point(loc.x, point.y + 5 + this.getSize().height); < } < // +4 here because of the width of the close button in popup, we < // want the progress bars to align visually.. but there's separator in status now.. < popupWindow.setLocation(loc); < // System.out.println("count=" + count); < // System.out.println("offset =" + offset); < } < < private class HideAWTListener extends ComponentAdapter implements AWTEventListener, WindowStateListener { < public void eventDispatched(java.awt.AWTEvent aWTEvent) { < if (aWTEvent instanceof MouseEvent) { < MouseEvent mv = (MouseEvent)aWTEvent; < if (mv.getClickCount() > 0) { < Component comp = (Component)aWTEvent.getSource(); < Container par = SwingUtilities.getAncestorNamed("progresspopup", comp); //NOI18N < Container barpar = SwingUtilities.getAncestorOfClass(StatusLineComponent.class, comp); < if (par == null && barpar == null) { < hidePopup(); < } < } < } < } < < public void windowStateChanged(WindowEvent windowEvent) { < if (showingPopup) { < int oldState = windowEvent.getOldState(); < int newState = windowEvent.getNewState(); < < if (((oldState & Frame.ICONIFIED) == 0) && < ((newState & Frame.ICONIFIED) == Frame.ICONIFIED)) { < hidePopup(); < // } else if (((oldState & Frame.ICONIFIED) == Frame.ICONIFIED) && < // ((newState & Frame.ICONIFIED) == 0 )) { < // //TODO remember we showed before and show again? I guess not worth the efford, not part of spec. < } < } < < } < < public void componentResized(ComponentEvent evt) { < if (showingPopup) { < resizePopup(); < } < } < < public void componentMoved(ComponentEvent evt) { < if (showingPopup) { < resizePopup(); < } < } < < } < < private class MListener extends MouseAdapter { < public void mouseClicked(java.awt.event.MouseEvent e) { < if (e.getButton() != MouseEvent.BUTTON1) { < showMenu(e); < } else { < if (showingPopup) { < hidePopup(); < } else { < showPopup(); < } < } < } < < } < < private void showMenu(MouseEvent e) { < JPopupMenu popup = new JPopupMenu(); < popup.add(new ProgressListAction(NbBundle.getMessage(StatusLineComponent.class, "StatusLineComponent.ShowProcessList"))); < popup.add(new ViewAction()); < popup.add(new CancelAction()); < popup.show((Component)e.getSource(), e.getX(), e.getY()); < } < < private class CancelAction extends AbstractAction { < public CancelAction() { < putValue(Action.NAME, NbBundle.getMessage(StatusLineComponent.class, "StatusLineComponent.Cancel")); < setEnabled(handle == null ? false : handle.isAllowCancel()); < < } < public void actionPerformed(ActionEvent actionEvent) { < InternalHandle hndl = handle; < if (hndl !=null && hndl.getState() == InternalHandle.STATE_RUNNING) { < String message = NbBundle.getMessage(StatusLineComponent.class, "Cancel_Question", handle.getDisplayName()); < String title = NbBundle.getMessage(StatusLineComponent.class, "Cancel_Question_Title"); < NotifyDescriptor dd = new NotifyDescriptor(message, title, < NotifyDescriptor.YES_NO_OPTION, < NotifyDescriptor.QUESTION_MESSAGE, null, null); < Object retType = DialogDisplayer.getDefault().notify(dd); < if (retType == NotifyDescriptor.YES_OPTION && hndl.getState() == InternalHandle.STATE_RUNNING) { < hndl.requestCancel(); < } < } < } < } < < private class ViewAction extends AbstractAction { < public ViewAction() { < putValue(Action.NAME, NbBundle.getMessage(StatusLineComponent.class, "StatusLineComponent.View")); < setEnabled(handle == null ? false : handle.isAllowView()); < < } < public void actionPerformed(ActionEvent actionEvent) { < if (handle != null) { < handle.requestView(); < } < } < } < < < } Index: progress/src/org/netbeans/progress/spi/InternalHandle.java =================================================================== RCS file: progress/src/org/netbeans/progress/spi/InternalHandle.java diff -N progress/src/org/netbeans/progress/spi/InternalHandle.java 0a1,347 > /* > * The contents of this file are subject to the terms of the Common Development > * and Distribution License (the License). You may not use this file except in > * compliance with the License. > * > * You can obtain a copy of the License at http://www.netbeans.org/cddl.html > * or http://www.netbeans.org/cddl.txt. > * > * When distributing Covered Code, include this CDDL Header Notice in each file > * and include the License file at http://www.netbeans.org/cddl.txt. > * If applicable, add the following below the CDDL Header, with the fields > * enclosed by brackets [] replaced by your own identifying information: > * "Portions Copyrighted [year] [name of copyright owner]" > * > * The Original Software is NetBeans. The Initial Developer of the Original > * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun > * Microsystems, Inc. All Rights Reserved. > */ > > > package org.netbeans.progress.spi; > > import java.awt.event.ActionEvent; > import java.util.ArrayList; > import java.util.Collection; > import java.util.Collections; > import java.util.List; > import java.util.logging.Level; > import java.util.logging.Logger; > import javax.swing.Action; > import javax.swing.JComponent; > import javax.swing.JProgressBar; > import javax.swing.SwingUtilities; > import org.netbeans.progress.module.*; > import org.openide.util.Cancellable; > import org.openide.util.Lookup; > > /** > * Instances provided by the ProgressHandleFactory allow the users of the API to > * notify the progress bar UI about changes in the state of the running task. > * @author Milos Kleint (mkleint@netbeans.org) > */ > public final class InternalHandle { > > private String displayName; > private boolean allowCancel; > private boolean allowBackground; > private boolean customPlaced = false; > private int state; > private int totalUnits; > private int currentUnit; > private long initialEstimate; > private long timeStarted; > private long timeLastProgress; > private String lastMessage; > private final Cancellable cancelable; > private final Action viewAction; > private final boolean userInitiated; > private int initialDelay = Controller.INITIAL_DELAY; > private Controller controller; > > public static final int STATE_INITIALIZED = 0; > public static final int STATE_RUNNING = 1; > public static final int STATE_FINISHED = 2; > public static final int STATE_REQUEST_STOP = 3; > > public static final int NO_INCREASE = -2; > > > > /** Creates a new instance of ProgressHandle */ > public InternalHandle(String displayName, > Cancellable cancel, > boolean userInitiated, > Action view) { > this.displayName = displayName; > this.userInitiated = userInitiated; > state = STATE_INITIALIZED; > totalUnits = 0; > lastMessage = null; > cancelable = cancel; > viewAction = view; > } > > public String getDisplayName() { > return displayName; > } > > /** > * XXX - called from UI, threading > */ > public synchronized int getState() { > return state; > } > > public boolean isAllowCancel() { > return cancelable != null && !isCustomPlaced(); > } > > public boolean isAllowView() { > return viewAction != null && !isCustomPlaced(); > } > > > public boolean isCustomPlaced() { > return customPlaced; > } > > public boolean isUserInitialized() { > return userInitiated; > } > > private int getCurrentUnit() { > return currentUnit; > } > > public int getTotalUnits() { > return totalUnits; > } > > public void setInitialDelay(int millis) { > if (state != STATE_INITIALIZED) { > Logger.getAnonymousLogger().warning("Setting ProgressHandle.setInitialDelay() after the task is started has no effect"); //NOI18N > return; > } > initialDelay = millis; > } > > public int getInitialDelay() { > return initialDelay; > } > > public synchronized void toIndeterminate() { > if (state != STATE_RUNNING && state != STATE_REQUEST_STOP) { > assert false : "cannot switch to indeterminate mode when not running"; > } > totalUnits = 0; > currentUnit = 0; > initialEstimate = -1; > timeLastProgress = System.currentTimeMillis(); > controller.toIndeterminate(this); > } > > public synchronized void toDeterminate(int workunits, long estimate) { > if (state != STATE_RUNNING && state != STATE_REQUEST_STOP) { > assert false : "cannot switch to determinate mode when not running"; > } > if (workunits < 0) { > throw new IllegalArgumentException("number of workunits cannot be negative"); > } > totalUnits = workunits; > currentUnit = 0; > initialEstimate = estimate; > timeLastProgress = System.currentTimeMillis(); > controller.toDeterminate(this); > } > > /** > * start the progress indication for a task with known number of steps and known > * time estimate for completing the task. > * > * @param message > * @param workunits > * @param estimate estimated time to process the task in seconds > */ > public synchronized void start(String message, int workunits, long estimate) { > if (state != STATE_INITIALIZED) { > throw new IllegalStateException("Cannot call start twice on a handle"); > } > if (workunits < 0) { > throw new IllegalArgumentException("number of workunits cannot be negative"); > } > totalUnits = workunits; > currentUnit = 0; > if (message != null) { > lastMessage = message; > } > state = STATE_RUNNING; > initialEstimate = estimate; > timeStarted = System.currentTimeMillis(); > timeLastProgress = timeStarted; > > if (! customPlaced) { > controller = Controller.getDefault(); > } > > controller.start(this); > } > > /** > * finish the task, remove the task's component from the progress bar UI. > */ > public synchronized void finish() { > if (state == STATE_INITIALIZED) { > throw new IllegalStateException("Cannot finish not a started task"); > } > if (state == STATE_FINISHED) { > return; > } > state = STATE_FINISHED; > currentUnit = totalUnits; > > controller.finish(this); > } > > > /** > * > * @param message > * @param workunit > */ > public synchronized void progress(String message, int workunit) { > if (state != STATE_RUNNING && state != STATE_REQUEST_STOP) { > return; > } > > if (workunit != NO_INCREASE) { > if (workunit < currentUnit) { > throw new IllegalArgumentException("Cannot decrease processed workunit count to lower value than before"); > } > if (workunit > totalUnits) { > // seems to be the by far most frequently abused contract. Record it to log file and safely handle the case > Logger.getAnonymousLogger().log(Level.WARNING, > "Cannot process more work than scheduled. " + > "Progress handle with name \"" + getDisplayName() + "\" has requested progress to workunit no." + workunit + > " but the total number of workunits is " + totalUnits + ". That means the progress bar UI will not display real progress and will stay at 100%.", > new IllegalArgumentException() > ); > workunit = totalUnits; > } > currentUnit = workunit; > } > if (message != null) { > lastMessage = message; > } > timeLastProgress = System.currentTimeMillis(); > > controller.progress(this, message, currentUnit, > totalUnits > 0 ? getPercentageDone() : -1, > (initialEstimate == -1 ? -1 : calculateFinishEstimate())); > } > > > // XXX - called from UI, threading > > public void requestCancel() { > if (!isAllowCancel()) { > return; > } > synchronized (this) { > state = STATE_REQUEST_STOP; > } > // do not call in synchronized block because it can take a long time to process, > /// and it could slow down UI. > //TODO - call in some other thread, not AWT? what is the cancel() contract? > cancelable.cancel(); > synchronized (this) { > requestStateSnapshot(); > } > } > > ///XXX - called from UI, threading > public void requestView() { > if (!isAllowView()) { > return; > } > viewAction.actionPerformed(new ActionEvent(viewAction, ActionEvent.ACTION_PERFORMED, "performView")); > } > > // XXX - called from UI, threading > public synchronized void requestExplicitSelection() { > timeLastProgress = System.currentTimeMillis(); > controller.explicitSelection(this, currentUnit, > totalUnits > 0 ? getPercentageDone() : -1, > (initialEstimate == -1 ? -1 : calculateFinishEstimate())); > } > > public synchronized void requestDisplayNameChange(String newDisplayName) { > displayName = newDisplayName; > if (state == STATE_INITIALIZED) { > return; > } > timeLastProgress = System.currentTimeMillis(); > controller.displayNameChange(this, currentUnit, > totalUnits > 0 ? getPercentageDone() : -1, > (initialEstimate == -1 ? -1 : calculateFinishEstimate()), newDisplayName); > } > > // XXX - called from UI, threading > public synchronized ProgressEvent requestStateSnapshot() { > timeLastProgress = System.currentTimeMillis(); > return controller.snapshot(this, lastMessage, currentUnit, > totalUnits > 0 ? getPercentageDone() : -1, > (initialEstimate == -1 ? -1 : calculateFinishEstimate())); > } > > /** > * have the component in custom location, don't include in the status bar. > */ > public synchronized JComponent extractComponent() { > if (customPlaced) { > throw new IllegalStateException("Cannot retrieve progress component multiple times"); > } > if (state != STATE_INITIALIZED) { > throw new IllegalStateException("You can request custom placement of progress component only before starting the task"); > } > customPlaced = true; > ProgressUIWorkerProvider prov = (ProgressUIWorkerProvider)Lookup.getDefault().lookup(ProgressUIWorkerProvider.class); > assert prov != null; > ProgressUIWorker component = prov.getExtractedComponentWorker(); > controller = new Controller(component); > return (JComponent)component; > } > > > long calculateFinishEstimate() { > > // we are interested in seconds only > double durationSoFar = ((double)(System.currentTimeMillis() - timeStarted)) / 1000; > if (initialEstimate == -1) { > // we don't have an initial estimate, calculate by real-life data only > return (long)(durationSoFar * (totalUnits - currentUnit) / totalUnits); > } else { > // in the begining give the initial estimate more weight than in the end. > // should give us more smooth estimates > long remainingUnits = (totalUnits - currentUnit); > double remainingPortion = (double)remainingUnits / (double)totalUnits; > double currentEstimate = (double)durationSoFar / (double)currentUnit * totalUnits; > long retValue = (long)(((initialEstimate * remainingUnits * remainingPortion) > + (currentEstimate * remainingUnits * (1 - remainingPortion))) > / totalUnits); > return retValue; > } > } > /** > *public because of tests. > */ > public int getPercentageDone() { > return (int)((long)currentUnit * 100 / (long)totalUnits); > } > > public long getTimeStampStarted() { > return timeStarted; > } > > > } Index: progress/src/org/netbeans/progress/spi/ProgressEvent.java =================================================================== RCS file: progress/src/org/netbeans/progress/spi/ProgressEvent.java diff -N progress/src/org/netbeans/progress/spi/ProgressEvent.java 0a1,126 > /* > * The contents of this file are subject to the terms of the Common Development > * and Distribution License (the License). You may not use this file except in > * compliance with the License. > * > * You can obtain a copy of the License at http://www.netbeans.org/cddl.html > * or http://www.netbeans.org/cddl.txt. > * > * When distributing Covered Code, include this CDDL Header Notice in each file > * and include the License file at http://www.netbeans.org/cddl.txt. > * If applicable, add the following below the CDDL Header, with the fields > * enclosed by brackets [] replaced by your own identifying information: > * "Portions Copyrighted [year] [name of copyright owner]" > * > * The Original Software is NetBeans. The Initial Developer of the Original > * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun > * Microsystems, Inc. All Rights Reserved. > */ > > > package org.netbeans.progress.spi; > > /** > * > * @author Milos Kleint (mkleint@netbeans.org) > */ > public final class ProgressEvent { > > public static final int TYPE_START = 0; > public static final int TYPE_FINISH = 4; > public static final int TYPE_REQUEST_STOP = 3; > public static final int TYPE_PROGRESS = 1; > public static final int TYPE_SWITCH = 5; > > private InternalHandle source; > private long estimatedCompletion; > private int percentageDone; > private int workunitsDone; > private String message; > private int type; > private boolean watched; > private boolean switched; > private String displayName; > /** Creates a new instance of ProgressEvent > * @param type one of TYPE_START, TYPE_REQUEST_STOP, TYPE_FINISH, TYPE_SWITCHED > */ > public ProgressEvent(InternalHandle src, int type, boolean isWatched) { > source = src; > estimatedCompletion = -1; > percentageDone = -1; > workunitsDone = -1; > message = null; > this.type = type; > watched = isWatched; > switched = (type == TYPE_SWITCH); > } > /** > * @param percentage completed work percentage > * @param estimate estimate of completion in seconds > */ > public ProgressEvent(InternalHandle src, String msg, int units, int percentage, long estimate, boolean isWatched) { > this(src, TYPE_PROGRESS, isWatched); > workunitsDone = units; > percentageDone = percentage; > estimatedCompletion = estimate; > message = msg; > } > public ProgressEvent(InternalHandle src, String msg, int units, int percentage, long estimate, boolean isWatched, String displayName) { > this(src, msg, units, percentage, estimate, isWatched); > this.displayName = displayName; > } > > public InternalHandle getSource() { > return source; > } > > public long getEstimatedCompletion() { > return estimatedCompletion; > } > > public int getPercentageDone() { > return percentageDone; > } > > public int getWorkunitsDone() { > return workunitsDone; > } > > public String getMessage() { > return message; > } > > public int getType() { > return type; > } > > public boolean isWatched() { > return watched; > } > > /** > * used in controller, preserve dynamic message from earlier events > * if this one doesn't have it's own. > */ > public void copyMessageFromEarlier(ProgressEvent last) { > if (message == null) { > message = last.getMessage(); > } > if (displayName == null) { > displayName = last.getDisplayName(); > } > } > > public void markAsSwitched() { > switched = true; > } > > public boolean isSwitched() { > return switched; > } > > public String getDisplayName() { > return displayName; > } > > } Index: progress/src/org/netbeans/progress/spi/ProgressUIWorker.java =================================================================== RCS file: progress/src/org/netbeans/progress/spi/ProgressUIWorker.java diff -N progress/src/org/netbeans/progress/spi/ProgressUIWorker.java 0a1,34 > /* > * The contents of this file are subject to the terms of the Common Development > * and Distribution License (the License). You may not use this file except in > * compliance with the License. > * > * You can obtain a copy of the License at http://www.netbeans.org/cddl.html > * or http://www.netbeans.org/cddl.txt. > * > * When distributing Covered Code, include this CDDL Header Notice in each file > * and include the License file at http://www.netbeans.org/cddl.txt. > * If applicable, add the following below the CDDL Header, with the fields > * enclosed by brackets [] replaced by your own identifying information: > * "Portions Copyrighted [year] [name of copyright owner]" > * > * The Original Software is NetBeans. The Initial Developer of the Original > * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun > * Microsystems, Inc. All Rights Reserved. > */ > > package org.netbeans.progress.spi; > > import org.netbeans.progress.module.*; > > /** > * > * @author mkleint > */ > public interface ProgressUIWorker { > > void processProgressEvent(ProgressEvent event); > void processSelectedProgressEvent(ProgressEvent event); > > > } Index: progress/src/org/netbeans/progress/spi/ProgressUIWorkerProvider.java =================================================================== RCS file: progress/src/org/netbeans/progress/spi/ProgressUIWorkerProvider.java diff -N progress/src/org/netbeans/progress/spi/ProgressUIWorkerProvider.java 0a1,31 > /* > * The contents of this file are subject to the terms of the Common Development > * and Distribution License (the License). You may not use this file except in > * compliance with the License. > * > * You can obtain a copy of the License at http://www.netbeans.org/cddl.html > * or http://www.netbeans.org/cddl.txt. > * > * When distributing Covered Code, include this CDDL Header Notice in each file > * and include the License file at http://www.netbeans.org/cddl.txt. > * If applicable, add the following below the CDDL Header, with the fields > * enclosed by brackets [] replaced by your own identifying information: > * "Portions Copyrighted [year] [name of copyright owner]" > * > * The Original Software is NetBeans. The Initial Developer of the Original > * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun > * Microsystems, Inc. All Rights Reserved. > */ > > package org.netbeans.progress.spi; > > /** > * > * @author mkleint > */ > public interface ProgressUIWorkerProvider { > > public ProgressUIWorkerWithModel getDefaultWorker(); > > public ProgressUIWorker getExtractedComponentWorker(); > } Index: progress/src/org/netbeans/progress/spi/ProgressUIWorkerWithModel.java =================================================================== RCS file: progress/src/org/netbeans/progress/spi/ProgressUIWorkerWithModel.java diff -N progress/src/org/netbeans/progress/spi/ProgressUIWorkerWithModel.java 0a1,33 > /* > * The contents of this file are subject to the terms of the Common Development > * and Distribution License (the License). You may not use this file except in > * compliance with the License. > * > * You can obtain a copy of the License at http://www.netbeans.org/cddl.html > * or http://www.netbeans.org/cddl.txt. > * > * When distributing Covered Code, include this CDDL Header Notice in each file > * and include the License file at http://www.netbeans.org/cddl.txt. > * If applicable, add the following below the CDDL Header, with the fields > * enclosed by brackets [] replaced by your own identifying information: > * "Portions Copyrighted [year] [name of copyright owner]" > * > * The Original Software is NetBeans. The Initial Developer of the Original > * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun > * Microsystems, Inc. All Rights Reserved. > */ > > package org.netbeans.progress.spi; > > import org.netbeans.progress.module.*; > > /** > * > * @author mkleint > */ > public interface ProgressUIWorkerWithModel extends ProgressUIWorker { > > void setModel(TaskModel model); > > void showPopup(); > } Index: progress/src/org/netbeans/progress/spi/TaskModel.java =================================================================== RCS file: progress/src/org/netbeans/progress/spi/TaskModel.java diff -N progress/src/org/netbeans/progress/spi/TaskModel.java 0a1,148 > /* > * The contents of this file are subject to the terms of the Common Development > * and Distribution License (the License). You may not use this file except in > * compliance with the License. > * > * You can obtain a copy of the License at http://www.netbeans.org/cddl.html > * or http://www.netbeans.org/cddl.txt. > * > * When distributing Covered Code, include this CDDL Header Notice in each file > * and include the License file at http://www.netbeans.org/cddl.txt. > * If applicable, add the following below the CDDL Header, with the fields > * enclosed by brackets [] replaced by your own identifying information: > * "Portions Copyrighted [year] [name of copyright owner]" > * > * The Original Software is NetBeans. The Initial Developer of the Original > * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun > * Microsystems, Inc. All Rights Reserved. > */ > > > package org.netbeans.progress.spi; > > import javax.swing.DefaultListModel; > import javax.swing.DefaultListSelectionModel; > import javax.swing.ListModel; > import javax.swing.ListSelectionModel; > import javax.swing.event.ListDataListener; > import javax.swing.event.ListSelectionListener; > import org.netbeans.progress.module.*; > > /** > * > * @author Milos Kleint (mkleint@netbeans.org) > */ > public final class TaskModel { > private DefaultListSelectionModel selectionModel; > private DefaultListModel model; > private InternalHandle explicit; > /** Creates a new instance of TaskModel */ > public TaskModel() { > selectionModel = new DefaultListSelectionModel(); > model = new DefaultListModel(); > } > > > > public void addHandle(InternalHandle handle) { > model.addElement(handle); > if (handle.isUserInitialized() && explicit == null) { > selectionModel.setSelectionInterval(model.size() - 1, model.size() - 1); > } > } > > public void removeHandle(InternalHandle handle) { > if (explicit == handle) { > explicit = null; > } > int index = model.indexOf(handle); > if (selectionModel.getMinSelectionIndex() == index) { > // if we are removing the handle that is selected, do tricks with selection > // too figure out which one should be sleected now > changeSelection(index); > } > InternalHandle selectedHandle = getSelectedHandle(); > model.removeElement(handle); > if (selectedHandle != null) { > selectionModel.setSelectionInterval(model.indexOf(selectedHandle), model.indexOf(selectedHandle)); > } else { > //TODO what to do here? > selectionModel.clearSelection(); > } > > } > > /** > * if we are removing the handle that is selected, do tricks with selection > * too figure out which one should be sleected no > */ > private void changeSelection(int current) { > InternalHandle last = null; > for (int i = 0; i < model.size(); i++) { > if (current != i) { > InternalHandle handle = (InternalHandle)model.getElementAt(i); > if (handle.isUserInitialized()) { > last = handle; > } else if (last == null) { > last = handle; > } > } > } > if (last != null) { > selectionModel.setSelectionInterval(model.indexOf(last), model.indexOf(last)); > } else { > selectionModel.clearSelection(); > } > > } > > public void explicitlySelect(InternalHandle handle) { > explicit = handle; > int index = model.indexOf(explicit); > if (index == -1) { > //TODO what? > } > selectionModel.setSelectionInterval(index, index); > } > > public InternalHandle getExplicitSelection() { > return explicit; > } > > public int getSize() { > return model.size(); > } > > > public InternalHandle[] getHandles() { > InternalHandle[] handles = new InternalHandle[model.size()]; > model.copyInto(handles); > return handles; > } > > public InternalHandle getSelectedHandle() { > int select = selectionModel.getMinSelectionIndex(); > if (select != -1) { > if (select >= 0 && select < model.size()) { > return (InternalHandle)model.getElementAt(selectionModel.getMinSelectionIndex()); > } > } > return null; > } > > public void addListSelectionListener(ListSelectionListener listener) { > selectionModel.addListSelectionListener(listener); > } > > public void removeListSelectionListener(ListSelectionListener listener) { > selectionModel.removeListSelectionListener(listener); > } > > public void addListDataListener(ListDataListener listener) { > model.addListDataListener(listener); > } > > public void removeListDataListener(ListDataListener listener) { > model.removeListDataListener(listener); > } > } Index: progress/test/unit/src/org/netbeans/api/progress/ProgressHandleFactoryTest.java =================================================================== RCS file: /cvs/core/progress/test/unit/src/org/netbeans/api/progress/ProgressHandleFactoryTest.java,v retrieving revision 1.4 diff -r1.4 ProgressHandleFactoryTest.java 22a23 > import javax.swing.JProgressBar; 24,25c25 < import org.netbeans.progress.module.InternalHandle; < import org.netbeans.progress.module.ui.NbProgressBar; --- > import org.netbeans.progress.spi.InternalHandle; 72,73c72,73 < assertEquals(15, ((NbProgressBar) component).getMaximum()); < assertEquals(2, ((NbProgressBar) component).getValue()); --- > assertEquals(15, ((JProgressBar) component).getMaximum()); > assertEquals(2, ((JProgressBar) component).getValue()); 85,86c85,86 < assertEquals(20, ((NbProgressBar) component).getMaximum()); < assertEquals(0, ((NbProgressBar) component).getValue()); --- > assertEquals(20, ((JProgressBar) component).getMaximum()); > assertEquals(0, ((JProgressBar) component).getValue()); Index: progress/test/unit/src/org/netbeans/api/progress/ProgressHandleTest.java =================================================================== RCS file: /cvs/core/progress/test/unit/src/org/netbeans/api/progress/ProgressHandleTest.java,v retrieving revision 1.8 diff -r1.8 ProgressHandleTest.java 21a22 > import java.lang.reflect.Method; 27,30c28,30 < import org.netbeans.progress.module.InternalHandle; < import org.netbeans.progress.module.ProgressUIWorker; < import org.netbeans.progress.module.ProgressEvent; < import org.netbeans.progress.module.ui.NbProgressBar; --- > import org.netbeans.progress.spi.InternalHandle; > import org.netbeans.progress.spi.ProgressUIWorker; > import org.netbeans.progress.spi.ProgressEvent; 309,322c309,322 < < class MyFrame extends JFrame implements Runnable { < < JComponent component; < < public MyFrame(JComponent component) { < getContentPane().add(component); < } < < public void run() { < setVisible(true); < setBounds(0, 0, 400, 50); < } < } --- > > class MyFrame extends JFrame implements Runnable { > > JComponent component; > > public MyFrame(JComponent component) { > getContentPane().add(component); > } > > public void run() { > setVisible(true); > setBounds(0, 0, 400, 50); > } > } 349,351c349,357 < } < < assertFalse("The progress bar is still indeterminate!", ((NbProgressBar)component).isIndeterminate()); --- > } > try { > Method meth = component.getClass().getMethod("isIndeterminate", new Class[0]); > Boolean bool = (Boolean)meth.invoke(component, new Object[0]); > assertFalse("The progress bar is still indeterminate!", bool.booleanValue()); > } catch (Exception ex) { > ex.printStackTrace(); > fail(); > } Index: progress/test/unit/src/org/netbeans/api/progress/aggregate/AggregateProgressHandleTest.java =================================================================== RCS file: /cvs/core/progress/test/unit/src/org/netbeans/api/progress/aggregate/AggregateProgressHandleTest.java,v retrieving revision 1.3 diff -r1.3 AggregateProgressHandleTest.java 24,25c24,25 < import org.netbeans.progress.module.ProgressUIWorker; < import org.netbeans.progress.module.ProgressEvent; --- > import org.netbeans.progress.spi.ProgressUIWorker; > import org.netbeans.progress.spi.ProgressEvent; Index: progressui/.cvsignore =================================================================== RCS file: progressui/.cvsignore diff -N progressui/.cvsignore 0a1 > build Index: progressui/build.xml =================================================================== RCS file: progressui/build.xml diff -N progressui/build.xml 0a1,5 > > > Builds, tests, and runs the project org.netbeans.modules.progress.ui > > Index: progressui/manifest.mf =================================================================== RCS file: progressui/manifest.mf diff -N progressui/manifest.mf 0a1,7 > Manifest-Version: 1.0 > OpenIDE-Module: org.netbeans.modules.progress.ui > OpenIDE-Module-Layer: org/netbeans/modules/progress/ui/layer.xml > OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/progress/ui/Bundle.properties > OpenIDE-Module-Specification-Version: 1.0 > OpenIDE-Module-Provides: org.netbeans.spi.progress.ProgressUIWorkerProvider > Index: progressui/nbproject/project.properties =================================================================== RCS file: progressui/nbproject/project.properties diff -N progressui/nbproject/project.properties 0a1,4 > # Sample ResourceBundle properties file > is.autoload=true > javac.compilerargs=-Xlint:unchecked > javac.source=1.5 Index: progressui/nbproject/project.xml =================================================================== RCS file: progressui/nbproject/project.xml diff -N progressui/nbproject/project.xml 0a1,45 > > > org.netbeans.modules.apisupport.project > > > org.netbeans.modules.progress.ui > > > org.netbeans.api.progress > > > > 1 > > > > > org.openide.dialogs > > > > 7.0 > > > > org.openide.util > > > > 7.3 > > > > org.openide.windows > > > > 6.7 > > > > > > > Index: progressui/src/META-INF/services/org.netbeans.progress.spi.ProgressUIWorkerProvider =================================================================== RCS file: progressui/src/META-INF/services/org.netbeans.progress.spi.ProgressUIWorkerProvider diff -N progressui/src/META-INF/services/org.netbeans.progress.spi.ProgressUIWorkerProvider 0a1 > org.netbeans.modules.progress.ui.ProviderImpl \ No newline at end of file Index: progressui/src/org/netbeans/modules/progress/ui/Bundle.properties =================================================================== RCS file: progressui/src/org/netbeans/modules/progress/ui/Bundle.properties diff -N progressui/src/org/netbeans/modules/progress/ui/Bundle.properties 0a1,28 > # The contents of this file are subject to the terms of the Common Development > # and Distribution License (the License). You may not use this file except in > # compliance with the License. > # > # You can obtain a copy of the License at http://www.netbeans.org/cddl.html > # or http://www.netbeans.org/cddl.txt. > # > # When distributing Covered Code, include this CDDL Header Notice in each file > # and include the License file at http://www.netbeans.org/cddl.txt. > # If applicable, add the following below the CDDL Header, with the fields > # enclosed by brackets [] replaced by your own identifying information: > # "Portions Copyrighted [year] [name of copyright owner]" > # > # The Original Software is NetBeans. The Initial Developer of the Original > # Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun > # Microsystems, Inc. All Rights Reserved. > > NbProgressBar.tooltip1={0} tasks running. Click for details. > NbProgressBar.tooltip2={0} task running. Click for details. > ListComponent.btnClose.tooltip=Click to cancel process > ListComponent.bar.tooltip=Click to watch the process > Cancel_Question=Are you sure you want to cancel {0}? > Cancel_Question_Title=Cancel Running Task > StatusLineComponent.ShowProcessList=Show Processes > StatusLineComponent.Cancel=Cancel Process > StatusLineComponent.View=Show Output > ListComponent.Watch=Watch Process > OpenIDE-Module-Name=Progress UI Index: progressui/src/org/netbeans/modules/progress/ui/ListComponent.java =================================================================== RCS file: progressui/src/org/netbeans/modules/progress/ui/ListComponent.java diff -N progressui/src/org/netbeans/modules/progress/ui/ListComponent.java 0a1,390 > /* > * The contents of this file are subject to the terms of the Common Development > * and Distribution License (the License). You may not use this file except in > * compliance with the License. > * > * You can obtain a copy of the License at http://www.netbeans.org/cddl.html > * or http://www.netbeans.org/cddl.txt. > * > * When distributing Covered Code, include this CDDL Header Notice in each file > * and include the License file at http://www.netbeans.org/cddl.txt. > * If applicable, add the following below the CDDL Header, with the fields > * enclosed by brackets [] replaced by your own identifying information: > * "Portions Copyrighted [year] [name of copyright owner]" > * > * The Original Software is NetBeans. The Initial Developer of the Original > * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun > * Microsystems, Inc. All Rights Reserved. > */ > > package org.netbeans.modules.progress.ui; > > import java.awt.Color; > import java.awt.Component; > import java.awt.Cursor; > import java.awt.Dimension; > import java.awt.Font; > import java.awt.Image; > import java.awt.LayoutManager; > import java.awt.event.ActionEvent; > import java.awt.event.FocusListener; > import java.awt.event.KeyEvent; > import java.awt.event.MouseAdapter; > import java.awt.event.MouseEvent; > import javax.swing.AbstractAction; > import javax.swing.Action; > import javax.swing.BorderFactory; > import javax.swing.Icon; > import javax.swing.ImageIcon; > import javax.swing.JButton; > import javax.swing.JLabel; > import javax.swing.JPanel; > import javax.swing.JPopupMenu; > import javax.swing.KeyStroke; > import javax.swing.UIManager; > import org.netbeans.progress.spi.InternalHandle; > import org.netbeans.progress.spi.ProgressEvent; > import org.openide.DialogDisplayer; > import org.openide.NotifyDescriptor; > import org.openide.util.NbBundle; > import org.openide.util.Utilities; > > /** > * > * @author mkleint > */ > public class ListComponent extends JPanel { > private NbProgressBar bar; > private JLabel mainLabel; > private JLabel dynaLabel; > private JButton closeButton; > private InternalHandle handle; > private boolean watched; > private Action cancelAction; > private Color selectBgColor; > private Color selectFgColor; > private Color bgColor; > private Color fgColor; > private Color dynaFgColor; > private int mainHeight; > private int dynaHeight; > > /** Creates a new instance of ListComponent */ > public ListComponent(InternalHandle hndl) { > setFocusable(true); > setRequestFocusEnabled(true); > // setVerifyInputWhenFocusTarget(false); > mainLabel = new JLabel(); > dynaLabel = new JLabel(); > // in gtk, the panel is non-opague, meaning we cannot color background > // #59419 > setOpaque(true); > dynaLabel.setFont(dynaLabel.getFont().deriveFont((float) (dynaLabel.getFont().getSize() - 2))); > bar = new NbProgressBar(); > handle = hndl; > Color bg = UIManager.getColor("nbProgressBar.popupText.background"); > if (bg != null) { > setBackground(bg); > mainLabel.setBackground(bg); > dynaLabel.setBackground(bg); > } > bgColor = getBackground(); > Color dynaFg = UIManager.getColor("nbProgressBar.popupDynaText.foreground"); > if (dynaFg != null) { > dynaLabel.setForeground(dynaFg); > } > dynaFgColor = dynaLabel.getForeground(); > fgColor = UIManager.getColor("nbProgressBar.popupText.foreground"); > if (fgColor != null) { > mainLabel.setForeground(fgColor); > } > fgColor = mainLabel.getForeground(); > selectBgColor = UIManager.getColor("nbProgressBar.popupText.selectBackground"); > if (selectBgColor == null) { > selectBgColor = UIManager.getColor("List.selectionBackground"); > } > selectFgColor = UIManager.getColor("nbProgressBar.popupText.selectForeground"); > if (selectFgColor == null) { > selectFgColor = UIManager.getColor("List.selectionForeground"); > } > bar.setToolTipText(NbBundle.getMessage(ListComponent.class, "ListComponent.bar.tooltip")); > bar.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); > //start figure out height > mainLabel.setText("XYZ"); > dynaLabel.setText("XYZ"); > mainHeight = mainLabel.getPreferredSize().height; > dynaHeight = dynaLabel.getPreferredSize().height; > mainLabel.setText(null); > dynaLabel.setText(null); > //end figure out height > > setLayout(new CustomLayout()); > add(mainLabel); > add(bar); > MListener list = new MListener(); > if (handle.isAllowCancel()) { > cancelAction = new CancelAction(false); > closeButton = new JButton(cancelAction); > closeButton.setBorderPainted(false); > closeButton.setBorder(BorderFactory.createEmptyBorder()); > closeButton.setOpaque(false); > > closeButton.setToolTipText(NbBundle.getMessage(ListComponent.class, "ListComponent.btnClose.tooltip")); > add(closeButton); > if (handle.getState() != InternalHandle.STATE_RUNNING) { > closeButton.setEnabled(false); > } > } > add(dynaLabel); > setBorder(BorderFactory.createEmptyBorder()); > addMouseListener(list); > bar.addMouseListener(list); > mainLabel.addMouseListener(list); > dynaLabel.addMouseListener(list); > if (handle.isAllowCancel()) { > closeButton.addMouseListener(list); > } > > mainLabel.setText(handle.getDisplayName()); > NbProgressBar.setupBar(handle, bar); > addFocusListener(new FocusListener() { > public void focusGained(java.awt.event.FocusEvent e) { > if (!e.isTemporary()) { > setBackground(selectBgColor); > mainLabel.setBackground(selectBgColor); > dynaLabel.setBackground(selectBgColor); > mainLabel.setForeground(selectFgColor); > // TODO assuming now that dynalabel has always the same foreground color > // seems to be the case according to the spec > scrollRectToVisible(getBounds()); > } > } > > public void focusLost(java.awt.event.FocusEvent e) { > if (!e.isTemporary()) { > setBackground(bgColor); > mainLabel.setBackground(bgColor); > dynaLabel.setBackground(bgColor); > mainLabel.setForeground(fgColor); > // TODO assuming now that dynalabel has always the same foreground color > // seems to be the case according to the spec > > } > } > > }); > > } > > > Action getCancelAction() { > return cancelAction; > } > > InternalHandle getHandle() { > return handle; > } > > void processProgressEvent(ProgressEvent event) { > if (event.getType() == ProgressEvent.TYPE_PROGRESS || > event.getType() == ProgressEvent.TYPE_SWITCH) { > if (event.getSource() != handle) { > throw new IllegalStateException(); > } > if (event.isSwitched()) { > NbProgressBar.setupBar(event.getSource(), bar); > } > if (event.getWorkunitsDone() > 0) { > bar.setValue(event.getWorkunitsDone()); > } > bar.setString(StatusLineComponent.getBarString(event.getPercentageDone(), event.getEstimatedCompletion())); > if (event.getMessage() != null) { > dynaLabel.setText(event.getMessage()); > } > if (event.getSource().getState() == InternalHandle.STATE_REQUEST_STOP) { > closeButton.setEnabled(false); > } > if (event.getDisplayName() != null) { > mainLabel.setText(event.getDisplayName()); > } > } else { > throw new IllegalStateException(); > } > } > > void markAsActive(boolean sel) { > if (sel == watched) { > return; > } > watched = sel; > if (sel) { > mainLabel.setFont(mainLabel.getFont().deriveFont(Font.BOLD)); > } else { > mainLabel.setFont(mainLabel.getFont().deriveFont(Font.PLAIN)); > } > if (mainLabel.isVisible()) { > mainLabel.repaint(); > } > } > > private class MListener extends MouseAdapter { > public void mouseClicked(MouseEvent e) { > if (e.getSource() == bar) { > handle.requestExplicitSelection(); > // markAsSelected(true); > } > if (e.getClickCount() > 1 && (e.getSource() == mainLabel || e.getSource() == dynaLabel)) { > handle.requestView(); > } > if (e.getButton() != e.BUTTON1) { > showMenu(e); > } else { > ListComponent.this.requestFocus(); > } > > // System.out.println("list component requesting focus.."); > } > } > > private void showMenu(MouseEvent e) { > JPopupMenu popup = new JPopupMenu(); > //mark teh popup for the status line awt listener > popup.setName("progresspopup"); > popup.add(new ViewAction()); > popup.add(new WatchAction()); > popup.add(new CancelAction(true)); > popup.show((Component)e.getSource(), e.getX(), e.getY()); > } > > private class CancelAction extends AbstractAction { > CancelAction(boolean text) { > if (text) { > putValue(Action.NAME, NbBundle.getMessage(ListComponent.class, "StatusLineComponent.Cancel")); > putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0)); > } else { > Image icon = (Image)UIManager.get("nb.progress.cancel.icon"); > if (icon == null) { > // for custom L&F? > icon = Utilities.loadImage("org/netbeans/progress/module/resources/buton.png"); > } > putValue(Action.SMALL_ICON, new ImageIcon(icon)); > } > setEnabled(handle == null ? false : handle.isAllowCancel()); > } > > public void actionPerformed(ActionEvent actionEvent) { > if (handle.getState() == InternalHandle.STATE_RUNNING) { > String message = NbBundle.getMessage(ListComponent.class, "Cancel_Question", handle.getDisplayName()); > String title = NbBundle.getMessage(ListComponent.class, "Cancel_Question_Title"); > NotifyDescriptor dd = new NotifyDescriptor(message, title, > NotifyDescriptor.YES_NO_OPTION, > NotifyDescriptor.QUESTION_MESSAGE, null, null); > Object retType = DialogDisplayer.getDefault().notify(dd); > if (retType == NotifyDescriptor.YES_OPTION) { > handle.requestCancel(); > } > } > } > } > > private class ViewAction extends AbstractAction { > public ViewAction() { > putValue(Action.NAME, NbBundle.getMessage(ListComponent.class, "StatusLineComponent.View")); > setEnabled(handle == null ? false : handle.isAllowView()); > putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0)); > } > public void actionPerformed(ActionEvent actionEvent) { > if (handle != null) { > handle.requestView(); > } > } > } > > private class WatchAction extends AbstractAction { > public WatchAction() { > putValue(Action.NAME, NbBundle.getMessage(ListComponent.class, "ListComponent.Watch")); > putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0)); > setEnabled(true); > } > public void actionPerformed(ActionEvent actionEvent) { > if (handle != null) { > handle.requestExplicitSelection(); > } > } > } > > > private static final int UPPERMARGIN = 3; > private static final int LEFTMARGIN = 2; > private static final int BOTTOMMARGIN = 2; > private static final int BETWEENTEXTMARGIN = 3; > > static final int ITEM_WIDTH = 400; > > private class CustomLayout implements LayoutManager { > > /** > * If the layout manager uses a per-component string, > * adds the component comp to the layout, > * associating it > * with the string specified by name. > * > * @param name the string to be associated with the component > * @param comp the component to be added > */ > public void addLayoutComponent(String name, java.awt.Component comp) { > } > > /** > * Calculates the preferred size dimensions for the specified > * container, given the components it contains. > * @param parent the container to be laid out > * > * @see #minimumLayoutSize > */ > public Dimension preferredLayoutSize(java.awt.Container parent) { > int height = UPPERMARGIN + mainHeight + BETWEENTEXTMARGIN + dynaHeight + BOTTOMMARGIN; > return new Dimension(ITEM_WIDTH, height); > } > > /** > * > * Lays out the specified container. > * @param parent the container to be laid out > */ > public void layoutContainer(java.awt.Container parent) { > int parentWidth = parent.getWidth(); > int parentHeight = parent.getHeight(); > int offset = parentWidth - 18; > if (closeButton != null) { > closeButton.setBounds(offset, UPPERMARGIN, 18, mainHeight); > } > // have the bar approx 30 percent of the width > int barOffset = offset - (ITEM_WIDTH / 3); > bar.setBounds(barOffset, UPPERMARGIN, offset - barOffset, mainHeight); > mainLabel.setBounds(LEFTMARGIN, UPPERMARGIN, barOffset - LEFTMARGIN, mainHeight); > dynaLabel.setBounds(LEFTMARGIN, mainHeight + UPPERMARGIN + BETWEENTEXTMARGIN, > parentWidth - LEFTMARGIN, dynaHeight); > } > > /** > * > * Calculates the minimum size dimensions for the specified > * container, given the components it contains. > * @param parent the component to be laid out > * @see #preferredLayoutSize > */ > public Dimension minimumLayoutSize(java.awt.Container parent) { > return preferredLayoutSize(parent); > } > > /** > * Removes the specified component from the layout. > * @param comp the component to be removed > */ > public void removeLayoutComponent(java.awt.Component comp) { > } > > > } > } \ No newline at end of file Index: progressui/src/org/netbeans/modules/progress/ui/NbProgressBar.java =================================================================== RCS file: progressui/src/org/netbeans/modules/progress/ui/NbProgressBar.java diff -N progressui/src/org/netbeans/modules/progress/ui/NbProgressBar.java 0a1,116 > /* > * The contents of this file are subject to the terms of the Common Development > * and Distribution License (the License). You may not use this file except in > * compliance with the License. > * > * You can obtain a copy of the License at http://www.netbeans.org/cddl.html > * or http://www.netbeans.org/cddl.txt. > * > * When distributing Covered Code, include this CDDL Header Notice in each file > * and include the License file at http://www.netbeans.org/cddl.txt. > * If applicable, add the following below the CDDL Header, with the fields > * enclosed by brackets [] replaced by your own identifying information: > * "Portions Copyrighted [year] [name of copyright owner]" > * > * The Original Software is NetBeans. The Initial Developer of the Original > * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun > * Microsystems, Inc. All Rights Reserved. > */ > > package org.netbeans.modules.progress.ui; > > import java.awt.Color; > import java.awt.Dimension; > import javax.swing.JProgressBar; > import javax.swing.UIManager; > import org.netbeans.progress.spi.InternalHandle; > import org.netbeans.progress.spi.ProgressUIWorker; > import org.netbeans.progress.spi.ProgressEvent; > > > /** > * progress component, let just put the UI related issues here, update the state from outside > > * @author mkleint > */ > public class NbProgressBar extends JProgressBar implements ProgressUIWorker { > boolean isSetup = false; > boolean usedInStatusBar = false; > > /** Creates a new instance of NbProgressBar */ > public NbProgressBar() { > super(); > setOrientation(JProgressBar.HORIZONTAL); > setAlignmentX(0.5f); > setAlignmentY(0.5f); > Color fg = UIManager.getColor ("nbProgressBar.Foreground"); > if (fg != null) { > setForeground(fg); > } > Color bg = UIManager.getColor ("nbProgressBar.Background"); > if (bg != null) { > setBackground(bg); > } > } > > public void setUseInStatusBar(boolean use) { > usedInStatusBar = use; > } > > public Dimension getPreferredSize() { > Dimension supers = super.getPreferredSize(); > if (usedInStatusBar) { > supers.width = ListComponent.ITEM_WIDTH / 3; > } > return supers; > } > > > //--- these are used only when dealing with extracted component, when in status bar this is not used. > //------------------------------------ > > public void processProgressEvent(ProgressEvent event) { > if (event.getType() == ProgressEvent.TYPE_START || !isSetup || event.isSwitched()) { > setupBar(event.getSource(), this); > isSetup = true; > } > if (event.getType() == ProgressEvent.TYPE_PROGRESS) { > if (event.getWorkunitsDone() > 0) { > setValue(event.getWorkunitsDone()); > } > setString(StatusLineComponent.getBarString(event.getPercentageDone(), event.getEstimatedCompletion())); > } else if (event.getType() == ProgressEvent.TYPE_FINISH) { > boolean wasIndetermenite = isIndeterminate(); > setIndeterminate(false); > setMaximum(event.getSource().getTotalUnits()); > setValue(event.getSource().getTotalUnits()); > if (wasIndetermenite) { > setStringPainted(false); > } else { > setString(StatusLineComponent.getBarString(100, -1)); > } > } > } > > public void processSelectedProgressEvent(ProgressEvent event) { > // ignore we'return always processing just one selected component > } > > > static void setupBar(InternalHandle handle, NbProgressBar bar) { > int total = handle.getTotalUnits(); > if (total < 1) { > // macosx workaround.. > bar.setValue(bar.getMaximum()); > bar.setIndeterminate(true); > bar.setStringPainted(false); > } else { > bar.setStringPainted(true); > bar.setIndeterminate(false); > bar.setMaximum(total); > bar.setMinimum(0); > bar.setValue(0); > } > bar.setString(" "); > } > } \ No newline at end of file Index: progressui/src/org/netbeans/modules/progress/ui/PopupPane.java =================================================================== RCS file: progressui/src/org/netbeans/modules/progress/ui/PopupPane.java diff -N progressui/src/org/netbeans/modules/progress/ui/PopupPane.java 0a1,278 > /* > * The contents of this file are subject to the terms of the Common Development > * and Distribution License (the License). You may not use this file except in > * compliance with the License. > * > * You can obtain a copy of the License at http://www.netbeans.org/cddl.html > * or http://www.netbeans.org/cddl.txt. > * > * When distributing Covered Code, include this CDDL Header Notice in each file > * and include the License file at http://www.netbeans.org/cddl.txt. > * If applicable, add the following below the CDDL Header, with the fields > * enclosed by brackets [] replaced by your own identifying information: > * "Portions Copyrighted [year] [name of copyright owner]" > * > * The Original Software is NetBeans. The Initial Developer of the Original > * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun > * Microsystems, Inc. All Rights Reserved. > */ > > > package org.netbeans.modules.progress.ui; > > import java.awt.Color; > import java.awt.Component; > import java.awt.Dimension; > import java.awt.Graphics; > import java.awt.GridLayout; > import java.awt.Insets; > import java.awt.Toolkit; > import java.awt.event.ActionEvent; > import java.awt.event.KeyEvent; > import java.util.HashSet; > import java.util.Iterator; > import javax.swing.AbstractAction; > import javax.swing.Action; > import javax.swing.BorderFactory; > import javax.swing.JComponent; > import javax.swing.JPanel; > import javax.swing.JScrollPane; > import javax.swing.KeyStroke; > import javax.swing.UIManager; > import javax.swing.border.Border; > import org.netbeans.progress.spi.InternalHandle; > > /** > * > * @author mkleint > */ > public class PopupPane extends JScrollPane { > private JPanel view; > private HashSet listComponents; > /** Creates a new instance of PopupPane */ > private ListComponent selected; > > public PopupPane() { > listComponents = new HashSet(); > view = new JPanel(); > GridLayout grid = new GridLayout(0, 1); > grid.setHgap(0); > grid.setVgap(0); > view.setLayout(grid); > view.setBorder(BorderFactory.createEmptyBorder()); > setName("progresspopup"); //NOI18N > setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); > setViewportView(view); > setFocusable(true); > setRequestFocusEnabled(true); > > Action down = new MoveDownAction(); > getActionMap().put("Move-Down", down); > getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "Move-Down"); > getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "Move-Down"); > > Action up = new MoveUpAction(); > getActionMap().put("Move-Up", up); > getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "Move-Up"); > getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "Move-Up"); > Action cancel = new CancelAction(); > getActionMap().put("Cancel-Task", cancel); > getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), "Cancel-Task"); > getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), "Cancel-Task"); > > Action select = new SelectAction(); > getActionMap().put("select-task", select); > getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "select-task"); > getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "select-task"); > > > setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); > // addFocusListener(new FocusListener() { > // public void focusLost(java.awt.event.FocusEvent e) { > // System.out.println("popup focus gained temp?=" + e.isTemporary()); > // } > // > // public void focusGained(java.awt.event.FocusEvent e) { > // System.out.println("popup focus lost temporary?=" + e.isTemporary()); > // } > // > // }); > } > > public void addListComponent(ListComponent lst) { > listComponents.add(lst); > if (view.getComponentCount() > 0) { > JComponent previous = (JComponent)view.getComponent(view.getComponentCount() - 1); > previous.setBorder(new BottomLineBorder()); > } > lst.setBorder(BorderFactory.createEmptyBorder()); > view.add(lst); > if (listComponents.size() > 3) { > setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); > } else { > setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER); > } > } > > public void removeListComponent(InternalHandle handle) { > Iterator it = listComponents.iterator(); > while (it.hasNext()) { > ListComponent comp = (ListComponent)it.next(); > if (comp.getHandle() == handle) { > view.remove(comp); > it.remove(); > break; > } > } > if (listComponents.size() > 3) { > setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); > } else { > setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER); > } > } > > public Dimension getPreferredSize() { > int count = view.getComponentCount(); > int height = count > 0 ? view.getComponent(0).getPreferredSize().height : 0; > int offset = count > 3 ? height * 3 + 5 : (count * height) + 5; > // 22 is the width of the additional scrollbar > return new Dimension(count >3 ? ListComponent.ITEM_WIDTH + 22 > : ListComponent.ITEM_WIDTH + 2, offset); > } > > /** > * bold font is now used not only for explicitly selected items, but for any > * change in currently selected task. > */ > public void updateBoldFont(InternalHandle handle) { > Iterator it = listComponents.iterator(); > while (it.hasNext()) { > ListComponent comp = (ListComponent)it.next(); > comp.markAsActive(handle == comp.getHandle()); > } > } > > > > private static class BottomLineBorder implements Border { > private Insets ins = new Insets(0, 0, 1, 0); > private Color col = new Color(221, 229, 248); > > public BottomLineBorder () {} > > public Insets getBorderInsets(Component c) { > return ins; > } > > public boolean isBorderOpaque() { > return false; > } > > public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { > Color old = g.getColor(); > g.setColor(col); > g.drawRect(x, y + height - 2, width, 1); > g.setColor(old); > } > } > > private int findIndex(Component comp) { > Component[] comps = view.getComponents(); > for (int i = 0; i < comps.length; i++) { > if (comps[i] == comp) { > return i; > } > } > return -1; > } > > public void requestFocus() { > //#63666 - don't focus any of the tasks explicitly, wait for user action. > // if (view.getComponentCount() > 1) { > // if (selected == null || !selected.isDisplayable()) { > // selected = (ListComponent)view.getComponent(0); > // } > // selected.requestFocus(); > // } else { > super.requestFocus(); > // } > } > > private class MoveDownAction extends AbstractAction { > > MoveDownAction() { > } > > public void actionPerformed(ActionEvent actionEvent) { > int index = -1; > if (selected != null) { > index = findIndex(selected); > } > index = index + 1; > if (index >= PopupPane.this.view.getComponentCount()) { > index = 0; > } > selected = (ListComponent)PopupPane.this.view.getComponent(index); > selected.requestFocus(); > } > > } > > private class MoveUpAction extends AbstractAction { > > MoveUpAction() { > } > > public void actionPerformed(ActionEvent actionEvent) { > int index = PopupPane.this.view.getComponentCount(); > if (selected != null) { > index = findIndex(selected); > // selected.setBackground(new Color(249, 249, 249)); > } > index = index - 1; > if (index < 0) { > index = PopupPane.this.view.getComponentCount() - 1; > } > selected = (ListComponent)PopupPane.this.view.getComponent(index); > selected.requestFocus(); > // selected.setBackground(selectBgColor); > // selected.scrollRectToVisible(selected.getBounds()); > } > } > > private class CancelAction extends AbstractAction { > public CancelAction () {} > > public void actionPerformed(ActionEvent actionEvent) { > if (selected != null) { > Action act = selected.getCancelAction(); > if (act != null) { > act.actionPerformed(actionEvent); > } else { > Toolkit.getDefaultToolkit().beep(); > } > } > } > } > > private class SelectAction extends AbstractAction { > public SelectAction () {} > > public void actionPerformed(ActionEvent actionEvent) { > if (selected != null) { > selected.getHandle().requestExplicitSelection(); > } > } > } > > private class ViewAction extends AbstractAction { > public ViewAction () {} > > public void actionPerformed(ActionEvent actionEvent) { > if (selected != null) { > selected.getHandle().requestView(); > } > } > } > > } Index: progressui/src/org/netbeans/modules/progress/ui/ProviderImpl.java =================================================================== RCS file: progressui/src/org/netbeans/modules/progress/ui/ProviderImpl.java diff -N progressui/src/org/netbeans/modules/progress/ui/ProviderImpl.java 0a1,44 > /* > * The contents of this file are subject to the terms of the Common Development > * and Distribution License (the License). You may not use this file except in > * compliance with the License. > * > * You can obtain a copy of the License at http://www.netbeans.org/cddl.html > * or http://www.netbeans.org/cddl.txt. > * > * When distributing Covered Code, include this CDDL Header Notice in each file > * and include the License file at http://www.netbeans.org/cddl.txt. > * If applicable, add the following below the CDDL Header, with the fields > * enclosed by brackets [] replaced by your own identifying information: > * "Portions Copyrighted [year] [name of copyright owner]" > * > * The Original Software is NetBeans. The Initial Developer of the Original > * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun > * Microsystems, Inc. All Rights Reserved. > */ > > package org.netbeans.modules.progress.ui; > > import org.netbeans.progress.spi.ProgressUIWorker; > import org.netbeans.progress.spi.ProgressUIWorkerProvider; > import org.netbeans.progress.spi.ProgressUIWorkerWithModel; > > /** > * > * @author mkleint > */ > public class ProviderImpl implements ProgressUIWorkerProvider { > > /** Creates a new instance of ProviderImpl */ > public ProviderImpl() { > } > > public ProgressUIWorkerWithModel getDefaultWorker() { > return new StatusLineComponent(); > } > > public ProgressUIWorker getExtractedComponentWorker() { > return new NbProgressBar(); > } > > } Index: progressui/src/org/netbeans/modules/progress/ui/StatusLineComponent.java =================================================================== RCS file: progressui/src/org/netbeans/modules/progress/ui/StatusLineComponent.java diff -N progressui/src/org/netbeans/modules/progress/ui/StatusLineComponent.java 0a1,465 > /* > * The contents of this file are subject to the terms of the Common Development > * and Distribution License (the License). You may not use this file except in > * compliance with the License. > * > * You can obtain a copy of the License at http://www.netbeans.org/cddl.html > * or http://www.netbeans.org/cddl.txt. > * > * When distributing Covered Code, include this CDDL Header Notice in each file > * and include the License file at http://www.netbeans.org/cddl.txt. > * If applicable, add the following below the CDDL Header, with the fields > * enclosed by brackets [] replaced by your own identifying information: > * "Portions Copyrighted [year] [name of copyright owner]" > * > * The Original Software is NetBeans. The Initial Developer of the Original > * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun > * Microsystems, Inc. All Rights Reserved. > */ > > > package org.netbeans.modules.progress.ui; > import java.awt.AWTEvent; > import java.awt.Component; > import java.awt.Container; > import java.awt.Cursor; > import java.awt.Dimension; > import java.awt.FlowLayout; > import java.awt.Frame; > import java.awt.Point; > import java.awt.Rectangle; > import java.awt.Toolkit; > import java.awt.event.AWTEventListener; > import java.awt.event.ActionEvent; > import java.awt.event.ComponentAdapter; > import java.awt.event.ComponentEvent; > import java.awt.event.KeyEvent; > import java.awt.event.MouseAdapter; > import java.awt.event.MouseEvent; > import java.awt.event.MouseListener; > import java.awt.event.WindowEvent; > import java.awt.event.WindowStateListener; > import java.util.HashMap; > import java.util.Map; > import javax.swing.AbstractAction; > import javax.swing.Action; > import javax.swing.BorderFactory; > import javax.swing.JComponent; > import javax.swing.JLabel; > import javax.swing.JPanel; > import javax.swing.JPopupMenu; > import javax.swing.JSeparator; > import javax.swing.JWindow; > import javax.swing.KeyStroke; > import javax.swing.Popup; > import javax.swing.SwingUtilities; > import javax.swing.event.ListDataEvent; > import javax.swing.event.ListDataListener; > import javax.swing.event.ListSelectionEvent; > import javax.swing.event.ListSelectionListener; > import org.netbeans.progress.spi.InternalHandle; > import org.netbeans.progress.spi.ProgressUIWorker; > import org.netbeans.progress.spi.ProgressEvent; > import org.netbeans.progress.module.ProgressListAction; > import org.netbeans.progress.spi.ProgressUIWorkerWithModel; > import org.netbeans.progress.spi.TaskModel; > import org.openide.DialogDisplayer; > import org.openide.NotifyDescriptor; > import org.openide.util.NbBundle; > import org.openide.util.Utilities; > import org.openide.windows.WindowManager; > > > /** > * > * @author Milos Kleint (mkleint@netbeans.org) > */ > public class StatusLineComponent extends JPanel implements ProgressUIWorkerWithModel { > private NbProgressBar bar; > private JLabel label; > private JSeparator separator; > private InternalHandle handle; > private boolean showingPopup = false; > private TaskModel model; > private MouseListener mouseListener; > private HideAWTListener hideListener; > private Popup popup; > private JWindow popupWindow; > private PopupPane pane; > private Map handleComponentMap; > private final int prefferedHeight; > /** Creates a new instance of StatusLineComponent */ > public StatusLineComponent() { > handleComponentMap = new HashMap(); > label = new JLabel(); > label.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); > bar = new NbProgressBar(); > bar.setUseInStatusBar(true); > // tricks to figure out correct height. > bar.setStringPainted(true); > bar.setString("XXX"); > label.setText("XXX"); > prefferedHeight = Math.max(label.getPreferredSize().height, bar.getPreferredSize().height) + 2; > > bar.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); > // setBorder(BorderFactory.createLineBorder(Color.BLUE, 1)); > FlowLayout flay = new FlowLayout(); > flay.setVgap(1); > flay.setHgap(5); > setLayout(flay); > // HACK - put smaller font inside the progress bar to keep > // the height of the progressbar constant for determinate and indeterminate bars > // Font fnt = UIManager.getFont("ProgressBar.font"); > // bar.setFont(fnt.deriveFont(fnt.getStyle(), fnt.getSize() - 3)); > > mouseListener = new MListener(); > label.addMouseListener(mouseListener); > bar.addMouseListener(mouseListener); > addMouseListener(mouseListener); > hideListener = new HideAWTListener(); > pane = new PopupPane(); > pane.getActionMap().put("HidePopup", new AbstractAction() { > public void actionPerformed(ActionEvent actionEvent) { > // System.out.println("escape pressed - hiding"); > hidePopup(); > } > }); > pane.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "HidePopup"); > pane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "HidePopup"); > separator = new JSeparator(JSeparator.VERTICAL); > separator.setPreferredSize(new Dimension(5, prefferedHeight)); > separator.setBorder(BorderFactory.createEmptyBorder(1, 0, 2, 0)); > } > > public Dimension getPreferredSize() { > Dimension retValue; > retValue = super.getPreferredSize(); > retValue.height = prefferedHeight; > return retValue; > } > > public Dimension getMinimumSize() { > Dimension retValue; > retValue = super.getMinimumSize(); > retValue.height = prefferedHeight; > return retValue; > } > > public Dimension getMaximumSize() { > Dimension retValue; > retValue = super.getMaximumSize(); > retValue.height = prefferedHeight; > return retValue; > } > > public void setModel(TaskModel mod) { > model = mod; > model.addListDataListener(new Listener()); > model.addListSelectionListener(new ListSelectionListener() { > public void valueChanged(ListSelectionEvent e) { > pane.updateBoldFont(model.getSelectedHandle()); > } > }); > } > > private void setTooltipForAll() { > int size = model.getSize(); > String key = "NbProgressBar.tooltip1"; //NOI18N > if (size == 1) { > key = "NbProgressBar.tooltip2"; //NOI18N > } > String text = NbBundle.getMessage(StatusLineComponent.class, key, new Integer(size)); > setToolTipText(text); > label.setToolTipText(text); > bar.setToolTipText(text); > } > > public void processProgressEvent(ProgressEvent event) { > if (event.getType() == ProgressEvent.TYPE_START) { > createListItem(event.getSource()); > } else if (event.getType() == ProgressEvent.TYPE_PROGRESS || > event.getType() == ProgressEvent.TYPE_SWITCH) { > ListComponent comp = (ListComponent)handleComponentMap.get(event.getSource()); > if (comp == null) { > createListItem(event.getSource()); > comp = (ListComponent)handleComponentMap.get(event.getSource()); > } > comp.processProgressEvent(event); > } else if (event.getType() == ProgressEvent.TYPE_FINISH) { > removeListItem(event.getSource()); > if (model.getSelectedHandle() != null && handle != model.getSelectedHandle()) { > initiateComponent(model.getSelectedHandle().requestStateSnapshot()); > } > } > > } > > public void processSelectedProgressEvent(ProgressEvent event) { > if (event.getType() == ProgressEvent.TYPE_START) { > initiateComponent(event); > return; > } else if (event.getType() == ProgressEvent.TYPE_FINISH) { > //happens only when there's no more handles. > hidePopup(); > removeAll(); > //#63393, 61940 fix - removeAll() just invalidates. seems to work without revalidate/repaint on some platforms, fail on others. > revalidate(); > repaint(); > return; > } else { > if (event.getSource() != handle || event.isSwitched()) { > initiateComponent(event); > } > if (event.getWorkunitsDone() > 0) { > bar.setValue(event.getWorkunitsDone()); > } > bar.setString(getBarString(event.getPercentageDone(), event.getEstimatedCompletion())); > if (event.getDisplayName() != null) { > label.setText(event.getDisplayName()); > } > } > } > > static String formatEstimate(long estimate) { > long minutes = estimate / 60; > long seconds = estimate - (minutes * 60); > return "" + minutes + (seconds < 10 ? ":0" : ":") + seconds; > } > > static String getBarString(int percentage, long estimatedCompletion) { > if (estimatedCompletion != -1) { > return formatEstimate(estimatedCompletion); > } > if (percentage != -1) { > return "" + percentage + "%"; > } > return ""; > } > > private void initiateComponent(ProgressEvent event) { > handle = event.getSource(); > boolean toShow = false; > label.setText(handle.getDisplayName()); > if (label.getParent() == null) { > add(label); > toShow = true; > } > NbProgressBar.setupBar(event.getSource(), bar); > if (bar.getParent() == null) { > add(bar); > toShow = true; > } > if (separator.getParent() == null) { > add(separator); > toShow = true; > } > if (toShow) { > revalidate(); > repaint(); > } > } > > private class Listener implements ListDataListener { > public void intervalAdded(ListDataEvent e) { > setTooltipForAll(); > } > > public void intervalRemoved(ListDataEvent e) { > setTooltipForAll(); > } > > > public void contentsChanged(ListDataEvent e) { > setTooltipForAll(); > } > } > > public void hidePopup() { > if (popupWindow != null) { > // popupWindow.getContentPane().removeAll(); > popupWindow.setVisible(false); > } > Toolkit.getDefaultToolkit().removeAWTEventListener(hideListener); > WindowManager.getDefault().getMainWindow().removeWindowStateListener(hideListener); > WindowManager.getDefault().getMainWindow().removeComponentListener(hideListener); > showingPopup = false; > } > > private void createListItem(InternalHandle handle) { > ListComponent comp; > if (handleComponentMap.containsKey(handle)) { > // happens when we click to display on popup and there is a > // new handle waiting in the queue. > comp = handleComponentMap.get(handle); > } else { > comp = new ListComponent(handle); > handleComponentMap.put(handle, comp); > } > pane.addListComponent(comp); > pane.updateBoldFont(model.getSelectedHandle()); > if (showingPopup) { > resizePopup(); > } > } > > private void removeListItem(InternalHandle handle) { > handleComponentMap.remove(handle); > pane.removeListComponent(handle); > pane.updateBoldFont(model.getSelectedHandle()); > if (showingPopup) { > resizePopup(); > } > } > > > public void showPopup() { > if (showingPopup) { > return; > } > InternalHandle[] handles = model.getHandles(); > if (handles.length == 0) { > // just in case.. > return; > } > showingPopup = true; > > // NOT using PopupFactory > // 1. on linux, creates mediumweight popup taht doesn't refresh behind visible glasspane > // 2. on mac, needs an owner frame otherwise hiding tooltip also hides the popup. (linux requires no owner frame to force heavyweight) > // 3. the created window is not focusable window > if (popupWindow == null) { > popupWindow = new JWindow(WindowManager.getDefault().getMainWindow()); > popupWindow.getContentPane().add(pane); > } > Toolkit.getDefaultToolkit().addAWTEventListener(hideListener, AWTEvent.MOUSE_EVENT_MASK); > WindowManager.getDefault().getMainWindow().addWindowStateListener(hideListener); > WindowManager.getDefault().getMainWindow().addComponentListener(hideListener); > resizePopup(); > popupWindow.setVisible(true); > pane.requestFocus(); > // System.out.println(" window focusable=" + popupWindow.isFocusableWindow()); > } > > private void resizePopup() { > popupWindow.pack(); > Point point = new Point(0,0); > SwingUtilities.convertPointToScreen(point, this); > Dimension dim = popupWindow.getSize(); > //#63265 > Rectangle usableRect = Utilities.getUsableScreenBounds(); > Point loc = new Point(point.x + this.getSize().width + 4 - dim.width , point.y - dim.height - 5); > if (! usableRect.contains(loc)) { > loc = new Point(loc.x, point.y + 5 + this.getSize().height); > } > // +4 here because of the width of the close button in popup, we > // want the progress bars to align visually.. but there's separator in status now.. > popupWindow.setLocation(loc); > // System.out.println("count=" + count); > // System.out.println("offset =" + offset); > } > > private class HideAWTListener extends ComponentAdapter implements AWTEventListener, WindowStateListener { > public void eventDispatched(java.awt.AWTEvent aWTEvent) { > if (aWTEvent instanceof MouseEvent) { > MouseEvent mv = (MouseEvent)aWTEvent; > if (mv.getClickCount() > 0) { > Component comp = (Component)aWTEvent.getSource(); > Container par = SwingUtilities.getAncestorNamed("progresspopup", comp); //NOI18N > Container barpar = SwingUtilities.getAncestorOfClass(StatusLineComponent.class, comp); > if (par == null && barpar == null) { > hidePopup(); > } > } > } > } > > public void windowStateChanged(WindowEvent windowEvent) { > if (showingPopup) { > int oldState = windowEvent.getOldState(); > int newState = windowEvent.getNewState(); > > if (((oldState & Frame.ICONIFIED) == 0) && > ((newState & Frame.ICONIFIED) == Frame.ICONIFIED)) { > hidePopup(); > // } else if (((oldState & Frame.ICONIFIED) == Frame.ICONIFIED) && > // ((newState & Frame.ICONIFIED) == 0 )) { > // //TODO remember we showed before and show again? I guess not worth the efford, not part of spec. > } > } > > } > > public void componentResized(ComponentEvent evt) { > if (showingPopup) { > resizePopup(); > } > } > > public void componentMoved(ComponentEvent evt) { > if (showingPopup) { > resizePopup(); > } > } > > } > > private class MListener extends MouseAdapter { > public void mouseClicked(java.awt.event.MouseEvent e) { > if (e.getButton() != MouseEvent.BUTTON1) { > showMenu(e); > } else { > if (showingPopup) { > hidePopup(); > } else { > showPopup(); > } > } > } > > } > > private void showMenu(MouseEvent e) { > JPopupMenu popup = new JPopupMenu(); > popup.add(new ProgressListAction(NbBundle.getMessage(StatusLineComponent.class, "StatusLineComponent.ShowProcessList"))); > popup.add(new ViewAction()); > popup.add(new CancelAction()); > popup.show((Component)e.getSource(), e.getX(), e.getY()); > } > > private class CancelAction extends AbstractAction { > public CancelAction() { > putValue(Action.NAME, NbBundle.getMessage(StatusLineComponent.class, "StatusLineComponent.Cancel")); > setEnabled(handle == null ? false : handle.isAllowCancel()); > > } > public void actionPerformed(ActionEvent actionEvent) { > InternalHandle hndl = handle; > if (hndl !=null && hndl.getState() == InternalHandle.STATE_RUNNING) { > String message = NbBundle.getMessage(StatusLineComponent.class, "Cancel_Question", handle.getDisplayName()); > String title = NbBundle.getMessage(StatusLineComponent.class, "Cancel_Question_Title"); > NotifyDescriptor dd = new NotifyDescriptor(message, title, > NotifyDescriptor.YES_NO_OPTION, > NotifyDescriptor.QUESTION_MESSAGE, null, null); > Object retType = DialogDisplayer.getDefault().notify(dd); > if (retType == NotifyDescriptor.YES_OPTION && hndl.getState() == InternalHandle.STATE_RUNNING) { > hndl.requestCancel(); > } > } > } > } > > private class ViewAction extends AbstractAction { > public ViewAction() { > putValue(Action.NAME, NbBundle.getMessage(StatusLineComponent.class, "StatusLineComponent.View")); > setEnabled(handle == null ? false : handle.isAllowView()); > > } > public void actionPerformed(ActionEvent actionEvent) { > if (handle != null) { > handle.requestView(); > } > } > } > > > } Index: progressui/src/org/netbeans/modules/progress/ui/layer.xml =================================================================== RCS file: progressui/src/org/netbeans/modules/progress/ui/layer.xml diff -N progressui/src/org/netbeans/modules/progress/ui/layer.xml 0a1,4 > > > >