diff --git a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/DirInfo.java b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/DirInfo.java index 07ef84d94f..b160797829 100644 --- a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/DirInfo.java +++ b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/DirInfo.java @@ -22,8 +22,9 @@ package com.raytheon.uf.viz.archive.data; import java.io.File; import java.util.ArrayList; import java.util.Calendar; -import java.util.LinkedList; import java.util.List; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicBoolean; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; @@ -53,15 +54,16 @@ import com.raytheon.uf.common.util.FileUtil; */ public class DirInfo { + private static final SizeJob sizeJob = new DirInfo.SizeJob(); final private DisplayData displayInfo; private final List files = new ArrayList(); - private Calendar startCal; + private final Calendar startCal; - private Calendar endCal; + private final Calendar endCal; public static void clearQueue() { sizeJob.clearQueue(); @@ -79,7 +81,6 @@ public class DirInfo { this.displayInfo = displayInfo; this.startCal = startCal; this.endCal = endCal; - displayInfo.setSize(-1); DirInfo.sizeJob.queue(this); } @@ -87,29 +88,57 @@ public class DirInfo { return displayInfo; } + /** + * Job to determine the size for a directory and its contents on a non-UI + * thread. + */ static private class SizeJob extends Job { - private LinkedList queueList = new LinkedList(); + private ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue(); - private boolean isShutdown = false; + private final ConcurrentLinkedQueue selectedQueue = new ConcurrentLinkedQueue(); + + private final AtomicBoolean stopComputeSize = new AtomicBoolean(false); List listeners = new ArrayList(); + /** + * Add entry to queue and if pending selected entries add them to the + * queue with same start/end times. + * + * @param fileInfo + */ protected void queue(DirInfo fileInfo) { - synchronized (queueList) { - queueList.add(fileInfo); - if (getState() == Job.NONE) { - System.out.println("schedule queue size: " - + queueList.size()); - schedule(); - } + queue.add(fileInfo); + + if (getState() == Job.NONE) { + schedule(); } } + /** + * Clear list off pending data but save selected entries still needing + * sizes. + */ protected void clearQueue() { - synchronized (queueList) { - queueList.clear(); - if (getState() != Job.NONE) { - isShutdown = true; + List pending = new ArrayList(); + + // Drain queue queue.removeAll() doesn't work. + while (!queue.isEmpty()) { + pending.add(queue.remove()); + } + + if (getState() != NONE) { + cancel(); + } + + // Save selected items that do not have sizes. + for (DirInfo dirInfo : pending) { + DisplayData displayData = dirInfo.getDisplayInfo(); + + if (displayData.isSelected() && displayData.getSize() < 0L) { + if (!selectedQueue.contains(displayData)) { + selectedQueue.add(displayData); + } } } } @@ -121,66 +150,68 @@ public class DirInfo { @Override protected IStatus run(IProgressMonitor monitor) { + if (monitor.isCanceled()) { + return Status.OK_STATUS; + } + ArchiveConfigManager manager = ArchiveConfigManager.getInstance(); - System.out.println("starting SizeJob"); - long startTime = System.currentTimeMillis(); - while (!isShutdown && !queueList.isEmpty()) { - List list = null; - synchronized (queueList) { - list = new ArrayList(queueList); + mainLoop: while (!queue.isEmpty()) { + DirInfo dirInfo = queue.remove(); - queueList.clear(); - } - System.out.println("sizeJob Processing: " + list.size()); - long t1 = System.currentTimeMillis(); + stopComputeSize.set(false); + DisplayData displayData = dirInfo.displayInfo; + Calendar startCal = dirInfo.startCal; + Calendar endCal = dirInfo.endCal; - for (DirInfo dirInfo : list) { - long t2 = System.currentTimeMillis(); - if (isShutdown) { - break; - } - DisplayData displayInfo = dirInfo.displayInfo; - Calendar startCal = dirInfo.startCal; - Calendar endCal = dirInfo.endCal; - displayInfo.setSize(-1); + List files = manager.getDisplayFiles(displayData, + startCal, endCal); - List files = manager.getDisplayFiles(displayInfo, - startCal, endCal); - dirInfo.files.clear(); - dirInfo.files.addAll(files); - long size = 0L; - for (File file : dirInfo.files) { - if (isShutdown) { - break; - } - if (file.isDirectory()) { - size += FileUtil.sizeOfDirectory(file); - } else { - size += file.length(); - } - } - long t3 = System.currentTimeMillis(); - System.out.println("-- \"" + displayInfo.getDisplayLabel() - + "\": oldSize: " + displayInfo.getSize() - + ", newSize: " + size + ", time: " + (t3 - t2) - + " ms"); - displayInfo.setSize(size); + // Is size still needed. + if (!displayData.isSelected() && stopComputeSize.get()) { + continue; } - if (!isShutdown) { - for (IUpdateListener listener : listeners) { - listener.update(list); + dirInfo.files.clear(); + dirInfo.files.addAll(files); + long size = 0L; + for (File file : dirInfo.files) { + + // Skip when size no longer needed. + if (!displayData.isSelected() && stopComputeSize.get()) { + continue mainLoop; } - } else { - synchronized (queueList) { - isShutdown = false; + + if (file.isDirectory()) { + size += FileUtil.sizeOfDirectory(file); + } else { + size += file.length(); + } + } + + displayData.setSize(size); + + List list = new ArrayList(); + list.add(dirInfo); + for (IUpdateListener listener : listeners) { + listener.update(list); + } + + if (!stopComputeSize.get()) { + // Place any pending selections at end of the queue. + while (!selectedQueue.isEmpty()) { + DisplayData data = selectedQueue.remove(); + new DirInfo(data, startCal, endCal); } } } - System.out.println("Ending SizeJob"); return Status.OK_STATUS; } + + @Override + protected void canceling() { + stopComputeSize.set(true); + } } } diff --git a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/IArchiveTotals.java b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/IArchiveTotals.java index 4bcb8b90e8..d4e8be9b00 100644 --- a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/IArchiveTotals.java +++ b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/IArchiveTotals.java @@ -38,9 +38,7 @@ package com.raytheon.uf.viz.archive.data; public interface IArchiveTotals { /** - * Total selected items from all tables. - * - * @return totalSelectedItems. + * Update total selected items and sizes. */ - public int getTotalSelectedItems(); + public void updateTotals(); } diff --git a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/AbstractArchiveDlg.java b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/AbstractArchiveDlg.java index e6b8b87667..1d4494800d 100644 --- a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/AbstractArchiveDlg.java +++ b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/AbstractArchiveDlg.java @@ -114,10 +114,13 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements setupCursor(); } - /* (non-Javadoc) - * @see com.raytheon.uf.viz.archive.data.IArchiveTotals#getTotalSelectedItems() + /* + * (non-Javadoc) + * + * @see + * com.raytheon.uf.viz.archive.data.IArchiveTotals#getTotalSelectedItems() */ - @Override + // @Override public int getTotalSelectedItems() { int totalSelected = 0; for (ArchiveInfo archiveInfo : archiveInfoMap.values()) { @@ -319,28 +322,6 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements populateTableComp(getSelectedArchiveName(), getSelectedCategoryName()); } - /** - * Add a separator line to the provided container. - * - * @param container - * Composite. - * @param orientation - * Vertical or horizontal orientation. - */ - protected void addSeparator(Composite container, int orientation) { - // Separator label - GridData gd; - - if (orientation == SWT.HORIZONTAL) { - gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false); - } else { - gd = new GridData(SWT.DEFAULT, SWT.FILL, false, true); - } - - Label sepLbl = new Label(container, SWT.SEPARATOR | orientation); - sepLbl.setLayoutData(gd); - } - /** * Init busyCursor. On close, make sure that cursor reverts back to unbusy * state if it isn't already. diff --git a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/ArchiveRetentionDlg.java b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/ArchiveRetentionDlg.java index fe7634b454..d7c0f221a6 100644 --- a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/ArchiveRetentionDlg.java +++ b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/ArchiveRetentionDlg.java @@ -39,6 +39,7 @@ import com.raytheon.uf.common.archive.config.ArchiveConfigManager; import com.raytheon.uf.common.archive.config.CategoryConfig; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; +import com.raytheon.uf.viz.archive.data.IArchiveTotals; /** * Archive retention dialog. @@ -57,7 +58,8 @@ import com.raytheon.uf.common.status.UFStatus; * @author lvenable * @version 1.0 */ -public class ArchiveRetentionDlg extends AbstractArchiveDlg { +public class ArchiveRetentionDlg extends AbstractArchiveDlg implements + IArchiveTotals { private final transient IUFStatusHandler statusHandler = UFStatus .getHandler(ArchiveRetentionDlg.class); @@ -106,7 +108,7 @@ public class ArchiveRetentionDlg extends AbstractArchiveDlg { */ private void init() { createRetentionControls(); - addSeparator(shell, SWT.HORIZONTAL); + GuiUtil.addSeparator(shell, SWT.HORIZONTAL); createBottomActionButtons(); selectionsUpdated(); } @@ -331,7 +333,7 @@ public class ArchiveRetentionDlg extends AbstractArchiveDlg { } @Override - protected void selectionsUpdated() { + public void updateTotals() { ArchiveConfig archive = getSelectedArchive(); if (archive != null) { if (minRetentionSpnr != null) { @@ -344,4 +346,9 @@ public class ArchiveRetentionDlg extends AbstractArchiveDlg { } } + @Override + protected void selectionsUpdated() { + // Not used. + } + } diff --git a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/ArchiveTableComp.java b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/ArchiveTableComp.java index 9345050952..b8e452b2f0 100644 --- a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/ArchiveTableComp.java +++ b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/ArchiveTableComp.java @@ -71,9 +71,6 @@ public class ArchiveTableComp extends Composite { /** Number of selected items label. */ private Label selectedLbl; - /** Total selected items for all tables */ - private Label totalSelectedLbl; - /** Size label. */ private Label sizeLbl; @@ -85,7 +82,7 @@ public class ArchiveTableComp extends Composite { /** Current table type. */ private TableType tableType = TableType.Retention; - private IArchiveTotals iTotalSelectedSize; + private IArchiveTotals iArchiveTotals; /** * Constructor. @@ -100,7 +97,7 @@ public class ArchiveTableComp extends Composite { super(parent, 0); tableType = type; - this.iTotalSelectedSize = iTotalSelectedSize; + this.iArchiveTotals = iTotalSelectedSize; init(); } @@ -172,7 +169,7 @@ public class ArchiveTableComp extends Composite { */ private void createTableLabels() { Composite lblComp = new Composite(this, SWT.NONE); - GridLayout gl = new GridLayout(3, true); + GridLayout gl = new GridLayout(2, true); GridData gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false); lblComp.setLayout(gl); lblComp.setLayoutData(gd); @@ -184,10 +181,6 @@ public class ArchiveTableComp extends Composite { gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false); sizeLbl = new Label(lblComp, SWT.NONE); sizeLbl.setLayoutData(gd); - - gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false); - totalSelectedLbl = new Label(lblComp, SWT.NONE); - totalSelectedLbl.setLayoutData(gd); } /** @@ -218,14 +211,13 @@ public class ArchiveTableComp extends Composite { } selectedLbl.setText("Table Selected Items: " + count); - int totalSelectedSize = iTotalSelectedSize.getTotalSelectedItems(); - totalSelectedLbl.setText("Total Selected Items: " + totalSelectedSize); - String sizeString = "????"; + String sizeString = DisplayData.UNKNOWN_SIZE_LABEL; if (tableTotalSize >= 0) { sizeString = SizeUtil.prettyByteSize(tableTotalSize); } sizeLbl.setText("Table Selected Size: " + sizeString); + iArchiveTotals.updateTotals(); } /** @@ -325,6 +317,8 @@ public class ArchiveTableComp extends Composite { } } } + + updateSelectionLabels(); } /* @@ -354,7 +348,7 @@ public class ArchiveTableComp extends Composite { private void setItemSize(TableItem item) { long size = ((DisplayData) item.getData(DISPLAY_INFO_KEY)).getSize(); if (size < 0L) { - item.setText(1, "????"); + item.setText(1, DisplayData.UNKNOWN_SIZE_LABEL); } else { item.setText(1, SizeUtil.prettyByteSize(size)); } diff --git a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/CaseCreationDlg.java b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/CaseCreationDlg.java index 95447b8427..ce9d5bfba9 100644 --- a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/CaseCreationDlg.java +++ b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/CaseCreationDlg.java @@ -28,6 +28,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.eclipse.core.runtime.jobs.IJobChangeEvent; +import org.eclipse.core.runtime.jobs.JobChangeAdapter; +import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; @@ -61,6 +64,7 @@ import com.raytheon.uf.viz.archive.ui.ArchiveTableComp.TableType; import com.raytheon.uf.viz.core.VizApp; import com.raytheon.viz.ui.dialogs.AwipsCalendar; import com.raytheon.viz.ui.dialogs.CaveSWTDialog; +import com.raytheon.viz.ui.dialogs.ICloseCallback; /** * @@ -103,6 +107,12 @@ public class CaseCreationDlg extends CaveSWTDialog implements IArchiveTotals, /** Category combo box. */ private Combo categoryCbo; + /** Action to bring up the case name dialog. */ + private Button caseNameCreate; + + /** Display the case name. */ + private Label caseNameLbl; + /** Compression check box. */ private Button compressChk; @@ -127,6 +137,12 @@ public class CaseCreationDlg extends CaveSWTDialog implements IArchiveTotals, /** Uncompressed file size label. */ private Label uncompressSizeLbl; + /** Displays total number of items selected from all categories. */ + private Label totalSelectedItemsLbl; + + /** Button to generate the case. */ + private Button generateBtn; + /** Date format. */ private SimpleDateFormat dateFmt = new SimpleDateFormat( "E MMM dd yyyy HH:00 z"); @@ -137,7 +153,8 @@ public class CaseCreationDlg extends CaveSWTDialog implements IArchiveTotals, /** Information for populating the various table displays. */ private final Map archiveInfoMap = new HashMap(); - private Cursor busyCursor; + /** Number of selected items. */ + private int selectedItemsSize = 0; /** * Constructor. @@ -162,7 +179,6 @@ public class CaseCreationDlg extends CaveSWTDialog implements IArchiveTotals, @Override protected void initializeComponents(Shell shell) { - busyCursor = shell.getDisplay().getSystemCursor(SWT.CURSOR_WAIT); setText("Archive Case Creation"); Composite mainComp = new Composite(shell, SWT.NONE); GridLayout gl = new GridLayout(1, false); @@ -187,12 +203,12 @@ public class CaseCreationDlg extends CaveSWTDialog implements IArchiveTotals, private void init() { DirInfo.addUpdateListener(this); createTimeControls(); - addSeparator(shell, SWT.HORIZONTAL); + GuiUtil.addSeparator(shell, SWT.HORIZONTAL); createCaseCompressionControls(); - addSeparator(shell, SWT.HORIZONTAL); + GuiUtil.addSeparator(shell, SWT.HORIZONTAL); createFileBrowserControls(); createTable(); - addSeparator(shell, SWT.HORIZONTAL); + GuiUtil.addSeparator(shell, SWT.HORIZONTAL); createBottomActionButtons(); populateComboBoxes(); @@ -256,7 +272,7 @@ public class CaseCreationDlg extends CaveSWTDialog implements IArchiveTotals, caseCompressionComp.setLayoutData(gd); createComboControls(caseCompressionComp); - addSeparator(caseCompressionComp, SWT.VERTICAL); + GuiUtil.addSeparator(caseCompressionComp, SWT.VERTICAL); createCompressionControls(caseCompressionComp); } @@ -283,9 +299,7 @@ public class CaseCreationDlg extends CaveSWTDialog implements IArchiveTotals, archCfgCbo.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { - String archiveName = archCfgCbo.getItem(archCfgCbo - .getSelectionIndex()); - populateCategoryCbo(archiveName); + populateCategoryCbo(getSelectedArchiveName()); } }); @@ -299,13 +313,24 @@ public class CaseCreationDlg extends CaveSWTDialog implements IArchiveTotals, categoryCbo.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { - String archiveName = archCfgCbo.getItem(archCfgCbo - .getSelectionIndex()); - String categoryName = categoryCbo.getItem(categoryCbo - .getSelectionIndex()); - populateTableComp(archiveName, categoryName); + populateTableComp(); } }); + + caseNameCreate = new Button(comboComp, SWT.PUSH); + caseNameCreate.setText(" Case Name... "); + caseNameCreate.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + handleCaseNameSelection(); + } + }); + caseNameCreate.setToolTipText("Must first select \"Case Location\"."); + + gd = new GridData(SWT.FILL, SWT.CENTER, true, false); + caseNameLbl = new Label(comboComp, SWT.BORDER); + caseNameLbl.setLayoutData(gd); } /** @@ -317,7 +342,7 @@ public class CaseCreationDlg extends CaveSWTDialog implements IArchiveTotals, private void createCompressionControls(Composite comp) { Composite compressionComp = new Composite(comp, SWT.NONE); GridLayout gl = new GridLayout(1, false); - GridData gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false); + GridData gd = new GridData(SWT.FILL, SWT.CENTER, true, false); compressionComp.setLayout(gl); compressionComp.setLayoutData(gd); @@ -325,7 +350,7 @@ public class CaseCreationDlg extends CaveSWTDialog implements IArchiveTotals, * Uncompressed file size label */ Composite compressionLblComp = new Composite(compressionComp, SWT.NONE); - gl = new GridLayout(3, false); + gl = new GridLayout(2, false); gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false); compressionLblComp.setLayout(gl); compressionLblComp.setLayoutData(gd); @@ -335,9 +360,15 @@ public class CaseCreationDlg extends CaveSWTDialog implements IArchiveTotals, gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false); uncompressSizeLbl = new Label(compressionLblComp, SWT.NONE); - // uncompressSizeLbl.setText("1024 MB"); uncompressSizeLbl.setLayoutData(gd); - updateUncompressSizeLbl(); + + Label totSelectedLbl = new Label(compressionLblComp, SWT.NONE); + totSelectedLbl.setText("Total Selected Items: "); + + gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false); + totalSelectedItemsLbl = new Label(compressionLblComp, SWT.NONE); + totalSelectedItemsLbl.setLayoutData(gd); + /* * Compression controls */ @@ -419,6 +450,7 @@ public class CaseCreationDlg extends CaveSWTDialog implements IArchiveTotals, handleBrowserSelection(); } }); + browseBtn.setToolTipText("Select directory to place case."); Label stateLbl = new Label(fileBrowserComp, SWT.NONE); stateLbl.setText("Full - Avaliable:"); @@ -456,12 +488,13 @@ public class CaseCreationDlg extends CaveSWTDialog implements IArchiveTotals, } }); - Button generateBtn = new Button(actionControlComp, SWT.PUSH); + generateBtn = new Button(actionControlComp, SWT.PUSH); generateBtn.setText(" Generate "); + generateBtn.setEnabled(false); generateBtn.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { - + generateCase(); } }); @@ -477,6 +510,52 @@ public class CaseCreationDlg extends CaveSWTDialog implements IArchiveTotals, }); } + /** + * Display modal dialog that performs the Generation of the case. + */ + private void generateCase() { + setBusy(true); + File targetDir = (File) locationLbl.getData(); + File caseDir = (File) caseNameLbl.getData(); + // TODO investigate using just Date or long values for start/end + Calendar startCal = TimeUtil.newCalendar(); + startCal.setTimeInMillis(startDate.getTime()); + Calendar endCal = TimeUtil.newCalendar(); + endCal.setTimeInMillis(endDate.getTime()); + + List displayDatas = getSelectedData(); + boolean doCompress = compressChk.getSelection(); + boolean doMultiFiles = breakFilesChk.getSelection(); + int compressSize = fileSizeSpnr.getSelection(); + String sizeType = fileSizeCbo.getItem(fileSizeCbo.getSelectionIndex()); + + // Assume Model dialog. + GenerateCaseDlg dialog = new GenerateCaseDlg(shell, targetDir, caseDir, + startCal, endCal, displayDatas, doCompress, doMultiFiles, + compressSize, sizeType); + dialog.addJobChangeListener(new JobChangeAdapter() { + + @Override + public void done(IJobChangeEvent event) { + VizApp.runAsync(new Runnable() { + @Override + public void run() { + updateLocationState(); + } + }); + } + }); + dialog.setCloseCallback(new ICloseCallback() { + + @Override + public void dialogClosed(Object returnValue) { + setBusy(false); + } + }); + dialog.open(); + + } + /** * Enable/Disable controls based on the compression check box. */ @@ -490,6 +569,36 @@ public class CaseCreationDlg extends CaveSWTDialog implements IArchiveTotals, breakFilesChk.setEnabled(compressChk.getSelection()); } + /** + * Bring up modal dialog to get the case's directory name. + */ + private void handleCaseNameSelection() { + Object o = locationLbl.getData(); + if (!(o instanceof File)) { + MessageDialog.openError(shell, "Error", + "Must select \"Case Location\"."); + return; + } + + File targetDir = (File) o; + // Assume modal dialog. + CaseNameDialog dialog = new CaseNameDialog(shell, targetDir); + dialog.setCloseCallback(new ICloseCallback() { + + @Override + public void dialogClosed(Object returnValue) { + if (returnValue instanceof File) { + File caseDir = (File) returnValue; + String caseName = caseDir.getAbsolutePath(); + caseNameLbl.setText(caseName); + caseNameLbl.setData(caseDir); + checkGenerateButton(); + } + } + }); + dialog.open(); + } + /** * Enable/Disable file size controls. * @@ -502,6 +611,16 @@ public class CaseCreationDlg extends CaveSWTDialog implements IArchiveTotals, fileSizeCbo.setEnabled(enabled); } + /** + * Enables the generate button will user has entered all needed elements. + */ + private void checkGenerateButton() { + if (generateBtn != null && !generateBtn.isDisposed()) { + generateBtn.setEnabled(locationLbl.getData() != null + && caseNameLbl.getData() != null && selectedItemsSize > 0); + } + } + /** * Action performed when the file size has changed. */ @@ -541,62 +660,51 @@ public class CaseCreationDlg extends CaveSWTDialog implements IArchiveTotals, if (dirName != null) { locationLbl.setText(trimDirectoryName(dirName)); locationLbl.setToolTipText(dirName); - locationLbl.setData(dirName); - File dir = new File(dirName); - long totSpace = dir.getTotalSpace(); - long freeSpace = dir.getUsableSpace(); - long percentFull = (long) Math - .round(((totSpace - freeSpace) * 100.0) / totSpace); - String state = null; - Color bgColor = null; - Color fgColor = null; - Display display = shell.getDisplay(); - if (percentFull <= 84) { - state = "GOOD"; - bgColor = display.getSystemColor(SWT.COLOR_GREEN); - fgColor = display.getSystemColor(SWT.COLOR_BLACK); - } else if (percentFull <= 94) { - state = "CAUTION"; - bgColor = display.getSystemColor(SWT.COLOR_YELLOW); - fgColor = display.getSystemColor(SWT.COLOR_BLACK); - } else if (percentFull <= 97) { - state = "DANGER"; - bgColor = display.getSystemColor(SWT.COLOR_RED); - fgColor = display.getSystemColor(SWT.COLOR_BLACK); - } else { - state = "FATAL"; - bgColor = display.getSystemColor(SWT.COLOR_DARK_MAGENTA); - fgColor = display.getSystemColor(SWT.COLOR_WHITE); - } - - String text = String.format("%1$3d%% %2$s - %3$s", percentFull, - state, SizeUtil.prettyByteSize(freeSpace)); - locationStateLbl.setText(text); - locationStateLbl.setBackground(bgColor); - locationStateLbl.setForeground(fgColor); + locationLbl.setData(new File(dirName)); + caseNameCreate.setToolTipText(null); + caseNameLbl.setText(""); + caseNameLbl.setData(null); + updateLocationState(); + checkGenerateButton(); } } /** - * Add a separator line to the provided container. - * - * @param container - * Composite. - * @param orientation - * Vertical or horizontal orientation. + * Update location's state. */ - private void addSeparator(Composite container, int orientation) { - // Separator label - GridData gd; - - if (orientation == SWT.HORIZONTAL) { - gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false); + private void updateLocationState() { + File dir = (File) locationLbl.getData(); + long totSpace = dir.getTotalSpace(); + long freeSpace = dir.getUsableSpace(); + long percentFull = (long) Math.round(((totSpace - freeSpace) * 100.0) + / totSpace); + String state = null; + Color bgColor = null; + Color fgColor = null; + Display display = shell.getDisplay(); + if (percentFull <= 84) { + state = "GOOD"; + bgColor = display.getSystemColor(SWT.COLOR_GREEN); + fgColor = display.getSystemColor(SWT.COLOR_BLACK); + } else if (percentFull <= 94) { + state = "CAUTION"; + bgColor = display.getSystemColor(SWT.COLOR_YELLOW); + fgColor = display.getSystemColor(SWT.COLOR_BLACK); + } else if (percentFull <= 97) { + state = "DANGER"; + bgColor = display.getSystemColor(SWT.COLOR_RED); + fgColor = display.getSystemColor(SWT.COLOR_BLACK); } else { - gd = new GridData(SWT.DEFAULT, SWT.FILL, false, true); + state = "FATAL"; + bgColor = display.getSystemColor(SWT.COLOR_DARK_MAGENTA); + fgColor = display.getSystemColor(SWT.COLOR_WHITE); } - Label sepLbl = new Label(container, SWT.SEPARATOR | orientation); - sepLbl.setLayoutData(gd); + String text = String.format("%1$3d%% %2$s - %3$s", percentFull, state, + SizeUtil.prettyByteSize(freeSpace)); + locationStateLbl.setText(text); + locationStateLbl.setBackground(bgColor); + locationStateLbl.setForeground(fgColor); } /** @@ -628,8 +736,7 @@ public class CaseCreationDlg extends CaveSWTDialog implements IArchiveTotals, if (!startDate.equals(date)) { startDate = date; - // TODO update all information not just the current table. - populateTableComp(); + resetSizes(); } } else { if (date.before(startDate)) { @@ -642,8 +749,7 @@ public class CaseCreationDlg extends CaveSWTDialog implements IArchiveTotals, } if (!endDate.equals(date)) { endDate = date; - // TODO update all information not just the current table. - populateTableComp(); + resetSizes(); } } @@ -720,19 +826,12 @@ public class CaseCreationDlg extends CaveSWTDialog implements IArchiveTotals, categoryCbo.add(categoryName); } categoryCbo.select(0); - String categoryName = categoryCbo.getItem(0); - populateTableComp(archiveName, categoryName); + populateTableComp(); } private void populateTableComp() { - String archiveName = archCfgCbo.getItem(archCfgCbo.getSelectionIndex()); - String categoryName = categoryCbo.getItem(categoryCbo - .getSelectionIndex()); - populateTableComp(archiveName, categoryName); - } - - private void populateTableComp(String archiveName, String categoryName) { - + String archiveName = getSelectedArchiveName(); + String categoryName = getSelectedCategoryName(); setBusy(true); DirInfo.clearQueue(); ArchiveInfo archiveInfo = archiveInfoMap.get(archiveName); @@ -755,36 +854,30 @@ public class CaseCreationDlg extends CaveSWTDialog implements IArchiveTotals, startCal.setTimeInMillis(startDate.getTime()); Calendar endCal = TimeUtil.newCalendar(); endCal.setTimeInMillis(endDate.getTime()); + List recomputList = new ArrayList(); for (DisplayData displayInfo : categoryInfo.getDisplayInfoList()) { - new DirInfo(displayInfo, startCal, endCal); + // Queue unknown sizes first + if (displayInfo.getSize() < 0L) { + new DirInfo(displayInfo, startCal, endCal); + } else { + recomputList.add(displayInfo); + } + } + + // Recompute sizes + for (DisplayData displayData : recomputList) { + new DirInfo(displayData, startCal, endCal); } tableComp.populateTable(categoryInfo.getDisplayInfoList()); - updateUncompressSizeLbl(); + updateTotals(); setBusy(false); } - public int getTotalSelectedItems() { - int totalSelected = 0; - for (ArchiveInfo archiveInfo : archiveInfoMap.values()) { - for (String categoryName : archiveInfo.getCategoryNames()) { - CategoryInfo categoryInfo = archiveInfo.get(categoryName); - for (DisplayData displayInfo : categoryInfo - .getDisplayInfoList()) { - if (displayInfo.isSelected()) { - ++totalSelected; - } - } - } - } - updateUncompressSizeLbl(); - return totalSelected; - } - private void setBusy(boolean state) { Cursor cursor = null; if (state) { - cursor = busyCursor; + cursor = getDisplay().getSystemCursor(SWT.CURSOR_WAIT); } shell.setCursor(cursor); } @@ -801,16 +894,37 @@ public class CaseCreationDlg extends CaveSWTDialog implements IArchiveTotals, @Override public void run() { tableComp.updateSize(displayInfos); - updateUncompressSizeLbl(); + updateTotals(); } }); } + /** + * Obtain the selected archive name. + * + * @return archiveName + */ + private String getSelectedArchiveName() { + return archCfgCbo.getItem(archCfgCbo.getSelectionIndex()); + } + + /** + * Obtain the selected category name. + * + * @return categoryName + */ + private String getSelectedCategoryName() { + return categoryCbo.getItem(categoryCbo.getSelectionIndex()); + } + /** * Updates the estimated uncompressed size of selected entries. */ - private void updateUncompressSizeLbl() { + public void updateTotals() { long totalSize = 0; + int totalSelected = 0; + boolean unknownSize = false; + for (String archiveName : archiveInfoMap.keySet()) { ArchiveInfo archiveInfo = archiveInfoMap.get(archiveName); for (String categoryName : archiveInfo.getCategoryNames()) { @@ -818,19 +932,92 @@ public class CaseCreationDlg extends CaveSWTDialog implements IArchiveTotals, for (DisplayData displayData : categoryInfo .getDisplayInfoList()) { if (displayData.isSelected()) { - long size = displayData.getSize(); - if (size < 0) { - // Size still being computed. - uncompressSizeLbl.setText("????MB"); - return; - } else { - totalSize += size; + ++totalSelected; + if (!unknownSize) { + long size = displayData.getSize(); + if (size >= 0) { + totalSize += size; + } else { + unknownSize = true; + } } } } } } - uncompressSizeLbl.setText(SizeUtil.prettyByteSize(totalSize)); + selectedItemsSize = totalSelected; + String sizeMsg = null; + if (unknownSize) { + sizeMsg = DisplayData.UNKNOWN_SIZE_LABEL; + } else { + sizeMsg = SizeUtil.prettyByteSize(totalSize); + } + + uncompressSizeLbl.setText(sizeMsg); + totalSelectedItemsLbl.setText("" + totalSelected); + checkGenerateButton(); + } + + /** + * Reset all entries to unknown size, recompute the sizes for the current + * display table and and other selected entries. + */ + private void resetSizes() { + List selectedDatas = new ArrayList(); + for (String archiveName : archiveInfoMap.keySet()) { + ArchiveInfo archiveInfo = archiveInfoMap.get(archiveName); + for (String categoryName : archiveInfo.getCategoryNames()) { + CategoryInfo categoryInfo = archiveInfo.get(categoryName); + for (DisplayData displayData : categoryInfo + .getDisplayInfoList()) { + displayData.setSize(DisplayData.UNKNOWN_SIZE); + if (displayData.isSelected()) { + selectedDatas.add(displayData); + } + } + } + } + + populateTableComp(); + + if (selectedDatas.size() > 0) { + String archiveName = getSelectedArchiveName(); + String categoryName = getSelectedCategoryName(); + Calendar startCal = TimeUtil.newCalendar(); + startCal.setTimeInMillis(startDate.getTime()); + Calendar endCal = TimeUtil.newCalendar(); + startCal.setTimeInMillis(endDate.getTime()); + + for (DisplayData displayData : selectedDatas) { + if (!displayData.isArchive(archiveName) + || !displayData.isCategory(categoryName)) { + new DirInfo(displayData, startCal, endCal); + } + } + } + } + + /** + * Get the data information on all selected items; not just the currently + * displayed table. + * + * @return selectedDatas + */ + private List getSelectedData() { + List selectedDatas = new ArrayList(); + for (String archiveName : archiveInfoMap.keySet()) { + ArchiveInfo archiveInfo = archiveInfoMap.get(archiveName); + for (String categoryName : archiveInfo.getCategoryNames()) { + CategoryInfo categoryInfo = archiveInfo.get(categoryName); + for (DisplayData displayData : categoryInfo + .getDisplayInfoList()) { + if (displayData.isSelected()) { + selectedDatas.add(displayData); + } + } + } + } + return selectedDatas; } } diff --git a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/CaseNameDialog.java b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/CaseNameDialog.java new file mode 100644 index 0000000000..60a5e16b54 --- /dev/null +++ b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/CaseNameDialog.java @@ -0,0 +1,189 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.viz.archive.ui; + +import java.io.File; + +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyAdapter; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +import com.raytheon.viz.ui.dialogs.CaveSWTDialog; + +/** + * Dialog to obtain and verify a case name. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jun 5, 2013  1966       rferrel     Initial creation
+ * 
+ * 
+ * + * @author rferrel + * @version 1.0 + */ + +public class CaseNameDialog extends CaveSWTDialog { + + /** The location directory. */ + private File locationDir; + + /** Text field for entering the case name's directory. */ + private Text caseNameText; + + /** Non-blocking modal constructor. */ + protected CaseNameDialog(Shell parent, File locationDir) { + super(parent, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL, + CAVE.DO_NOT_BLOCK); + this.locationDir = locationDir; + } + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.viz.ui.dialogs.CaveSWTDialogBase#initializeComponents(org + * .eclipse.swt.widgets.Shell) + */ + @Override + protected void initializeComponents(Shell shell) { + Composite mainComp = new Composite(shell, SWT.NONE); + GridLayout gl = new GridLayout(1, false); + gl.marginHeight = 0; + gl.marginWidth = 0; + gl.horizontalSpacing = 0; + mainComp.setLayout(gl); + init(); + } + + /** + * create layout of the dialog. + */ + private void init() { + setText("Case Name"); + createFieldsComp(); + GuiUtil.addSeparator(shell, SWT.HORIZONTAL); + createBottomActionButtons(); + } + + /** + * The xomposite with case name text field. + */ + private void createFieldsComp() { + Composite fieldComp = new Composite(shell, SWT.NONE); + GridLayout gl = new GridLayout(2, false); + GridData gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false); + fieldComp.setLayout(gl); + fieldComp.setLayoutData(gd); + + Label nameLbl = new Label(fieldComp, SWT.LEFT); + nameLbl.setText("Name: "); + + caseNameText = new Text(fieldComp, SWT.SINGLE); + gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false); + gd.minimumWidth = 200; + caseNameText.setLayoutData(gd); + caseNameText.addKeyListener(new KeyAdapter() { + + @Override + public void keyReleased(KeyEvent e) { + super.keyReleased(e); + if (e.character == SWT.CR || e.character == SWT.KEYPAD_CR) { + if (verifySelection()) { + close(); + } + } + } + }); + } + + /** + * The composite with the action buttons. + */ + private void createBottomActionButtons() { + Composite actionControlComp = new Composite(shell, SWT.NONE); + GridLayout gl = new GridLayout(2, false); + GridData gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false); + actionControlComp.setLayout(gl); + actionControlComp.setLayoutData(gd); + + Button okBtn = new Button(actionControlComp, SWT.PUSH); + okBtn.setText(" OK "); + okBtn.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + if (verifySelection()) { + close(); + } + } + }); + + Button cancelBtn = new Button(actionControlComp, SWT.PUSH); + cancelBtn.setText(" Cancel "); + cancelBtn.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + close(); + } + }); + } + + /** + * Validate the case's directory does not exist and set the return value + * when it doesn't exist. + * + * @return true when case's directory does not exist. + */ + private boolean verifySelection() { + String caseName = caseNameText.getText().trim(); + if (caseName.length() == 0) { + MessageDialog.openError(shell, "Error", "Enter a case name."); + return false; + } + + File caseDir = new File(locationDir, caseName); + if (caseDir.exists()) { + MessageDialog.openError(shell, "Error", + "Case already exists choose another name."); + caseNameText.selectAll(); + caseNameText.setFocus(); + return false; + } + + setReturnValue(caseDir); + return true; + } + +} diff --git a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/GenerateCaseDlg.java b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/GenerateCaseDlg.java new file mode 100644 index 0000000000..0115e9032d --- /dev/null +++ b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/GenerateCaseDlg.java @@ -0,0 +1,465 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.viz.archive.ui; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.IJobChangeListener; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.ShellAdapter; +import org.eclipse.swt.events.ShellEvent; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.ProgressBar; +import org.eclipse.swt.widgets.Shell; + +import com.raytheon.uf.common.archive.config.ArchiveConfigManager; +import com.raytheon.uf.common.archive.config.ArchiveConfigManager.DisplayData; +import com.raytheon.uf.common.status.IUFStatusHandler; +import com.raytheon.uf.common.status.UFStatus; +import com.raytheon.uf.common.status.UFStatus.Priority; +import com.raytheon.uf.common.util.FileUtil; +import com.raytheon.uf.viz.core.VizApp; +import com.raytheon.viz.ui.dialogs.CaveSWTDialog; + +/** + * Class to show progress of creating a case. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jun 3, 2013  1966       rferrel     Initial creation
+ * 
+ * 
+ * + * @author rferrelGenerateJob + * @version 1.0 + */ + +public class GenerateCaseDlg extends CaveSWTDialog { + private final IUFStatusHandler statusHandler = UFStatus + .getHandler(GenerateCaseDlg.class); + + /** Use to display the current state of the case generation. */ + private Label stateLbl; + + /** Progress bar to indicate activity. */ + private ProgressBar progressBar; + + /** Stops the case generation leaving it in an unknown state. */ + private Button cancelBtn; + + /** Active have generation is finish or has an error. */ + private Button closeBtn; + + /** The main destination directory. */ + private final File targetDir; + + /** + * The case's destination directory. Assumed to be a sub-directory of + * targetDir. + */ + private final File caseDir; + + /** Starting time for the case. */ + private final Calendar startCal; + + /** End time for the case. */ + private final Calendar endCal; + + /** Data list for the case. */ + private final List sourceDataList; + + /** When true compress the case directory. */ + private final boolean doCompress; + + /** When true break the compress file into multliple files. */ + private final boolean doMultiFiles; + + /** The compress size for muliple files. */ + private final int compressSize; + + /** Assumed to be MG or GB to indicate scaling factor for compressSize. */ + private final String sizeType; + + /** Job to perform the case generation off of the UI thread. */ + private GenerateJob generateJob; + + /** Shorten case name to use in status message. */ + private final String caseName; + + /** Listeners to add to the job when scheduled. */ + private final List jobListeners = new ArrayList(); + + /** Data manager. */ + private final ArchiveConfigManager archiveManager = ArchiveConfigManager + .getInstance(); + + /** + * Constructor. + * + * @param parentShell + * @param targetDir + * @param caseDir + * @param startCal + * @param endCal + * @param sourceList + * @param doCompress + * @param doMultiFiles + * @param compressSize + * @param sizeType + */ + protected GenerateCaseDlg(Shell parentShell, File targetDir, File caseDir, + Calendar startCal, Calendar endCal, List sourceList, + boolean doCompress, boolean doMultiFiles, int compressSize, + String sizeType) { + super(parentShell, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL, + CAVE.DO_NOT_BLOCK); + this.targetDir = targetDir; + this.caseDir = caseDir; + this.startCal = startCal; + this.endCal = endCal; + this.sourceDataList = new ArrayList(sourceList); + this.doCompress = doCompress; + this.doMultiFiles = doMultiFiles; + this.compressSize = compressSize; + this.sizeType = sizeType; + this.caseName = caseDir.getAbsolutePath().substring( + targetDir.getAbsolutePath().length() + 1); + setText("Generating - " + caseName); + } + + /** + * Add a job listener. + * + * @param listener + */ + protected void addJobChangeListener(IJobChangeListener listener) { + jobListeners.add(listener); + } + + /** + * Remve a job listener. + * + * @param listener + */ + protected void removeJobChangeListener(IJobChangeListener listener) { + jobListeners.remove(listener); + } + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.viz.ui.dialogs.CaveSWTDialogBase#initializeComponents(org + * .eclipse.swt.widgets.Shell) + */ + @Override + protected void initializeComponents(Shell shell) { + Composite mainComp = new Composite(shell, SWT.NONE); + GridLayout gl = new GridLayout(1, false); + gl.marginHeight = 0; + gl.marginWidth = 0; + gl.horizontalSpacing = 0; + mainComp.setLayout(gl); + + init(); + } + + /** + * Set up main layout. + */ + private void init() { + createProgress(); + GuiUtil.addSeparator(shell, SWT.HORIZONTAL); + createBottomActionButtons(); + } + + /** + * The progress component. + */ + private void createProgress() { + Composite progComp = new Composite(shell, SWT.NONE); + GridLayout gl = new GridLayout(1, false); + progComp.setLayout(gl); + + GridData gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false); + gd.minimumWidth = 300; + stateLbl = new Label(shell, SWT.BORDER | SWT.CENTER); + stateLbl.setLayoutData(gd); + stateLbl.setText("state of progress goes here."); + + progressBar = new ProgressBar(shell, SWT.DEFAULT); + gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false); + progressBar.setLayoutData(gd); + } + + /** + * Component for the action buttons. + */ + private void createBottomActionButtons() { + Composite actionComp = new Composite(shell, SWT.NONE); + GridLayout gl = new GridLayout(2, false); + actionComp.setLayout(gl); + + cancelBtn = new Button(actionComp, SWT.PUSH); + cancelBtn.setText(" Cancel "); + cancelBtn.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + if (generateJob != null && generateJob.getState() != Job.NONE) { + generateJob.cancel(); + } + + close(); + } + }); + + closeBtn = new Button(actionComp, SWT.PUSH); + closeBtn.setText(" Close "); + closeBtn.setEnabled(false); + closeBtn.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + close(); + } + }); + } + + /* + * (non-Javadoc) + * + * @see com.raytheon.viz.ui.dialogs.CaveSWTDialog#preOpened() + */ + @Override + protected void preOpened() { + super.preOpened(); + + generateJob = new GenerateJob(); + for (IJobChangeListener listener : jobListeners) { + generateJob.addJobChangeListener(listener); + } + + generateJob.schedule(); + shell.addShellListener(new ShellAdapter() { + + @Override + public void shellClosed(ShellEvent e) { + if (generateJob != null && generateJob.getState() != Job.NONE) { + e.doit = false; + } + } + }); + } + + /** + * Allow a non-UI thread to update the state label. + * + * @param message + * @param tooltip + */ + private void setStateLbl(final String message, final String tooltip) { + VizApp.runAsync(new Runnable() { + @Override + public void run() { + if (!stateLbl.isDisposed()) { + stateLbl.setText(message); + stateLbl.setToolTipText(tooltip); + } + } + }); + } + + /** + * Allow a non-UI thread to update the progress bar and background of the + * state label when there is an error. + * + * @param value + * @param state + */ + private void setProgressBar(final int value, final int state) { + VizApp.runAsync(new Runnable() { + + @Override + public void run() { + if (!progressBar.isDisposed()) { + int val = value; + if (val < progressBar.getMinimum()) { + val = progressBar.getMinimum(); + } else if (val >= progressBar.getMaximum()) { + val = progressBar.getMaximum(); + closeBtn.setEnabled(true); + cancelBtn.setEnabled(false); + } + progressBar.setSelection(val); + progressBar.setState(state); + progressBar.setVisible(val != progressBar.getMaximum()); + Color bgColor = null; + if (state == SWT.ERROR) { + bgColor = shell.getDisplay().getSystemColor( + SWT.COLOR_RED); + } + stateLbl.setBackground(bgColor); + } + } + }); + } + + /* + * (non-Javadoc) + * + * @see com.raytheon.viz.ui.dialogs.CaveSWTDialogBase#disposed() + */ + @Override + protected void disposed() { + if (generateJob != null && generateJob.getState() != Job.NONE) { + generateJob.cancel(); + } + } + + /** + * The performs the work of generating the case on a non-UI thread. + */ + private class GenerateJob extends Job { + boolean shutdown = false; + + public GenerateJob() { + super("Generate Job"); + } + + @Override + protected IStatus run(IProgressMonitor monitor) { + if (monitor.isCanceled()) { + return Status.OK_STATUS; + } + + setStateLbl("Creating: " + caseDir.getName(), + caseDir.getAbsolutePath()); + if (caseDir.exists()) { + setStateLbl("Case exists: " + caseName, + caseDir.getAbsolutePath()); + setProgressBar(100, SWT.ERROR); + return Status.OK_STATUS; + } + + if (!caseDir.mkdirs()) { + setStateLbl("Unable to create case: " + caseName, + caseDir.getAbsolutePath()); + setProgressBar(100, SWT.ERROR); + return Status.OK_STATUS; + } + + if (shutdown) { + return Status.OK_STATUS; + } + + for (DisplayData displayData : sourceDataList) { + if (shutdown) { + return Status.OK_STATUS; + } + + setStateLbl( + "Copying \"" + displayData.getDisplayLabel() + "\"", + null); + String rootDir = displayData.getRootDir(); + int beginIndex = rootDir.length(); + + List files = archiveManager.getDisplayFiles(displayData, + startCal, endCal); + for (File source : files) { + if (shutdown) { + return Status.OK_STATUS; + } + + String name = source.getAbsolutePath(); + String relativePath = name.substring(beginIndex); + + setStateLbl("Copy: " + relativePath, name); + File destination = new File(caseDir, relativePath); + try { + if (source.isDirectory()) { + destination.mkdirs(); + FileUtil.copyDirectory(source, destination); + } else { + File destParent = caseDir.getParentFile(); + destParent.mkdirs(); + FileUtil.copyFile(source, destination); + } + } catch (IOException e) { + statusHandler.handle(Priority.PROBLEM, + e.getLocalizedMessage(), e); + } + } + } + + if (!doCompress) { + setProgressBar(100, SWT.NORMAL); + setStateLbl("Created: " + caseName, caseDir.getAbsolutePath()); + return Status.OK_STATUS; + } + + if (shutdown) { + return Status.OK_STATUS; + } + + if (doMultiFiles) { + setProgressBar(100, SWT.NORMAL); + String message = "Compress into multifiles NYI."; + setStateLbl(message, null); + } else { + setProgressBar(100, SWT.NORMAL); + String message = "Compress into one file NYI"; + setStateLbl(message, null); + } + + return Status.OK_STATUS; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.core.runtime.jobs.Job#canceling() + */ + @Override + protected void canceling() { + shutdown = true; + generateJob = null; + } + } +} diff --git a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/GuiUtil.java b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/GuiUtil.java new file mode 100644 index 0000000000..4d02e65d0a --- /dev/null +++ b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/GuiUtil.java @@ -0,0 +1,70 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.viz.archive.ui; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; + +/** + * Common methods used in the dialogs. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jun 6, 2013  1966       rferrel     Initial creation
+ * 
+ * 
+ * + * @author rferrel + * @version 1.0 + */ + +public class GuiUtil { + private GuiUtil() { + } + + /** + * Add a separator line to the provided container. + * + * @param container + * Composite. + * @param orientation + * Vertical or horizontal orientation. + */ + public static void addSeparator(Composite container, int orientation) { + // Separator label + GridData gd; + + if (orientation == SWT.HORIZONTAL) { + gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false); + } else { + gd = new GridData(SWT.DEFAULT, SWT.FILL, false, true); + } + + Label sepLbl = new Label(container, SWT.SEPARATOR | orientation); + sepLbl.setLayoutData(gd); + } + +} diff --git a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/ArchiveConfigManager.java b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/ArchiveConfigManager.java index 32676d4e53..0694d853e7 100644 --- a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/ArchiveConfigManager.java +++ b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/ArchiveConfigManager.java @@ -78,16 +78,21 @@ public class ArchiveConfigManager { private final IUFStatusHandler statusHandler = UFStatus .getHandler(ArchiveConfigManager.class); + /** The only instance or this class. */ private final static ArchiveConfigManager instance = new ArchiveConfigManager(); + /** Localize directory for the archive configuration files. */ public final String ARCHIVE_DIR = "archive"; + /** Localization manager. */ private IPathManager pathMgr; private final Map archiveNameToLocalizationFileMap = new HashMap(); + /** Mapping of archive configuration data keyed to the name. */ private final Map archiveMap = new HashMap(); + /** Get the singleton. */ public final static ArchiveConfigManager getInstance() { return instance; } @@ -671,19 +676,46 @@ public class ArchiveConfigManager { * with a display label. Allows a GUI to maintain the state of the display * instead of the manager. */ - public class DisplayData { + public static class DisplayData { + + /** Label to use when size not yet known. */ + public static final String UNKNOWN_SIZE_LABEL = "????"; + + /** A negative value to indicate unknown size. */ + public static final long UNKNOWN_SIZE = -1L; + + /** The data's archive configuration. */ protected final ArchiveConfig archiveConfig; + /** The data's category configration. */ protected final CategoryConfig categoryConfig; + /** The display label for this data. */ protected final String displayLabel; + /** + * List of directories for the display label matching the category's + * directory pattern and found under the archive's root directory. + */ protected final List dirs; + /** + * For use by GUI to indicate. Use to indicate selected for retention or + * for placing in a case. + */ private boolean selected = false; - private long size = -1L; + /** For use by GUI for indicating the size of the directories' contents. */ + private long size = UNKNOWN_SIZE; + /** + * Constructor. + * + * @param archiveConfig + * @param categoryConfig + * @param displayLabel + * @param dirs + */ public DisplayData(ArchiveConfig archiveConfig, CategoryConfig categoryConfig, String displayLabel, List dirs) { @@ -693,36 +725,92 @@ public class ArchiveConfigManager { this.dirs = dirs; } + /** + * Is instance selected. + * + * @return selected + */ public boolean isSelected() { return selected; } + /** + * Set selected state. + * + * @param selected + */ public void setSelected(boolean selected) { this.selected = selected; } + /** + * + * @return displayLabel. + */ public String getDisplayLabel() { return displayLabel; } + /** + * The size of the directories' contents. + * + * @return size + */ public long getSize() { return size; } + /** + * Set the size of the directories' contents. + * + * @param size + */ public void setSize(long size) { this.size = size; } + /** + * The archive's root directory name. + * + * @return rootDir + */ + public String getRootDir() { + return archiveConfig.getRootDir(); + } + + /** + * Determine if this is the name of the archive. + * + * @param archiveName + * @return + */ + public boolean isArchive(String archiveName) { + return archiveConfig.getName().equals(archiveName); + } + + /** + * Determine if this is the name of the category. + * + * @param categoryName + * @return + */ + public boolean isCategory(String categoryName) { + return categoryConfig.getName().equals(categoryName); + } + + /** + * Determine if the object contains the same data as the instance. + */ public boolean equals(Object object) { if (this == object) { return true; } if (object instanceof DisplayData) { - DisplayData displayInfo = (DisplayData) object; - return (archiveConfig == displayInfo.archiveConfig - && categoryConfig == displayInfo.categoryConfig && displayLabel - .equals(displayInfo.displayLabel)); + DisplayData displayData = (DisplayData) object; + return (archiveConfig == displayData.archiveConfig + && categoryConfig == displayData.categoryConfig && displayLabel + .equals(displayData.displayLabel)); } return false; }