aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/uk/org/ury/database/DatabaseItem.java70
-rw-r--r--src/uk/org/ury/database/exceptions/MissingPropertyException.java47
-rw-r--r--src/uk/org/ury/database/exceptions/QueryFailureException.java1
-rw-r--r--src/uk/org/ury/frontend/FrontendBanner.java68
-rw-r--r--src/uk/org/ury/frontend/FrontendControlPanel.java97
-rw-r--r--src/uk/org/ury/frontend/FrontendFrame.java205
-rw-r--r--src/uk/org/ury/frontend/FrontendMaster.java65
-rw-r--r--src/uk/org/ury/frontend/FrontendModule.java14
-rw-r--r--src/uk/org/ury/frontend/FrontendModulePanel.java90
-rw-r--r--src/uk/org/ury/frontend/FrontendPanel.java84
-rw-r--r--src/uk/org/ury/frontend/images/ury.pngbin10143 -> 6566 bytes
-rw-r--r--src/uk/org/ury/library/LibraryItem.java84
-rw-r--r--src/uk/org/ury/library/LibraryItemProperty.java43
-rw-r--r--src/uk/org/ury/library/LibraryTableModel.java116
-rw-r--r--src/uk/org/ury/library/LibraryUtils.java60
-rw-r--r--src/uk/org/ury/library/viewer/LibraryViewer.java69
-rw-r--r--src/uk/org/ury/library/viewer/LibraryViewerPanel.java72
-rw-r--r--src/uk/org/ury/library/viewer/library_viewer_gui.xml9
-rw-r--r--src/uk/org/ury/show/ShowChannel.java92
-rw-r--r--src/uk/org/ury/show/ShowItem.java25
-rw-r--r--src/uk/org/ury/show/ShowItemProperty.java26
-rw-r--r--src/uk/org/ury/show/ShowUtils.java153
-rw-r--r--src/uk/org/ury/show/viewer/ChannelPanel.java100
-rw-r--r--src/uk/org/ury/show/viewer/LibraryControlPanel.java33
-rw-r--r--src/uk/org/ury/show/viewer/ShowViewer.java161
-rw-r--r--src/uk/org/ury/show/viewer/ShowViewerPanel.java82
-rw-r--r--src/uk/org/ury/show/viewer/channel_panel.xml36
-rw-r--r--src/uk/org/ury/show/viewer/library_control_panel.xml13
-rw-r--r--src/uk/org/ury/show/viewer/show_viewer_gui.xml25
-rw-r--r--src/uk/org/ury/testrig/DemoControlPanel.java33
-rw-r--r--src/uk/org/ury/testrig/DemoMenu.java112
-rw-r--r--src/uk/org/ury/testrig/demo_control_panel.xml9
32 files changed, 1814 insertions, 280 deletions
diff --git a/src/uk/org/ury/database/DatabaseItem.java b/src/uk/org/ury/database/DatabaseItem.java
new file mode 100644
index 0000000..4f6d34d
--- /dev/null
+++ b/src/uk/org/ury/database/DatabaseItem.java
@@ -0,0 +1,70 @@
+package uk.org.ury.database;
+
+import java.util.Map;
+
+import uk.org.ury.database.exceptions.MissingPropertyException;
+
+
+/**
+ * An abstract class presenting a template for objects serving as
+ * a data structure for collections of properties retrieved from
+ * a SQL database.
+ *
+ * @param E The enumeration type used as the property list.
+ *
+ * @param T The type of datum stored for each property.
+ *
+ * @author Matt Windsor
+ */
+
+public abstract class DatabaseItem<E, T>
+{
+ private Map<E, T> properties;
+
+ /**
+ * Construct a new item from an existing list of properties.
+ *
+ * @param properties The map of properties that the new item will
+ * inherit.
+ */
+
+ public
+ DatabaseItem (Map<E, T> properties)
+ {
+ this.properties = properties;
+ }
+
+
+ /**
+ * Check whether a property has been set in the item.
+ *
+ * @return true if the property has been set; false otherwise.
+ */
+
+ public boolean
+ has (E property)
+ {
+ return properties.containsKey (property);
+ }
+
+
+ /**
+ * Query this item for a property.
+ *
+ * @param property The property to query.
+ *
+ * @return The property, if it exists.
+ *
+ * @throws MissingPropertyException if the property does
+ * not exist.
+ */
+
+ public T
+ get (E property) throws MissingPropertyException
+ {
+ if (properties.containsKey (property))
+ return properties.get (property);
+ else
+ throw new MissingPropertyException (property.toString ());
+ }
+}
diff --git a/src/uk/org/ury/database/exceptions/MissingPropertyException.java b/src/uk/org/ury/database/exceptions/MissingPropertyException.java
new file mode 100644
index 0000000..3766fcf
--- /dev/null
+++ b/src/uk/org/ury/database/exceptions/MissingPropertyException.java
@@ -0,0 +1,47 @@
+/**
+ *
+ */
+package uk.org.ury.database.exceptions;
+
+
+/**
+ * Exception thrown when a DatabaseItem is queried for a property
+ * that does not exist.
+ *
+ * This is (usually) not a fatal error.
+ *
+ * @author Matt Windsor
+ */
+
+public class MissingPropertyException extends Exception
+{
+ /**
+ *
+ */
+ private static final long serialVersionUID = -7353531873142099828L;
+
+
+/**
+ * Construct a new MissingPropertyException with a
+ * default reason.
+ */
+
+ public
+ MissingPropertyException ()
+ {
+ super ("Query failure.");
+ }
+
+
+ /**
+ * Construct a new MissingPropertyException.
+ *
+ * @param reason The explanation for the exception.
+ */
+
+ public
+ MissingPropertyException (String reason)
+ {
+ super (reason);
+ }
+}
diff --git a/src/uk/org/ury/database/exceptions/QueryFailureException.java b/src/uk/org/ury/database/exceptions/QueryFailureException.java
index d7b3e5b..5293a7c 100644
--- a/src/uk/org/ury/database/exceptions/QueryFailureException.java
+++ b/src/uk/org/ury/database/exceptions/QueryFailureException.java
@@ -3,6 +3,7 @@
*/
package uk.org.ury.database.exceptions;
+
/**
* Exception thrown when the database backend fails to execute
* a query.
diff --git a/src/uk/org/ury/frontend/FrontendBanner.java b/src/uk/org/ury/frontend/FrontendBanner.java
new file mode 100644
index 0000000..f3ce502
--- /dev/null
+++ b/src/uk/org/ury/frontend/FrontendBanner.java
@@ -0,0 +1,68 @@
+package uk.org.ury.frontend;
+
+import java.awt.Color;
+import java.awt.FlowLayout;
+
+import javax.swing.BorderFactory;
+import javax.swing.ImageIcon;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+
+/**
+ * A banner, displaying a title, intended for use at the top of the
+ * frontend frame.
+ *
+ * @author Matt Windsor
+ */
+
+public class FrontendBanner extends JPanel
+{
+ /**
+ *
+ */
+ private static final long serialVersionUID = -3636933349004358394L;
+
+ private static final String TITLE_PREFIX = "<html><h1><font color=white>";
+ private static final String TITLE_SUFFIX = "</font></h1></html>";
+
+ private JLabel titleLabel;
+
+
+ /**
+ * Construct a new banner.
+ *
+ * @param title The initial title to display in the banner.
+ */
+
+ public
+ FrontendBanner (String title)
+ {
+ setLayout (new FlowLayout (FlowLayout.LEFT));
+ setBackground (new Color (0, 0, 0));
+
+
+ JLabel logo = new JLabel (new ImageIcon (getClass ().getResource ("images/ury.png")));
+
+
+ titleLabel = new JLabel (TITLE_PREFIX + title + TITLE_SUFFIX);
+ titleLabel.setBorder (BorderFactory.createEmptyBorder (5, 15, 5, 5));
+
+
+ add (logo);
+ add (titleLabel);
+ }
+
+
+ /**
+ * Change the title displayed on the banner.
+ *
+ * @param title The new title to display.
+ */
+
+ public void
+ setTitle (String title)
+ {
+ titleLabel.setText (TITLE_PREFIX + title + TITLE_SUFFIX);
+ }
+}
diff --git a/src/uk/org/ury/frontend/FrontendControlPanel.java b/src/uk/org/ury/frontend/FrontendControlPanel.java
new file mode 100644
index 0000000..5b7f486
--- /dev/null
+++ b/src/uk/org/ury/frontend/FrontendControlPanel.java
@@ -0,0 +1,97 @@
+/**
+ *
+ */
+package uk.org.ury.frontend;
+
+
+/**
+ * Abstract class for frontend module control panels.
+ *
+ * Control panels are installed as a means of exposing module
+ * intercommunication to the user. For example, when the library
+ * viewer is launched from the playout module, a control panel
+ * is installed allowing the user to add library items to the
+ * playout system.
+ *
+ * @author Matt Windsor
+ */
+
+public abstract class FrontendControlPanel extends FrontendPanel
+{
+ /**
+ *
+ */
+ private static final long serialVersionUID = -5628250552779928189L;
+
+ protected FrontendControlPanel prevCPanel;
+ protected FrontendModulePanel parent;
+ protected FrontendModulePanel child;
+
+
+ /**
+ * Alternative constructor allowing an XML file to be used to
+ * create the layout of the ControlPanel.
+ *
+ * This is provided for the benefit of subclasses of this class
+ * that use it in their default constructors.
+ *
+ * @param xmlPath The path, relative from this source file, to the
+ * XML file from which this panel will read its
+ * layout.
+ */
+
+ public
+ FrontendControlPanel (String xmlPath)
+ {
+ super (xmlPath, null);
+ }
+
+
+ /**
+ * Set the frontend master to which this panel is bound.
+ *
+ * @param master The master to set.
+ */
+
+ public void
+ setMaster (FrontendMaster master)
+ {
+ this.master = master;
+ }
+
+
+ /**
+ * Set the parent and child panels that this ControlPanel
+ * facilitates intercommunication.
+ *
+ * @param parent The panel belonging to the parent module,
+ * or the module that was switched out in place of
+ * the child.
+ *
+ * @param child The panel belonging to the child module,
+ * or the module that was switched in in place of
+ * the parent.
+ */
+
+ public void
+ setPanels (FrontendModulePanel parent, FrontendModulePanel child)
+ {
+ this.parent = parent;
+ this.child = child;
+ }
+
+
+ /**
+ * Set the previous control panel (if any), so that it can be
+ * restored when this control panel returns control to the
+ * parent.
+ *
+ * @param cpanel The previous control panel.
+ */
+
+ public void
+ setPreviousCPanel (FrontendControlPanel cpanel)
+ {
+ prevCPanel = cpanel;
+ }
+}
diff --git a/src/uk/org/ury/frontend/FrontendFrame.java b/src/uk/org/ury/frontend/FrontendFrame.java
index 6324512..ef2a31a 100644
--- a/src/uk/org/ury/frontend/FrontendFrame.java
+++ b/src/uk/org/ury/frontend/FrontendFrame.java
@@ -4,26 +4,20 @@
package uk.org.ury.frontend;
import java.awt.BorderLayout;
-import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
-import java.awt.FlowLayout;
-import javax.swing.BorderFactory;
-import javax.swing.ImageIcon;
import javax.swing.JFrame;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
/**
- * A frame that hosts a FrontendPanel, used for serving frontend
+ * A frame that hosts a FrontendModulePanel, used for serving frontend
* panels in a window (application mode).
*
* @author Matt Windsor
*
*/
-public class FrontendFrame extends JFrame
+public class FrontendFrame extends JFrame implements FrontendMaster
{
/**
*
@@ -31,31 +25,24 @@ public class FrontendFrame extends JFrame
private static final long serialVersionUID = 740928181256928433L;
- private FrontendPanel parent;
+ private FrontendBanner banner;
+ private FrontendModulePanel child;
+ private FrontendControlPanel cpanel;
public
- FrontendFrame (FrontendPanel parent)
+ FrontendFrame (FrontendModulePanel parent)
{
super (parent.getName ());
setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
- this.parent = parent;
+ this.child = parent;
Container cp = getContentPane ();
// Banner
- JPanel banner = new JPanel ();
- JLabel bannerLabel = new JLabel ("<html><h1><font color=white>"
- + parent.getName () + "</font></h1></html>");
-
- bannerLabel.setBorder (BorderFactory.createEmptyBorder (5, 15, 5, 5));
-
- banner.setLayout (new FlowLayout (FlowLayout.LEFT));
- banner.setBackground (new Color (0, 0, 0));
- banner.add (new JLabel (new ImageIcon (getClass ().getResource ("images/ury.png"))));
- banner.add (bannerLabel);
+ banner = new FrontendBanner (parent.getName ());
// Composition
@@ -67,4 +54,180 @@ public class FrontendFrame extends JFrame
pack ();
setVisible (true);
}
+
+
+ /**
+ * Load a module into the frontend frame.
+ *
+ * Loading will fail with a fatal error if the class is not found,
+ * or is not an implementor of FrontendModule.
+ *
+ * @param moduleName The fully qualified class-name of the module,
+ * minus the leading "uk.org.ury." domain.
+ */
+
+ @Override
+ public void
+ loadModule (String moduleName)
+ {
+ Class<?> moduleClass = null;
+
+ try
+ {
+ moduleClass = Class.forName ("uk.org.ury." + moduleName);
+ }
+ catch (ClassNotFoundException e)
+ {
+ FrontendError.reportFatal ("Could not load module: " + e.getMessage (), this);
+ }
+
+
+ if (FrontendModule.class.isAssignableFrom (moduleClass))
+ {
+ FrontendModulePanel temp = child;
+
+ try
+ {
+ child = ((FrontendModule) moduleClass.newInstance ()).runFrontend (this);
+ }
+ catch (InstantiationException e)
+ {
+ FrontendError.reportFatal ("Could not load module: " + e.getMessage (), this);
+ }
+ catch (IllegalAccessException e)
+ {
+ FrontendError.reportFatal ("Could not load module: " + e.getMessage (), this);
+ }
+
+ remove (temp);
+ add (child);
+
+ banner.setTitle (child.getName ());
+ pack ();
+ }
+ }
+
+
+ /**
+ * Load a module into the frontend frame, additionally installing
+ * a control panel to communicate with the previous module.
+ *
+ * Loading will fail with a fatal error if the class is not found,
+ * or is not an implementor of FrontendModule.
+ *
+ * @param moduleName The fully qualified class-name of the module,
+ * minus the leading "uk.org.ury." domain.
+ *
+ * @param cPanelName The fully qualified class-name of the control
+ * panel to install, minus the leading
+ * "uk.org.ury." domain.
+ */
+
+ @Override
+ public void
+ loadModule (String moduleName, String cPanelName)
+ {
+ FrontendModulePanel newParent = child;
+ loadModule (moduleName);
+ FrontendModulePanel newChild = child;
+
+ loadControlPanel (cPanelName, newParent, newChild);
+ }
+
+
+ /**
+ * Load and install a control panel class given the class name.
+ *
+ * @param cPanelName The fully qualified class-name of the control
+ * panel to load, minus the leading
+ * "uk.org.ury." domain.
+ *
+ * @param parent The parent panel in the relationship modelled
+ * by the control panel interface.
+ *
+ * @param child The child panel in the relationship modelled
+ * by the control panel interface.
+ */
+
+ private void
+ loadControlPanel (String cPanelName, FrontendModulePanel parent,
+ FrontendModulePanel child)
+ {
+ Class<?> cPanelClass = null;
+
+ try
+ {
+ cPanelClass = Class.forName ("uk.org.ury." + cPanelName);
+ }
+ catch (ClassNotFoundException e)
+ {
+ FrontendError.reportFatal ("Could not load control panel: " + e.getMessage (), this);
+ }
+
+
+ if (FrontendControlPanel.class.isAssignableFrom (cPanelClass))
+ {
+ FrontendControlPanel temp = cpanel;
+
+ try
+ {
+ cpanel = ((FrontendControlPanel) cPanelClass.newInstance ());
+ }
+ catch (InstantiationException e)
+ {
+ FrontendError.reportFatal ("Could not load module: " + e.getMessage (), this);
+ }
+ catch (IllegalAccessException e)
+ {
+ FrontendError.reportFatal ("Could not load module: " + e.getMessage (), this);
+ }
+
+ if (temp != null)
+ remove (temp);
+
+ cpanel.setPanels (parent, child);
+ cpanel.setMaster (this);
+ cpanel.setPreviousCPanel (temp);
+
+ add (cpanel, BorderLayout.SOUTH);
+ pack ();
+ }
+ }
+
+
+ /**
+ * Restore an existing module and control panel into the frontend
+ * frame.
+ *
+ * @param mpanel The module panel to restore.
+ *
+ * @param cpanel The control panel to restore, if any. A null
+ * value signifies a lack of control panel.
+ *
+ * @throws IllegalArgumentException if the mpanel is null.
+ */
+
+ @Override
+ public void
+ restoreModule (FrontendModulePanel mpanel,
+ FrontendControlPanel cpanel)
+ {
+ if (mpanel == null)
+ throw new IllegalArgumentException ("mpanel is null.");
+
+ remove (child);
+ remove (this.cpanel);
+
+ child = mpanel;
+ add (child);
+ banner.setTitle (child.getName ());
+
+ if (cpanel != null)
+ add (cpanel, BorderLayout.SOUTH);
+
+ this.cpanel = cpanel;
+
+ pack ();
+ repaint ();
+ }
}
diff --git a/src/uk/org/ury/frontend/FrontendMaster.java b/src/uk/org/ury/frontend/FrontendMaster.java
new file mode 100644
index 0000000..c169d04
--- /dev/null
+++ b/src/uk/org/ury/frontend/FrontendMaster.java
@@ -0,0 +1,65 @@
+/**
+ *
+ */
+package uk.org.ury.frontend;
+
+
+/**
+ * Interface for classes providing the parent unit of a frontend
+ * session.
+ *
+ * This includes the FrontendFrame used in application mode as
+ * well as applets.
+ *
+ * @author Matt Windsor
+ */
+
+public interface FrontendMaster
+{
+ /**
+ * Load a module into the frontend frame.
+ *
+ * Loading will fail with a fatal error if the class is not found,
+ * or is not an implementor of FrontendModule.
+ *
+ * @param moduleName The fully qualified class-name of the module,
+ * minus the leading "uk.org.ury." domain.
+ */
+
+ public void
+ loadModule (String moduleName);
+
+
+ /**
+ * Load a module into the frontend frame, additionally installing
+ * a control panel to communicate with the previous module.
+ *
+ * Loading will fail with a fatal error if the class is not found,
+ * or is not an implementor of FrontendModule.
+ *
+ * @param moduleName The fully qualified class-name of the module,
+ * minus the leading "uk.org.ury." domain.
+ *
+ * @param cpanelName The fully qualified class-name of the control
+ * panel to install, minus the leading
+ * "uk.org.ury." domain.
+ */
+
+ public void
+ loadModule (String moduleName, String cPanelName);
+
+
+ /**
+ * Restore an existing module and control panel into the frontend
+ * master.
+ *
+ * @param mpanel The module panel to restore.
+ *
+ * @param cpanel The control panel to restore.
+ *
+ * @throws IllegalArgumentException if either are null.
+ */
+
+ public void
+ restoreModule (FrontendModulePanel mpanel, FrontendControlPanel cpanel);
+}
diff --git a/src/uk/org/ury/frontend/FrontendModule.java b/src/uk/org/ury/frontend/FrontendModule.java
index 407b2db..4d1e3bf 100644
--- a/src/uk/org/ury/frontend/FrontendModule.java
+++ b/src/uk/org/ury/frontend/FrontendModule.java
@@ -11,7 +11,7 @@ package uk.org.ury.frontend;
*
* - be runnable standalone, as either an application or an applet;
*
- * - contain their user interface in a subclass of FrontendPanel
+ * - contain their user interface in a subclass of FrontendModulePanel
* which can be embedded either in a FrontendFrame, a web page
* or another module;
*
@@ -27,5 +27,15 @@ package uk.org.ury.frontend;
public interface FrontendModule
{
- // Space for rent
+ /**
+ * Begin execution of the frontend module.
+ *
+ * @param master The FrontendMaster driving the frontend.
+ *
+ * @return the frontend panel to insert into the
+ * FrontendMaster.
+ */
+
+ public FrontendModulePanel
+ runFrontend (FrontendMaster master);
}
diff --git a/src/uk/org/ury/frontend/FrontendModulePanel.java b/src/uk/org/ury/frontend/FrontendModulePanel.java
new file mode 100644
index 0000000..148875f
--- /dev/null
+++ b/src/uk/org/ury/frontend/FrontendModulePanel.java
@@ -0,0 +1,90 @@
+/**
+ *
+ */
+package uk.org.ury.frontend;
+
+
+/**
+ * A frontend user interface panel.
+ *
+ * All frontend user interfaces should subclass this as their main
+ * interface space, so that frontend panels can include each other
+ * and panels can be embedded into application frames or applets.
+ *
+ * @author Matt Windsor
+ *
+ */
+
+public abstract class FrontendModulePanel extends FrontendPanel
+{
+ /**
+ *
+ */
+
+ private static final long serialVersionUID = 5616222530691425635L;
+
+ private FrontendModule module;
+
+
+ /**
+ * Construct a new, blank FrontendModulePanel.
+ *
+ * @param module the module that the panel is viewing.
+ *
+ * @param master The FrontendMaster driving the frontend.
+ */
+
+ public
+ FrontendModulePanel (FrontendModule module, FrontendMaster master)
+ {
+ super (master);
+ this.module = module;
+ }
+
+
+ /**
+ * Construct a FrontendModulePanel using an XML layout manifest.
+ *
+ * @param module the module that the panel is viewing.
+ *
+ * @param xmlPath The path, relative from this source file, to the
+ * XML file from which this panel will read its
+ * layout.
+ *
+ * @param master The FrontendMaster driving the frontend.
+ */
+
+ public
+ FrontendModulePanel (FrontendModule module, String xmlPath,
+ FrontendMaster master)
+ {
+ super (xmlPath, master);
+ this.module = module;
+ }
+
+
+ /**
+ * @return the name of the panel module.
+ */
+
+ public abstract String
+ getName ();
+
+
+ /**
+ * Retrieve the module that this panel is serving as a view into.
+ *
+ * @return the module.
+ */
+
+ public FrontendModule
+ getModule ()
+ {
+ return module;
+ }
+
+
+ /**
+ *
+ */
+}
diff --git a/src/uk/org/ury/frontend/FrontendPanel.java b/src/uk/org/ury/frontend/FrontendPanel.java
index 6012f22..1617ab0 100644
--- a/src/uk/org/ury/frontend/FrontendPanel.java
+++ b/src/uk/org/ury/frontend/FrontendPanel.java
@@ -1,32 +1,90 @@
-/**
- *
- */
package uk.org.ury.frontend;
+import java.net.URL;
+
import javax.swing.JPanel;
+import org.swixml.SwingEngine;
+
+
/**
- * A frontend user interface panel.
+ * An extension of JPanel providing common functionality for user
+ * interface panels in the URY system frontend.
*
- * All frontend user interfaces should subclass this as their main
- * interface space, so that frontend panels can include each other
- * and panels can be embedded into application frames or applets.
- *
- * @author Matt Windsor
+ * @author Matt Windsor
*
*/
-public abstract class FrontendPanel extends JPanel
+public class FrontendPanel extends JPanel
{
/**
*
*/
-
- private static final long serialVersionUID = 5616222530691425635L;
+ private static final long serialVersionUID = -4481079599056565279L;
+ protected FrontendMaster master;
+
+ /**
+ * Construct a new, blank FrontendPanel.
+ *
+ * @param master The FrontendMaster driving the frontend.
+ */
+
public
- FrontendPanel ()
+ FrontendPanel (FrontendMaster master)
{
super ();
+
+ this.master = master;
+ }
+
+
+ /**
+ * Construct a new FrontendPanel from an XML layout.
+ *
+ * This is the preferred means of constructing FrontendPanels, and
+ * uses SWIXml to construct the panel layout.
+ *
+ * @param xmlPath The path, relative from this source file, to the
+ * XML file from which this panel will read its
+ * layout.
+ *
+ * @param master The FrontendMaster driving the frontend.
+ */
+
+ public
+ FrontendPanel (String xmlPath, FrontendMaster master)
+ {
+ super ();
+
+ this.master = master;
+
+
+ // Acquire path.
+
+ URL path = getClass ().getResource (xmlPath);
+
+ if (path == null)
+ FrontendError.reportFatal ("UI creation failure: XML layout "
+ + xmlPath + " does not exist.", null);
+
+ SwingEngine se = new SwingEngine (this);
+
+
+ // Custom UI element tag registration.
+
+ se.getTaglib ().registerTag ("hint", HintField.class);
+
+
+ // Read the XML.
+
+ try
+ {
+ se.insert (path, this);
+ }
+ catch (Exception e)
+ {
+ FrontendError.reportFatal ("UI creation failure: " + e.getMessage (), null);
+ }
}
}
diff --git a/src/uk/org/ury/frontend/images/ury.png b/src/uk/org/ury/frontend/images/ury.png
index f71a461..b1f85a1 100644
--- a/src/uk/org/ury/frontend/images/ury.png
+++ b/src/uk/org/ury/frontend/images/ury.png
Binary files differ
diff --git a/src/uk/org/ury/library/LibraryItem.java b/src/uk/org/ury/library/LibraryItem.java
index 881f840..6156bab 100644
--- a/src/uk/org/ury/library/LibraryItem.java
+++ b/src/uk/org/ury/library/LibraryItem.java
@@ -6,6 +6,9 @@ package uk.org.ury.library;
import java.util.Map;
+import uk.org.ury.database.DatabaseItem;
+import uk.org.ury.library.LibraryItemProperty;
+
/**
* An item in the URY library.
@@ -13,81 +16,12 @@ import java.util.Map;
* @author Matt Windsor
*/
-public class LibraryItem
+public class LibraryItem extends DatabaseItem<LibraryItemProperty,
+ String>
{
- /**
- * The parameters that are stored in the LibraryItem.
- *
- * @author Matt Windsor
- */
-
- public enum LibraryProperty
- {
- // Constant SQL identifier
- TITLE ("title"),
- ALBUM ("album"),
- ARTIST ("artist"),
- LABEL ("label"),
- STATUS ("status"),
- MEDIUM ("medium"),
- FORMAT ("format"),
- DATE_RELEASED ("datereleased"),
- DATE_ADDED ("dateadded"),
- DATE_EDITED ("dateedited"),
- SHELF_LETTER ("shelfletter"),
- SHELF_NUMBER ("shelfnumber"),
- CD_ID ("cdid"),
- ADD_MEMBER_ID ("memberid_add"),
- EDIT_MEMBER_ID ("memberid_lastedit"),
- ADD_FORENAME ("fnameadd"),
- ADD_SURNAME ("snameadd"),
- EDIT_FORENAME ("fnameedit"),
- EDIT_SURNAME ("snameedit"),
- IS_DIGITISED ("digitised"),
- IS_CLEAN ("clean");
-
-
- public final String sql;
-
- private
- LibraryProperty (String sql)
- {
- this.sql = sql;
- }
- };
-
-
- private Map<LibraryProperty, String> properties;
-
-
- /**
- * Construct a new library item from an existing list of
- * properties.
- *
- * @param properties The map of properties that the new item will
- * inherit.
- */
-
public
- LibraryItem (Map<LibraryProperty, String> properties)
- {
- this.properties = properties;
- }
-
-
- /**
- * Query this item for a property.
- *
- * @param property The property to query.
- * @return The property, if it exists, or "Unknown" otherwise.
- */
-
- public String
- get (LibraryProperty property)
+ LibraryItem (Map<LibraryItemProperty, String> properties)
{
- if (properties.containsKey (property))
- return properties.get (property);
- else
- return "Unknown";
- }
-}
+ super (properties);
+ }
+} \ No newline at end of file
diff --git a/src/uk/org/ury/library/LibraryItemProperty.java b/src/uk/org/ury/library/LibraryItemProperty.java
new file mode 100644
index 0000000..154e405
--- /dev/null
+++ b/src/uk/org/ury/library/LibraryItemProperty.java
@@ -0,0 +1,43 @@
+package uk.org.ury.library;
+
+/**
+ * The parameters that are stored in the LibraryItem.
+ *
+ * @author Matt Windsor
+ */
+
+public enum LibraryItemProperty
+ {
+ // Constant SQL identifier
+ TITLE ("title"),
+ ALBUM ("album"),
+ ARTIST ("artist"),
+ LABEL ("label"),
+ STATUS ("status"),
+ MEDIUM ("medium"),
+ FORMAT ("format"),
+ DATE_RELEASED ("datereleased"),
+ DATE_ADDED ("dateadded"),
+ DATE_EDITED ("dateedited"),
+ SHELF_LETTER ("shelfletter"),
+ SHELF_NUMBER ("shelfnumber"),
+ CD_ID ("cdid"),
+ ADD_MEMBER_ID ("memberid_add"),
+ EDIT_MEMBER_ID ("memberid_lastedit"),
+ ADD_FORENAME ("fnameadd"),
+ ADD_SURNAME ("snameadd"),
+ EDIT_FORENAME ("fnameedit"),
+ EDIT_SURNAME ("snameedit"),
+ IS_DIGITISED ("digitised"),
+ IS_CLEAN ("clean");
+
+
+ public final String sql;
+
+
+ private
+ LibraryItemProperty (String sql)
+ {
+ this.sql = sql;
+ }
+ }; \ No newline at end of file
diff --git a/src/uk/org/ury/library/LibraryTableModel.java b/src/uk/org/ury/library/LibraryTableModel.java
index c648520..f380274 100644
--- a/src/uk/org/ury/library/LibraryTableModel.java
+++ b/src/uk/org/ury/library/LibraryTableModel.java
@@ -7,7 +7,8 @@ import java.util.List;
import javax.swing.table.AbstractTableModel;
-import uk.org.ury.library.LibraryItem.LibraryProperty;
+import uk.org.ury.database.exceptions.MissingPropertyException;
+import uk.org.ury.library.LibraryItemProperty;
/**
@@ -88,60 +89,67 @@ public class LibraryTableModel extends AbstractTableModel
{
LibraryItem li = data.get (rowIndex);
- switch (columnIndex)
+ try
+ {
+ switch (columnIndex)
+ {
+ case 0: // Title
+ return li.get (LibraryItemProperty.TITLE);
+
+ case 1: // Artist
+ return li.get (LibraryItemProperty.ARTIST);
+
+ case 2: // Album
+ return li.get (LibraryItemProperty.ALBUM);
+
+ case 3: // Medium
+
+ // TODO: Make this less kludge-y
+
+ String mediumString = li.get (LibraryItemProperty.MEDIUM);
+
+ if (mediumString.equals ("c"))
+ return "Compact Disc";
+ else if (mediumString.equals ("7"))
+ return "7\" Vinyl";
+ else if (mediumString.equals ("2"))
+ return "12\" Vinyl";
+ else
+ return "Unrecognised";
+
+ case 4: // Clean?
+
+ // Return true if marked true, false if marked false or unknown etc.
+
+ String cleanString = li.get (LibraryItemProperty.IS_CLEAN);
+
+ // TODO: Nicer way of showing this
+
+ if (cleanString.equals ("y"))
+ return "Yes";
+ else if (cleanString.equals ("n"))
+ return "No";
+ else
+ return "???";
+
+ case 5: // isDigitised
+
+ // Return true if marked true, false if marked false or unknown etc.
+
+ String digitisedString = li.get (LibraryItemProperty.IS_DIGITISED);
+
+ if (digitisedString.equals ("t"))
+ return true;
+ else
+ return false;
+
+ default:
+ return "";
+ }
+ }
+ catch (MissingPropertyException e)
{
- case 0: // Title
- return li.get (LibraryProperty.TITLE);
-
- case 1: // Artist
- return li.get (LibraryProperty.ARTIST);
-
- case 2: // Album
- return li.get (LibraryProperty.ALBUM);
-
- case 3: // Medium
-
- // TODO: Make this less kludge-y
-
- String mediumString = li.get (LibraryProperty.MEDIUM);
-
- if (mediumString.equals ("c"))
- return "Compact Disc";
- else if (mediumString.equals ("7"))
- return "7\" Vinyl";
- else if (mediumString.equals ("2"))
- return "12\" Vinyl";
- else
- return "Unrecognised";
-
- case 4: // Clean?
-
- // Return true if marked true, false if marked false or unknown etc.
-
- String cleanString = li.get (LibraryProperty.IS_CLEAN);
-
- // TODO: Nicer way of showing this
-
- if (cleanString.equals ("y"))
- return "Yes";
- else if (cleanString.equals ("n"))
- return "No";
- else
- return "???";
-
- case 5: // isDigitised
-
- // Return true if marked true, false if marked false or unknown etc.
-
- String digitisedString = li.get (LibraryProperty.IS_DIGITISED);
-
- if (digitisedString.equals ("t"))
- return true;
- else
- return false;
-
- default:
- return "";
+ return "Unknown";
}
}
diff --git a/src/uk/org/ury/library/LibraryUtils.java b/src/uk/org/ury/library/LibraryUtils.java
index 1c69004..a280738 100644
--- a/src/uk/org/ury/library/LibraryUtils.java
+++ b/src/uk/org/ury/library/LibraryUtils.java
@@ -12,7 +12,7 @@ import java.util.List;
import uk.org.ury.database.DatabaseDriver;
import uk.org.ury.database.exceptions.QueryFailureException;
-import uk.org.ury.library.LibraryItem.LibraryProperty;
+import uk.org.ury.library.LibraryItemProperty;
import uk.org.ury.library.exceptions.EmptySearchException;
@@ -99,31 +99,49 @@ public class LibraryUtils
{
while (rs.next ())
{
- // Translate SQL columns into a list of properties.
-
- HashMap<LibraryProperty, String> properties = new HashMap<LibraryProperty, String> ();
-
- for (LibraryProperty p : LibraryProperty.values ())
- {
- try
- {
- properties.put (p, rs.getString (p.sql));
- }
- catch (SQLException e)
- {
- // Ignore this, as it is almost certainly just a non-existent
- // property.
- }
- }
-
- results.add (new LibraryItem (properties));
+ results.add (translateRow (rs));
}
}
catch (SQLException e)
{
throw new QueryFailureException (e.getMessage ());
}
-
+
return results;
}
-} \ No newline at end of file
+
+
+ /**
+ * Translate a row retrieved from the database into a LibraryItem.
+ *
+ * @param rs The result-set, or database cursor, pointing to the
+ * row to translate.
+ *
+ * @return A new LibraryItem containing the properties extracted
+ * from the translated row.
+ */
+
+ private static LibraryItem
+ translateRow (ResultSet rs)
+ {
+ // Translate SQL columns into a list of properties.
+
+ HashMap<LibraryItemProperty, String> properties = new HashMap<LibraryItemProperty, String> ();
+
+ for (LibraryItemProperty p : LibraryItemProperty.values ())
+ {
+ try
+ {
+ properties.put (p, rs.getString (p.sql));
+ }
+ catch (SQLException e)
+ {
+ // Ignore this, as it is almost certainly just a non-existent
+ // property.
+ }
+ }
+
+
+ return new LibraryItem (properties);
+ }
+}
diff --git a/src/uk/org/ury/library/viewer/LibraryViewer.java b/src/uk/org/ury/library/viewer/LibraryViewer.java
index 19f94fb..a98fa54 100644
--- a/src/uk/org/ury/library/viewer/LibraryViewer.java
+++ b/src/uk/org/ury/library/viewer/LibraryViewer.java
@@ -15,6 +15,8 @@ import uk.org.ury.database.exceptions.QueryFailureException;
import uk.org.ury.frontend.AbstractFrontendModule;
import uk.org.ury.frontend.FrontendError;
import uk.org.ury.frontend.FrontendFrame;
+import uk.org.ury.frontend.FrontendMaster;
+import uk.org.ury.frontend.FrontendModulePanel;
import uk.org.ury.library.LibraryItem;
@@ -32,40 +34,28 @@ public class LibraryViewer extends AbstractFrontendModule
private List<LibraryItem> libraryList;
private LibraryViewerPanel panel;
private FrontendFrame frame;
- private static ConfigReader config;
+ private ConfigReader config;
/**
- * Main function, for running this module as a standalone
- * application.
- *
- * @param args The command-line argument array.
- */
-
- public static void
- main (String[] args)
- {
- try {
- config = new ConfigReader("res/conf.xml");
- }
- catch(MissingCredentialsException e) {
- System.out.println(e);
- }
- LibraryViewer lv = new LibraryViewer ();
- lv.runFrontendInFrame ();
- }
-
-
- /**
- * Construct a new LibraryViewer.
+ * Construct a new LibraryViewer as a frontend object.
*/
public
LibraryViewer ()
{
+ try
+ {
+ config = new ConfigReader ("res/conf.xml");
+ }
+ catch (MissingCredentialsException e)
+ {
+ System.out.println(e);
+ }
+
frame = null;
libraryList = new ArrayList<LibraryItem> ();
- panel = new LibraryViewerPanel (this);
+ panel = null;
}
@@ -78,7 +68,7 @@ public class LibraryViewer extends AbstractFrontendModule
{
frame = null;
libraryList = new ArrayList<LibraryItem> ();
- panel = new LibraryViewerPanel (this);
+ panel = null;
try
@@ -91,7 +81,7 @@ public class LibraryViewer extends AbstractFrontendModule
panel.setOpaque (true);
setContentPane (panel);
- runFrontend ();
+ runFrontend (null);
}
});
@@ -117,38 +107,24 @@ public class LibraryViewer extends AbstractFrontendModule
start ()
{
frame = null;
- panel = new LibraryViewerPanel (this);
+ panel = new LibraryViewerPanel (this, null);
add (panel);
}
-
-
- /**
- * Run the library viewer frontend in a FrontendFrame.
- */
-
- public void
- runFrontendInFrame ()
- {
- FrontendFrame frame = new FrontendFrame (panel);
- this.frame = frame;
-
- runFrontend ();
- }
-
+
/**
* Run the library viewer frontend.
*/
- private void
- runFrontend ()
+ public FrontendModulePanel
+ runFrontend (FrontendMaster master)
{
dd = null;
try
{
- dd = new DatabaseDriver(config, UserClass.READ_ONLY);
+ dd = new DatabaseDriver (config, UserClass.READ_ONLY);
}
catch (MissingCredentialsException e)
{
@@ -159,6 +135,9 @@ public class LibraryViewer extends AbstractFrontendModule
{
FrontendError.reportFatal (f.getMessage (), frame);
}
+
+ panel = new LibraryViewerPanel (this, master);
+ return panel;
}
diff --git a/src/uk/org/ury/library/viewer/LibraryViewerPanel.java b/src/uk/org/ury/library/viewer/LibraryViewerPanel.java
index 7057cc0..d6a00d9 100644
--- a/src/uk/org/ury/library/viewer/LibraryViewerPanel.java
+++ b/src/uk/org/ury/library/viewer/LibraryViewerPanel.java
@@ -4,10 +4,10 @@
package uk.org.ury.library.viewer;
-import java.net.URL;
import java.util.concurrent.ExecutionException;
import javax.swing.JButton;
+import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
@@ -15,11 +15,8 @@ import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingWorker;
-import org.swixml.SwingEngine;
-
-import uk.org.ury.frontend.FrontendError;
-import uk.org.ury.frontend.FrontendPanel;
-import uk.org.ury.frontend.HintField;
+import uk.org.ury.frontend.FrontendMaster;
+import uk.org.ury.frontend.FrontendModulePanel;
import uk.org.ury.library.LibraryTableModel;
import uk.org.ury.library.exceptions.EmptySearchException;
@@ -30,25 +27,21 @@ import uk.org.ury.library.exceptions.EmptySearchException;
* @author Matt Windsor, Nathan Lasseter
*/
-public class LibraryViewerPanel extends FrontendPanel
+public class LibraryViewerPanel extends FrontendModulePanel
{
/**
*
*/
private static final long serialVersionUID = -2441616418398056712L;
-
-
- /* Controller of this panel. */
-
- private LibraryViewer master;
/* Panel widgets exposed by the SwiXML user interface. */
private JTable resultsTable;
private JScrollPane resultsPane;
- private JPanel messagePanel;
+ private JPanel messagePanel;
private JLabel messageLabel;
+ private JPanel searchingPanel;
private JTextField searchField;
private JButton searchButton;
@@ -57,49 +50,28 @@ public class LibraryViewerPanel extends FrontendPanel
* letting the user know what happened.
*/
- private String searchFailureMessage = "ALEX!";
+ private String searchFailureMessage = "Unknown error.";
+
/**
* Construct a new LibraryViewerPanel.
*
- * @param inMaster The LibraryViewer controlling this LibraryViewerPanel.
+ * @param viewer The LibraryViewer controlling this LibraryViewerPanel.
+ *
+ * @param master The FrontendMaster driving the frontend.
*/
public
- LibraryViewerPanel (LibraryViewer inMaster)
+ LibraryViewerPanel (LibraryViewer viewer, FrontendMaster master)
{
- super ();
-
- master = inMaster;
-
-
- URL path = getClass ().getResource ("library_viewer_gui.xml");
-
- if (path == null)
- throw new IllegalArgumentException ("XML file does not exist.");
-
- SwingEngine se = new SwingEngine (this);
- se.getTaglib ().registerTag ("hint", HintField.class);
-
-
+ super (viewer, "library_viewer_gui.xml", master);
+
/* The UI implementation is contained in library_viewer_gui.xml.
*
- * It is hooked into the object resultsTable and the action
- * method search.
- *
- * See the XML file for more details.
+ * See this file for more details.
*/
-
- try
- {
- se.insert (path, this);
- }
- catch (Exception e)
- {
- FrontendError.reportFatal ("UI creation failure: " + e.getMessage (), null);
- }
-
+
// Fine-tune table
@@ -110,7 +82,7 @@ public class LibraryViewerPanel extends FrontendPanel
/**
* @return the name of the panel.
*
- * @see uk.org.ury.frontend.FrontendPanel#getName()
+ * @see uk.org.ury.frontend.FrontendModulePanel#getName()
*/
@Override
@@ -143,8 +115,10 @@ public class LibraryViewerPanel extends FrontendPanel
searchField.setEnabled (false);
searchButton.setEnabled (false);
resultsPane.setVisible (false);
- messageLabel.setText ("Searching...");
- messagePanel.setVisible (true);
+ messagePanel.setVisible (false);
+ searchingPanel.setVisible (true);
+
+ final LibraryViewer master = (LibraryViewer) getModule ();
SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void> ()
@@ -207,16 +181,18 @@ public class LibraryViewerPanel extends FrontendPanel
searchField.setEnabled (true);
searchButton.setEnabled (true);
- messagePanel.setVisible (true);
+ searchingPanel.setVisible (false);
if (hasSucceeded == false)
{
messageLabel.setText (searchFailureMessage);
+ messagePanel.setVisible (true);
}
else if (master.getLibraryList ().size () == 0)
{
messageLabel.setText ("Sorry, but no results were "
+ "found for that term.");
+ messagePanel.setVisible (true);
}
else
{
diff --git a/src/uk/org/ury/library/viewer/library_viewer_gui.xml b/src/uk/org/ury/library/viewer/library_viewer_gui.xml
index 60ae0d1..6b7e745 100644
--- a/src/uk/org/ury/library/viewer/library_viewer_gui.xml
+++ b/src/uk/org/ury/library/viewer/library_viewer_gui.xml
@@ -7,13 +7,20 @@
<textfield id="searchField" mnemonic="VK_F" action="search" />
</hbox>
<button id="searchButton" text="Search" mnemonic="VK_S" action="search"
- font="Verdana-BOLD-14" />
+ font="Verdana-BOLD-14" />
</hbox>
<hbox constraints="BorderLayout.CENTER" border="EmptyBorder(0,5,0,5)">
<scrollpane id="resultsPane" constraints="BorderLayout.CENTER">
<table id="resultsTable" />
</scrollpane>
+ <panel id="searchingPanel" constraints="BorderLayout.CENTER" visible="false"
+ layout="BorderLayout">
+ <label id="searchingLabel" text="Searching..." font="Verdana-BOLD-16"
+ constraints="BorderLayout.CENTER" horizontalalignment="CENTER" />
+ <progressbar id="searchingProgressBar" indeterminate="true"
+ constraints="BorderLayout.SOUTH" />
+ </panel>
<panel id="messagePanel" constraints="BorderLayout.CENTER" visible="false"
layout="BorderLayout">
<label id="messageLabel" text="Searching..." font="Verdana-BOLD-16"
diff --git a/src/uk/org/ury/show/ShowChannel.java b/src/uk/org/ury/show/ShowChannel.java
new file mode 100644
index 0000000..6aa3ee8
--- /dev/null
+++ b/src/uk/org/ury/show/ShowChannel.java
@@ -0,0 +1,92 @@
+package uk.org.ury.show;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * A channel of ShowItems in a show.
+ *
+ * @author Matt Windsor
+ */
+
+public class ShowChannel
+{
+ /* Items enqueued in channel. */
+ private List<ShowItem> items;
+
+
+ /**
+ * Construct a new, empty channel.
+ */
+
+ public
+ ShowChannel ()
+ {
+ items = new ArrayList<ShowItem> ();
+ }
+
+
+ /**
+ * Add a new item to the channel.
+ *
+ * @param index The position at which to add the item.
+ *
+ * @param item The new item to add.
+ *
+ * @throws IllegalArgumentException if the item is
+ * null, the index is negative or the index
+ * is out of bounds.
+ */
+
+ public void
+ add (int index, ShowItem item)
+ {
+ if (item == null)
+ throw new IllegalArgumentException ("Item is null.");
+
+ if (index < 0 || index >= items.size ())
+ throw new IllegalArgumentException ("Index " + index +
+ " out of bounds.");
+
+ items.add (index, item);
+ }
+
+
+ /**
+ * Add a new item to the end of the channel.
+ *
+ * @param item The new item to add.
+ */
+
+ public void
+ add (ShowItem item)
+ {
+ if (item == null)
+ throw new IllegalArgumentException ("Item is null.");
+
+ items.add (item);
+ }
+
+
+ /**
+ * Retrieve an item from the channel.
+ *
+ * @param index The index of the item to retrieve from the channel.
+ *
+ * @return the item at the given index in the list.
+ *
+ * @throws IllegalArgumentException if the index is negative
+ * or overflowing.
+ */
+
+ public ShowItem
+ get (int index)
+ {
+ if (index < 0 || index >= items.size ())
+ throw new IllegalArgumentException ("Index " + index +
+ " out of bounds.");
+
+ return items.get (index);
+ }
+}
diff --git a/src/uk/org/ury/show/ShowItem.java b/src/uk/org/ury/show/ShowItem.java
new file mode 100644
index 0000000..be65c80
--- /dev/null
+++ b/src/uk/org/ury/show/ShowItem.java
@@ -0,0 +1,25 @@
+/**
+ *
+ */
+package uk.org.ury.show;
+
+
+import java.util.Map;
+
+import uk.org.ury.database.DatabaseItem;
+
+
+/**
+ * An item in the show database.
+ *
+ * @author Matt Windsor
+ */
+
+public class ShowItem extends DatabaseItem<ShowItemProperty, String>
+{
+ public
+ ShowItem (Map<ShowItemProperty, String> properties)
+ {
+ super (properties);
+ }
+}
diff --git a/src/uk/org/ury/show/ShowItemProperty.java b/src/uk/org/ury/show/ShowItemProperty.java
new file mode 100644
index 0000000..a722a21
--- /dev/null
+++ b/src/uk/org/ury/show/ShowItemProperty.java
@@ -0,0 +1,26 @@
+package uk.org.ury.show;
+
+
+/**
+ * Enumeration of the parameters that are stored in a ShowItem.
+ *
+ * @author Matt Windsor
+ */
+
+public enum ShowItemProperty
+ {
+ // Constant SQL identifier
+ NAME1 ("name1"),
+ NAME2 ("name2"),
+ POSITION ("positionid");
+
+
+ public final String sql;
+
+
+ private
+ ShowItemProperty (String sql)
+ {
+ this.sql = sql;
+ }
+ }; \ No newline at end of file
diff --git a/src/uk/org/ury/show/ShowUtils.java b/src/uk/org/ury/show/ShowUtils.java
new file mode 100644
index 0000000..11a5dad
--- /dev/null
+++ b/src/uk/org/ury/show/ShowUtils.java
@@ -0,0 +1,153 @@
+/**
+ *
+ */
+package uk.org.ury.show;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import uk.org.ury.database.DatabaseDriver;
+import uk.org.ury.database.exceptions.QueryFailureException;
+
+import uk.org.ury.show.ShowItem;
+import uk.org.ury.show.ShowItemProperty;
+
+
+/**
+ * A set of common utility routines to facilitate the extraction of
+ * show items from the show storage areas of the URY database.
+ *
+ * @author Matt Windsor
+ *
+ */
+
+public class ShowUtils
+{
+ /**
+ * The number of channels reserved for show items.
+ *
+ * TODO: move this somewhere more appropriate.
+ */
+
+ public static final int NUM_CHANNELS = 3;
+
+
+ // Maximum number of results to pull from database
+ private static final int MAX_RESULTS = 50;
+
+
+ /**
+ * Given a show and a channel, retrieve a list of all show items
+ * bound to that channel for the show.
+ *
+ * @param db The database to query.
+ *
+ * @param showID The unique number that identifies the show.
+ *
+ * @param channel The index of the channel to query.
+ *
+ * @throws IllegalArgumentException if the database is
+ * null, the show ID is negative or the
+ * channel index falls out of bounds.
+ *
+ * @throws QueryFailureException if the database backend
+ * yielded an error while executing the search
+ * query.
+ *
+ * @return a list of ShowItems extracted from the show and
+ * channel. The list may be empty.
+ */
+
+ public static List<ShowItem>
+ getChannelList (DatabaseDriver db, int showID, int channel)
+ throws QueryFailureException
+ {
+ if (db == null)
+ throw new IllegalArgumentException ("Database handle is null.");
+
+ if (showID < 0)
+ throw new IllegalArgumentException ("Show ID is negative.");
+
+ if (channel < 0 || channel >= NUM_CHANNELS)
+ throw new IllegalArgumentException ("Channel index is out of bounds.");
+
+ List<ShowItem> results = new ArrayList<ShowItem> ();
+
+
+ ResultSet rs = null;
+
+ Object[] params = {showID, channel};
+
+ try
+ {
+ rs = db.executeQuery ("SELECT name1, name2, positionid"
+ + " FROM baps_show"
+ + " INNER JOIN baps_listing"
+ + " ON baps_show.showid"
+ + " = baps_listing.showid"
+ + " INNER JOIN baps_item"
+ + " ON baps_listing.listingid"
+ + " = baps_show.showid"
+ + " WHERE baps_show.showid"
+ + " = ?"
+ + " AND baps_listing.channel"
+ + " = ?", params, MAX_RESULTS);
+ }
+ catch (SQLException e)
+ {
+ throw new QueryFailureException (e.getMessage ());
+ }
+
+ try
+ {
+ while (rs.next ())
+ {
+ results.add (translateRow (rs));
+ }
+ }
+ catch (SQLException e)
+ {
+ throw new QueryFailureException (e.getMessage ());
+ }
+
+ return results;
+ }
+
+
+ /**
+ * Translate a row retrieved from the database into a LibraryItem.
+ *
+ * @param rs The result-set, or database cursor, pointing to the
+ * row to translate.
+ *
+ * @return A new LibraryItem containing the properties extracted
+ * from the translated row.
+ */
+
+ private static ShowItem
+ translateRow (ResultSet rs)
+ {
+ // Translate SQL columns into a list of properties.
+
+ HashMap<ShowItemProperty, String> properties = new HashMap<ShowItemProperty, String> ();
+
+ for (ShowItemProperty p : ShowItemProperty.values ())
+ {
+ try
+ {
+ properties.put (p, rs.getString (p.sql));
+ }
+ catch (SQLException e)
+ {
+ // Ignore this, as it is almost certainly just a non-existent
+ // property.
+ }
+ }
+
+
+ return new ShowItem (properties);
+ }
+} \ No newline at end of file
diff --git a/src/uk/org/ury/show/viewer/ChannelPanel.java b/src/uk/org/ury/show/viewer/ChannelPanel.java
new file mode 100644
index 0000000..187aa86
--- /dev/null
+++ b/src/uk/org/ury/show/viewer/ChannelPanel.java
@@ -0,0 +1,100 @@
+/**
+ *
+ */
+package uk.org.ury.show.viewer;
+
+import java.awt.event.KeyEvent;
+import java.net.URL;
+
+import javax.swing.DefaultListModel;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.ListModel;
+
+import org.swixml.SwingEngine;
+
+import uk.org.ury.frontend.FrontendError;
+import uk.org.ury.show.ShowChannel;
+
+
+/**
+ * A panel displaying channel informstion.
+ *
+ * @author Matt Windsor.
+ */
+
+public class ChannelPanel extends JPanel
+{
+ private JLabel channelName;
+ private JList itemList;
+ private JButton playButton;
+ private JButton pauseButton;
+ private JButton stopButton;
+
+
+ /**
+ * Construct a new ChannelPanel.
+ *
+ * This constructor reads the channel panel layout from the
+ * XML manifest "channel_panel.xml" in the same directory as
+ * this class file.
+ *
+ * @param number The number of the channel.
+ *
+ * @param channel The channel whose data the ChannelPanel is viewing.
+ */
+
+ public
+ ChannelPanel (int number, ShowChannel channel)
+ {
+ super ();
+
+ // Acquire path.
+
+ URL path = getClass ().getResource ("channel_panel.xml");
+
+ if (path == null)
+ FrontendError.reportFatal ("UI creation failure: XML layout does not exist.", null);
+
+ SwingEngine se = new SwingEngine (this);
+
+
+ // Read the XML.
+
+ try
+ {
+ se.insert (path, this);
+ }
+ catch (Exception e)
+ {
+ FrontendError.reportFatal ("UI creation failure: " + e.getMessage (), null);
+ }
+
+ // Tweak buttons to add function key mnemonics, if function keys are available.
+
+ if (number <= 4)
+ {
+ int base = number * 3;
+
+ playButton.setText ("Play (F" + (base - 2) + ")");
+ playButton.setMnemonic (KeyEvent.VK_F1 + (base - 1));
+ playButton.setDisplayedMnemonicIndex (7);
+
+ pauseButton.setText ("Stop (F" + (base - 1) + ")");
+ pauseButton.setMnemonic (KeyEvent.VK_F2 + (base - 1));
+ pauseButton.setDisplayedMnemonicIndex (7);
+
+ stopButton.setText ("Pause (F" + (base ) + ")");
+ stopButton.setMnemonic (KeyEvent.VK_F3 + (base - 1));
+ stopButton.setDisplayedMnemonicIndex (8);
+ }
+
+ // Test stuff
+ DefaultListModel test = new DefaultListModel ();
+ test.add (0, "Test");
+ itemList.setModel (test);
+ channelName.setText ("Channel " + number);
+ }
+}
diff --git a/src/uk/org/ury/show/viewer/LibraryControlPanel.java b/src/uk/org/ury/show/viewer/LibraryControlPanel.java
new file mode 100644
index 0000000..cf5eec2
--- /dev/null
+++ b/src/uk/org/ury/show/viewer/LibraryControlPanel.java
@@ -0,0 +1,33 @@
+package uk.org.ury.show.viewer;
+
+
+import uk.org.ury.frontend.FrontendControlPanel;
+
+
+/**
+ * Control panel for the demo system.
+ *
+ * @author Matt Windsor
+ *
+ */
+
+public class LibraryControlPanel extends FrontendControlPanel
+{
+
+ public
+ LibraryControlPanel ()
+ {
+ super ("library_control_panel.xml");
+ }
+
+
+ /**
+ * Go back to the previous module.
+ */
+
+ public void
+ back ()
+ {
+ master.restoreModule (parent, prevCPanel);
+ }
+}
diff --git a/src/uk/org/ury/show/viewer/ShowViewer.java b/src/uk/org/ury/show/viewer/ShowViewer.java
new file mode 100644
index 0000000..8b3f2db
--- /dev/null
+++ b/src/uk/org/ury/show/viewer/ShowViewer.java
@@ -0,0 +1,161 @@
+package uk.org.ury.show.viewer;
+
+import java.lang.reflect.InvocationTargetException;
+
+import javax.swing.SwingUtilities;
+
+import uk.org.ury.config.ConfigReader;
+import uk.org.ury.database.DatabaseDriver;
+import uk.org.ury.database.UserClass;
+import uk.org.ury.database.exceptions.MissingCredentialsException;
+import uk.org.ury.frontend.AbstractFrontendModule;
+import uk.org.ury.frontend.FrontendError;
+import uk.org.ury.frontend.FrontendFrame;
+import uk.org.ury.frontend.FrontendMaster;
+import uk.org.ury.frontend.FrontendModule;
+import uk.org.ury.frontend.FrontendModulePanel;
+
+import uk.org.ury.show.ShowChannel;
+import uk.org.ury.show.ShowUtils;
+
+
+/**
+ * Frontend module for viewing show details.
+ *
+ * This serves as the base for the show playout and editor classes,
+ * but can be used stand-alone as an (admittedly rather pointless)
+ * module.
+ *
+ * @author Matt Windsor
+ *
+ */
+
+public class ShowViewer extends AbstractFrontendModule
+{
+ /**
+ *
+ */
+
+ private static final long serialVersionUID = -2782366476480563739L;
+ private DatabaseDriver dd;
+ private ShowChannel[] channels;
+ private ShowViewerPanel panel;
+ private FrontendFrame frame;
+ private ConfigReader config;
+
+
+ /**
+ * Construct a new ShowViewer as a frontend object.
+ */
+
+ public
+ ShowViewer ()
+ {
+ try
+ {
+ config = new ConfigReader ("res/conf.xml");
+ }
+ catch (MissingCredentialsException e)
+ {
+ System.out.println(e);
+ }
+
+ frame = null;
+ channels = new ShowChannel[ShowUtils.NUM_CHANNELS];
+ }
+
+
+ /**
+ * Initialise the library viewer frontend as an applet.
+ */
+
+ public void
+ init ()
+ {
+ frame = null;
+ channels = new ShowChannel[ShowUtils.NUM_CHANNELS];
+ panel = new ShowViewerPanel (this, null);
+
+
+ try
+ {
+ SwingUtilities.invokeAndWait (new Runnable ()
+ {
+ public void
+ run ()
+ {
+ panel.setOpaque (true);
+ setContentPane (panel);
+
+ runFrontend (null);
+ }
+
+ });
+ }
+ catch (InterruptedException e)
+ {
+ // TODO Auto-generated catch block
+ e.printStackTrace ();
+ }
+ catch (InvocationTargetException e)
+ {
+ // TODO Auto-generated catch block
+ e.printStackTrace ();
+ }
+ }
+
+
+ /**
+ * Run the library viewer frontend as an applet.
+ */
+
+ public void
+ start ()
+ {
+ frame = null;
+ panel = new ShowViewerPanel (this, null);
+
+ add (panel);
+ }
+
+
+ /**
+ * Run the library viewer frontend.
+ */
+
+ @Override
+ public FrontendModulePanel
+ runFrontend (FrontendMaster master)
+ {
+ dd = null;
+
+ try
+ {
+ dd = new DatabaseDriver (config, UserClass.READ_ONLY);
+ }
+ catch (MissingCredentialsException e)
+ {
+ // TODO: Privilege de-escalation
+ FrontendError.reportFatal (e.getMessage (), frame);
+ }
+ catch (Exception f)
+ {
+ FrontendError.reportFatal (f.getMessage (), frame);
+ }
+
+ panel = new ShowViewerPanel (this, master);
+ return panel;
+ }
+
+
+ /**
+ * @return the channel array.
+ */
+
+ public ShowChannel[]
+ getChannels ()
+ {
+ // TODO Auto-generated method stub
+ return channels;
+ }
+}
diff --git a/src/uk/org/ury/show/viewer/ShowViewerPanel.java b/src/uk/org/ury/show/viewer/ShowViewerPanel.java
new file mode 100644
index 0000000..d276420
--- /dev/null
+++ b/src/uk/org/ury/show/viewer/ShowViewerPanel.java
@@ -0,0 +1,82 @@
+/**
+ *
+ */
+package uk.org.ury.show.viewer;
+
+import javax.swing.JButton;
+import javax.swing.JPanel;
+
+import uk.org.ury.frontend.FrontendMaster;
+import uk.org.ury.frontend.FrontendModulePanel;
+import uk.org.ury.show.ShowChannel;
+
+
+/**
+ * Frontend panel providing access to an underlying lshow viewer.
+ *
+ * @author Matt Windsor, Nathan Lasseter
+ */
+
+public class ShowViewerPanel extends FrontendModulePanel
+{
+ /**
+ *
+ */
+ private static final long serialVersionUID = -2441616418398056712L;
+
+ private JPanel channelGroupPanel;
+
+ /* Panel widgets exposed by the SwiXML user interface. */
+
+
+ /**
+ * Construct a new ShowViewerPanel.
+ *
+ * @param viewer The ShowViewer controlling this LibraryViewerPanel.
+ *
+ * @param master The FrontendMaster driving the frontend.
+ */
+
+ public
+ ShowViewerPanel (ShowViewer viewer, FrontendMaster master)
+ {
+ super (viewer, "show_viewer_gui.xml", master);
+
+ int channelNumber = 1;
+ ChannelPanel cp;
+
+ for (ShowChannel channel : viewer.getChannels ())
+ {
+ cp = new ChannelPanel (channelNumber, channel);
+
+ channelGroupPanel.add (cp);
+ channelNumber++;
+ }
+ }
+
+
+ /**
+ * @return the name of the panel.
+ *
+ * @see uk.org.ury.frontend.FrontendModulePanel#getName()
+ */
+
+ @Override
+ public String
+ getName ()
+ {
+ return "Show Viewer Demo";
+ }
+
+
+ /**
+ * Initialise the library viewer for the purposes of adding tracks
+ * and/or browsing the library.
+ */
+
+ public void
+ search ()
+ {
+ master.loadModule ("library.viewer.LibraryViewer", "show.viewer.LibraryControlPanel");
+ }
+}
diff --git a/src/uk/org/ury/show/viewer/channel_panel.xml b/src/uk/org/ury/show/viewer/channel_panel.xml
new file mode 100644
index 0000000..f739c7a
--- /dev/null
+++ b/src/uk/org/ury/show/viewer/channel_panel.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<panel border="RaisedBevelBorder" size="100,250">
+ <vbox>
+ <hbox>
+ <label id ="channelName"
+ border="EmptyBorder(5,5,5,5)"
+ text="Channel x" font="Verdana-BOLD-14" />
+ </hbox>
+ <scrollpane id="itemScroller">
+ <list id="itemList" />
+ </scrollpane>
+ <hbox>
+ <button id="playButton" text="Play" />
+ <button id="pauseButton" text="Pause" />
+ <button id="stopButton" text="Stop" />
+ </hbox>
+ <hbox>
+ <label text="Name of track" />
+ </hbox>
+ <hbox>
+ <label text="Duration chart" />
+ </hbox>
+ <hbox>
+ <hbox border="EtchedBorder">
+ <vbox border="EmptyBorder(5,5,5,5)">
+ <label text="Elapsed" />
+ </vbox>
+ </hbox>
+ <hbox border="EtchedBorder">
+ <vbox border="EmptyBorder(5,5,5,5)">
+ <label text="Remaining" />
+ </vbox>
+ </hbox>
+ </hbox>
+ </vbox>
+</panel> \ No newline at end of file
diff --git a/src/uk/org/ury/show/viewer/library_control_panel.xml b/src/uk/org/ury/show/viewer/library_control_panel.xml
new file mode 100644
index 0000000..79e5777
--- /dev/null
+++ b/src/uk/org/ury/show/viewer/library_control_panel.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<panel>
+ <hbox border="EmptyBorder(0,5,5,5)" size="640,32">
+ <button id="backButton" text="Back to Show" mnemonic="VK_B" action="back"
+ font="Verdana-BOLD-14" />
+ <button id="c1Button" text="Add to Channel 1" mnemonic="VK_1" action="addch1"
+ font="Verdana-BOLD-14" />
+ <button id="c2Button" text="Add to Channel 2" mnemonic="VK_2" action="addch2"
+ font="Verdana-BOLD-14" />
+ <button id="c3Button" text="Add to Channel 3" mnemonic="VK_3" action="addch3"
+ font="Verdana-BOLD-14" />
+ </hbox>
+</panel>
diff --git a/src/uk/org/ury/show/viewer/show_viewer_gui.xml b/src/uk/org/ury/show/viewer/show_viewer_gui.xml
new file mode 100644
index 0000000..a4f0f5b
--- /dev/null
+++ b/src/uk/org/ury/show/viewer/show_viewer_gui.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<panel layout="BorderLayout">
+ <hbox constraints="BorderLayout.NORTH" border="EmptyBorder(5,5,5,5)" size="640,32">
+ <button id="loadButton" text="Load Show or Template..." mnemonic="VK_L"
+ action="load"
+ font="Verdana-BOLD-14" />
+ <button id="searchButton" text="Search Record Library" mnemonic="VK_S"
+ action="search"
+ font="Verdana-BOLD-14" />
+ </hbox>
+
+ <splitpane constraints="BorderLayout.CENTER" border="EmptyBorder(0,5,0,5)"
+ orientation="0">
+ <scrollpane id="binScrollPane">
+ <label text="Bins will go here." />
+ </scrollpane>
+ <scrollpane id="channelScrollPane">
+ <panel id="channelGroupPanel" />
+ </scrollpane>
+ </splitpane>
+
+ <hbox constraints="BorderLayout.SOUTH" border="EmptyBorder(5,5,5,5)">
+ <hint text="Hint goes here." />
+ </hbox>
+</panel>
diff --git a/src/uk/org/ury/testrig/DemoControlPanel.java b/src/uk/org/ury/testrig/DemoControlPanel.java
new file mode 100644
index 0000000..7e4b439
--- /dev/null
+++ b/src/uk/org/ury/testrig/DemoControlPanel.java
@@ -0,0 +1,33 @@
+package uk.org.ury.testrig;
+
+
+import uk.org.ury.frontend.FrontendControlPanel;
+
+
+/**
+ * Control panel for the demo system.
+ *
+ * @author Matt Windsor
+ *
+ */
+
+public class DemoControlPanel extends FrontendControlPanel
+{
+
+ public
+ DemoControlPanel ()
+ {
+ super ("demo_control_panel.xml");
+ }
+
+
+ /**
+ * Go back to the previous module.
+ */
+
+ public void
+ back ()
+ {
+ master.restoreModule (parent, prevCPanel);
+ }
+}
diff --git a/src/uk/org/ury/testrig/DemoMenu.java b/src/uk/org/ury/testrig/DemoMenu.java
new file mode 100644
index 0000000..bc4636b
--- /dev/null
+++ b/src/uk/org/ury/testrig/DemoMenu.java
@@ -0,0 +1,112 @@
+package uk.org.ury.testrig;
+
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JButton;
+
+import uk.org.ury.frontend.FrontendFrame;
+import uk.org.ury.frontend.FrontendModulePanel;
+
+
+/**
+ * Application frontend, for testing early-stage frontend code.
+ *
+ * @author Matt Windsor
+ *
+ */
+
+public class DemoMenu
+{
+ private FrontendFrame frame;
+
+ /**
+ * Main method.
+ *
+ * @param args The command-line arguments to the program. These
+ * will be ignored.
+ */
+
+ public static void
+ main (String[] args)
+ {
+ DemoMenu dm = new DemoMenu ();
+ dm.run ();
+ }
+
+
+ /**
+ *
+ */
+
+ public void
+ loadModule (String module)
+ {
+ frame.loadModule (module, "testrig.DemoControlPanel");
+ }
+
+ /**
+ * Run the demo menu, creating a user interface.
+ */
+
+ public void
+ run ()
+ {
+ FrontendModulePanel panel = new FrontendModulePanel (null, frame)
+ {
+ private static final long serialVersionUID = 1L;
+
+ {
+ setLayout (new GridLayout (2, 1));
+
+ JButton lb = new JButton ("Library Viewer Demo");
+ JButton sb = new JButton ("Show Viewer Demo");
+
+ lb.addActionListener (new ActionListener ()
+ {
+
+ @Override
+ public void
+ actionPerformed (ActionEvent arg0)
+ {
+ loadModule ("library.viewer.LibraryViewer");
+ }
+
+ });
+
+
+ sb.addActionListener (new ActionListener ()
+ {
+
+ @Override
+ public void
+ actionPerformed (ActionEvent arg0)
+ {
+ loadModule ("show.viewer.ShowViewer");
+ }
+
+ });
+
+
+ add (lb);
+ add (sb);
+ }
+
+
+ /**
+ * @return the name of the module.
+ */
+
+ @Override
+ public String
+ getName ()
+ {
+ return "Demo Menu";
+ }
+ };
+
+
+ frame = new FrontendFrame (panel);
+ }
+}
diff --git a/src/uk/org/ury/testrig/demo_control_panel.xml b/src/uk/org/ury/testrig/demo_control_panel.xml
new file mode 100644
index 0000000..cade1dd
--- /dev/null
+++ b/src/uk/org/ury/testrig/demo_control_panel.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<panel>
+ <hbox border="EmptyBorder(0,5,5,5)" size="640,32">
+ <button id="backButton" text="Back to Demo Menu" mnemonic="VK_B" action="back"
+ font="Verdana-BOLD-14" />
+ <button id="aboutButton" text="About..." mnemonic="VK_A" action="about"
+ font="Verdana-BOLD-14" />
+ </hbox>
+</panel>