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); } }