FolderInfoPropertyPage Class After Editing


package samples.ui.propertypages;

import org.eclipse.swt.widgets.*;
import org.eclipse.swt.events.*;

import RSESamples.*;
import com.ibm.etools.systems.core.ui.propertypages.SystemAbstractRemoteFilePropertyPageExtensionAction;
import com.ibm.etools.systems.subsystems.*;
import com.ibm.etools.systems.core.ui.*;

import java.util.*;

/**
 * A sample property page for a remote object, which in this case is scoped via the
 *  extension point xml to only apply to folder objects.
 */
public class FolderInfoPropertyPage
	extends SystemAbstractRemoteFilePropertyPageExtensionAction 
	implements SelectionListener
{
	// gui widgets...
	private Label sizeLabel, filesLabel, foldersLabel;
	private Button stopButton;
	// state...
	private int totalSize = 0;
	private int totalFolders = 0;
	private int totalFiles = 0;
	private boolean stopped = false;
	private Thread workerThread;
	private Runnable guiUpdater;

	/**
	 * Constructor for FolderInfoPropertyPage.
	 */
	public FolderInfoPropertyPage()
	{
		super();
	}

	// --------------------------
	// Parent method overrides...
	// --------------------------
	
	/**
	 * @see com.ibm.etools.systems.core.ui.propertypages.SystemBasePropertyPage#createContentArea(Composite)
	 */
	protected Control createContentArea(Composite parent)
	{
		Composite composite = SystemWidgetHelpers.createComposite(parent, 2);
		ResourceBundle rb = RSESamplesPlugin.getDefault().getResourceBundle();
		// draw the gui		
		sizeLabel = SystemWidgetHelpers.createLabeledLabel(composite, rb, "pp.size.", false);
		filesLabel = SystemWidgetHelpers.createLabeledLabel(composite, rb, "pp.files.", false);
		foldersLabel = SystemWidgetHelpers.createLabeledLabel(composite, rb, "pp.folders.", false);
		stopButton = SystemWidgetHelpers.createPushButton(composite, null, rb, "pp.stopButton.");
		stopButton.addSelectionListener(this);
		
		setValid(false); // Disable OK button until thread is done
		
		// show "Processing..." message
		setMessage(RSESamplesPlugin.getPluginMessage("RSSG1002"));
		
		// create instance of Runnable to allow asynchronous GUI updates from background thread	   
		guiUpdater = new RunnableGUIClass();
		// spawn a thread to calculate the information
		workerThread = new RunnableClass(getRemoteFile());
		workerThread.start();
		
		return composite;
	}
	
	/**
	 * Intercept from PreferencePage. Called when user presses Cancel button.
	 * We stop the background thread.
	 */
	public boolean performCancel() 
	{
		killThread();
		return true;
	}			
	
	/**
	 * Intercept from DialogPage. Called when dialog going away.
	 * If the user presses the X to close this dialog, we 
	 *  need to stop that background thread.
	 */
	public void dispose()
	{
		killThread();
		super.dispose();
	}
	
	/**
	 * Private method to kill our background thread.
	 * Control doesn't return until it ends.
	 */
	private void killThread()
	{
		if (!stopped && workerThread.isAlive())
		{
		    stopped = true;
		    try {
		      workerThread.join(); // wait for thread to end
		    } catch (InterruptedException exc) {}
		}		
	}

	// -------------------------------------------
	// Methods from SelectionListener interface...
	// -------------------------------------------
	
	/**
	 * From SelectionListener
	 */
	public void widgetSelected(SelectionEvent event) 
	{
		if (event.getSource() == stopButton)
		{
			stopped = true;
			stopButton.setEnabled(false);
		}
	}
	/**
	 * From SelectionListener
	 */
	public void widgetDefaultSelected(SelectionEvent event) {}
	

	// ----------------
	// Inner classes...
	// ----------------
	/**
	 * Inner class encapsulating the background work to be done, so it may be executed
	 *  in background thread.
	 */
	private class RunnableClass extends Thread
	{
		IRemoteFile inputFolder;
		
		RunnableClass(IRemoteFile inputFolder)
		{
			this.inputFolder = inputFolder;
		}
		
		public void run()
		{
			if (stopped)
			  return;
			walkFolder(inputFolder);						
			updateGUI();
			if (!stopped)
			{
				stopped = true;
				updateGUI();
			}
		}
		
		/**
		 * Recursively walk a folder, updating the running tallies. 
		 * Update the GUI after processing each subfolder.
		 */
		private void walkFolder(IRemoteFile currFolder)
		{
			IRemoteFile[] folders = currFolder.getParentRemoteFileSubSystem().listFoldersAndFiles(currFolder);
			if ((folders != null) && (folders.length>0))
			{
				for (int idx=0; !stopped && (idx<folders.length); idx++)
				{
					// is this a folder? 
					if (folders[idx].isDirectory())
					{
						++totalFolders;
						walkFolder(folders[idx]);
						updateGUI();
					}
					// is this a file?
					else
					{
						++totalFiles;
						totalSize += folders[idx].getLength();
					}
				}
			}
		} // end of walkFolder method

	} // end of inner class
	
	/**
	 * Inner class encapsulating the GUI work to be done from the
	 *  background thread.
	 */
	private class RunnableGUIClass implements Runnable
	{
		public void run()
		{
			if (stopButton.isDisposed())
			  return; 
			if (!stopped)
			{
				sizeLabel.setText(Integer.toString(totalSize));		
				filesLabel.setText(Integer.toString(totalFiles));
				foldersLabel.setText(Integer.toString(totalFolders));
			}
			else if (stopped)
			{				
				setValid(true); // re-enable OK button								
				stopButton.setEnabled(false); // disable Stop button				
				clearMessage(); // clear "Processing..." message
			}			  
		}
	}	

	
	/**
	 * Update the GUI with the current status
	 */
	private void updateGUI()
	{
		Display.getDefault().asyncExec(guiUpdater);
	}

}


Copyright IBM Corporation 2002, 2003.