true
if and only if the instant of time
+ * represented by the first Date object is equal to
+ * or earlier than the instant represented by the second;
+ * false
otherwise.
+ * @exception NullPointerException if either is null.
+ */
+ public static boolean beforeEqual(Date one, Date two) {
+ return one.getTime() <= two.getTime();
+ }
+
+ /**
+ * Tests if the first date is after or equal to the second date.
+ *
+ * @param one
+ * @param two
+ * @return true
if and only if the instant represented
+ * by the first Date object is equal to or later
+ * than the instant represented by the second;
+ * false
otherwise.
+ * @exception NullPointerException if either is null.
+ */
+ public static boolean afterEqual(Date one, Date two) {
+ return one.getTime() >= two.getTime();
+ }
+}
diff --git a/ResearchManagementSystem/src/rms/util/DateRangeType.java b/ResearchManagementSystem/src/rms/util/DateRangeType.java
new file mode 100644
index 0000000..8fbf141
--- /dev/null
+++ b/ResearchManagementSystem/src/rms/util/DateRangeType.java
@@ -0,0 +1,23 @@
+package rms.util;
+
+/**
+ *
+ * @author Timothy
+ */
+public enum DateRangeType {
+ CREATED("completed"), MODIFIED("modified"), DEADLINE("with deadline");
+
+ private final String text;
+
+ /**
+ * @param text
+ */
+ private DateRangeType(final String text) {
+ this.text = text;
+ }
+
+ @Override
+ public String toString() {
+ return text;
+ }
+}
diff --git a/ResearchManagementSystem/src/rms/util/DateUnit.java b/ResearchManagementSystem/src/rms/util/DateUnit.java
new file mode 100644
index 0000000..85b644f
--- /dev/null
+++ b/ResearchManagementSystem/src/rms/util/DateUnit.java
@@ -0,0 +1,23 @@
+package rms.util;
+
+/**
+ *
+ * @author Timothy
+ */
+public enum DateUnit {
+ DAY("day(s)"), WEEK("week(s)"), MONTH("month(s)");
+
+ private final String text;
+
+ /**
+ * @param text
+ */
+ private DateUnit(final String text) {
+ this.text = text;
+ }
+
+ @Override
+ public String toString() {
+ return text;
+ }
+}
diff --git a/ResearchManagementSystem/src/rms/util/Helpers.java b/ResearchManagementSystem/src/rms/util/Helpers.java
new file mode 100644
index 0000000..ae9175d
--- /dev/null
+++ b/ResearchManagementSystem/src/rms/util/Helpers.java
@@ -0,0 +1,42 @@
+package rms.util;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Static utility methods
+ *
+ * @author Timothy
+ */
+public final class Helpers {
+
+ private static final Logger thisLog = Logger.getLogger(Helpers.class.getName());
+
+ /**
+ * Checks if String s1 contains string s2 in a case insensitive manner
+ *
+ * @param s1
+ * @param s2
+ * @return
+ */
+ public static boolean containsIgnoreCase(String s1, String s2){
+ return s1.toLowerCase().contains(s2.toLowerCase());
+ }
+
+ /**
+ * Closes the Closable resource if it is not null or already closed.
+ *
+ * @param c
+ */
+ public static void closeResource(Closeable c) {
+ if (c != null) {
+ try {
+ c.close();
+ } catch (IOException ex) {
+ thisLog.log(Level.WARNING, "Error closing resource", ex);
+ }
+ }
+ }
+}
diff --git a/ResearchManagementSystem/src/rms/view/MainFrame.form b/ResearchManagementSystem/src/rms/view/MainFrame.form
new file mode 100644
index 0000000..69ce9f3
--- /dev/null
+++ b/ResearchManagementSystem/src/rms/view/MainFrame.form
@@ -0,0 +1,540 @@
+
+
+
diff --git a/ResearchManagementSystem/src/rms/view/MainFrame.java b/ResearchManagementSystem/src/rms/view/MainFrame.java
new file mode 100644
index 0000000..0ed392f
--- /dev/null
+++ b/ResearchManagementSystem/src/rms/view/MainFrame.java
@@ -0,0 +1,1055 @@
+package rms.view;
+
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.concurrent.ExecutionException;
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.JScrollBar;
+import javax.swing.SwingWorker;
+import javax.swing.border.EtchedBorder;
+import rms.control.Main;
+import rms.control.search.AbstractFinder;
+import rms.control.search.LateTaskFinder;
+import rms.control.search.PendingTaskFinder;
+import rms.control.search.TagFinder;
+import rms.model.Tag;
+import rms.model.item.FileItem;
+import rms.model.item.Item;
+import rms.model.item.ItemThread;
+import rms.model.item.NoteItem;
+import rms.model.item.TaskItem;
+import rms.view.item.PanelFileItem;
+import rms.view.item.PanelNoteItem;
+import rms.view.item.PanelTaskItem;
+import rms.view.search.BaseDialog;
+import rms.view.search.DialogDateRange;
+import rms.view.search.DialogDeadline;
+import rms.view.search.DialogSearchTags;
+import rms.view.search.DialogSearchText;
+import rms.view.util.LoadingPanel;
+import rms.view.util.Prompts;
+import rms.view.util.Prompts.PromptType;
+import rms.view.util.WrapLayout;
+
+/**
+ * The main UI window (singleton)
+ *
+ * @author Timothy
+ */
+public class MainFrame extends rms.view.util.NotificationFrame {
+
+ private final boolean DEBUG_WORKERS = false;
+
+ private static MainFrame inst = null;
+
+ /**
+ * Creates new form MainFrame2
+ */
+ private MainFrame() {
+ initComponents();
+ initComponentsMore();
+ }
+
+ @SuppressWarnings("unchecked")
+ // getResult()
will
+ * always return null
+ * @return
+ */
+ protected AbstractFinder createFinder(){
+ return null;
+ }
+
+ public AbstractFinder getResult(){
+ AbstractFinder retVal = null;
+ if(approved){
+ retVal = createFinder();
+ }
+ return retVal;
+ }
+
+ public Container getInnerContentPanel() {
+ return jPanelContent;
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // WrapLayout
with a left alignment and a
+ * default 5-unit horizontal and vertical gap.
+ */
+ public WrapLayout() {
+ super();
+ }
+
+ /**
+ * Constructs a new FlowLayout
with the specified alignment and
+ * a default 5-unit horizontal and vertical gap. The value of the alignment
+ * argument must be one of WrapLayout
, WrapLayout
,
+ * or WrapLayout
.
+ *
+ * @param align the alignment value
+ */
+ public WrapLayout(int align) {
+ super(align);
+ }
+
+ /**
+ * Creates a new flow layout manager with the indicated alignment and the
+ * indicated horizontal and vertical gaps.
+ *
+ * The value of the alignment argument must be one of
+ * WrapLayout
, WrapLayout
, or
+ * WrapLayout
.
+ *
+ * @param align the alignment value
+ * @param hgap the horizontal gap between components
+ * @param vgap the vertical gap between components
+ */
+ public WrapLayout(int align, int hgap, int vgap) {
+ super(align, hgap, vgap);
+ }
+
+ /**
+ * Returns the preferred dimensions for this layout given the
+ * visible components in the specified target container.
+ *
+ * @param target the component which needs to be laid out
+ * @return the preferred dimensions to lay out the subcomponents of the
+ * specified container
+ */
+ @Override
+ public Dimension preferredLayoutSize(Container target) {
+ return layoutSize(target, true);
+ }
+
+ /**
+ * Returns the minimum dimensions needed to layout the visible
+ * components contained in the specified target container.
+ *
+ * @param target the component which needs to be laid out
+ * @return the minimum dimensions to lay out the subcomponents of the
+ * specified container
+ */
+ @Override
+ public Dimension minimumLayoutSize(Container target) {
+ Dimension minimum = layoutSize(target, false);
+ minimum.width -= (getHgap() + 1);
+ return minimum;
+ }
+
+ /**
+ * Returns the minimum or preferred dimension needed to layout the target
+ * container.
+ *
+ * @param target target to get layout size for
+ * @param preferred should preferred size be calculated
+ * @return the dimension to layout the target container
+ */
+ private Dimension layoutSize(Container target, boolean preferred) {
+ synchronized (target.getTreeLock()) {
+ // Each row must fit with the width allocated to the containter.
+ // When the container width = 0, the preferred width of the container
+ // has not yet been calculated so lets ask for the maximum.
+
+ int targetWidth = target.getSize().width;
+
+ if (targetWidth == 0) {
+ targetWidth = Integer.MAX_VALUE;
+ }
+
+ int hgap = getHgap();
+ int vgap = getVgap();
+ Insets insets = target.getInsets();
+ int horizontalInsetsAndGap = insets.left + insets.right + (hgap * 2);
+ int maxWidth = targetWidth - horizontalInsetsAndGap;
+
+ // Fit components into the allowed width
+ Dimension dim = new Dimension(0, 0);
+ int rowWidth = 0;
+ int rowHeight = 0;
+
+ int nmembers = target.getComponentCount();
+
+ for (int i = 0; i < nmembers; i++) {
+ Component m = target.getComponent(i);
+
+ if (m.isVisible()) {
+ Dimension d = preferred ? m.getPreferredSize() : m.getMinimumSize();
+
+ // Can't add the component to current row. Start a new row.
+ if (rowWidth + d.width > maxWidth) {
+ addRow(dim, rowWidth, rowHeight);
+ rowWidth = 0;
+ rowHeight = 0;
+ }
+
+ // Add a horizontal gap for all components after the first
+ if (rowWidth != 0) {
+ rowWidth += hgap;
+ }
+
+ rowWidth += d.width;
+ rowHeight = Math.max(rowHeight, d.height);
+ }
+ }
+
+ addRow(dim, rowWidth, rowHeight);
+
+ dim.width += horizontalInsetsAndGap;
+ dim.height += insets.top + insets.bottom + vgap * 2;
+
+ // When using a scroll pane or the DecoratedLookAndFeel we need to
+ // make sure the preferred size is less than the size of the
+ // target containter so shrinking the container size works
+ // correctly. Removing the horizontal gap is an easy way to do this.
+ Container scrollPane = SwingUtilities.getAncestorOfClass(JScrollPane.class, target);
+
+ if (scrollPane != null && target.isValid()) {
+ dim.width -= (hgap + 1);
+ }
+
+ return dim;
+ }
+ }
+
+ /*
+ * A new row has been completed. Use the dimensions of this row
+ * to update the preferred size for the container.
+ *
+ * @param dim update the width and height when appropriate
+ * @param rowWidth the width of the row to add
+ * @param rowHeight the height of the row to add
+ */
+ private void addRow(Dimension dim, int rowWidth, int rowHeight) {
+ dim.width = Math.max(dim.width, rowWidth);
+
+ if (dim.height > 0) {
+ dim.height += getVgap();
+ }
+
+ dim.height += rowHeight;
+ }
+}
diff --git a/ResearchManagementSystem/src/rms/view/util/loading.gif b/ResearchManagementSystem/src/rms/view/util/loading.gif
new file mode 100644
index 0000000..0ca7ada
Binary files /dev/null and b/ResearchManagementSystem/src/rms/view/util/loading.gif differ