aboutsummaryrefslogtreecommitdiff
path: root/src/uk/org/ury/frontend
diff options
context:
space:
mode:
Diffstat (limited to 'src/uk/org/ury/frontend')
-rw-r--r--src/uk/org/ury/frontend/FrontendApplet.java2
-rw-r--r--src/uk/org/ury/frontend/FrontendFrame.java584
-rw-r--r--src/uk/org/ury/frontend/FrontendModule.java42
-rw-r--r--src/uk/org/ury/frontend/client/Client.java60
-rw-r--r--src/uk/org/ury/frontend/client/test/ClientTest.java57
-rw-r--r--src/uk/org/ury/frontend/cpanels/menu/DemoControlPanel.java47
-rw-r--r--src/uk/org/ury/frontend/cpanels/menu/demo_control_panel.xml7
-rw-r--r--src/uk/org/ury/frontend/cpanels/show/LibraryControlPanel.java48
-rw-r--r--src/uk/org/ury/frontend/cpanels/show/library_control_panel.xml9
-rw-r--r--src/uk/org/ury/frontend/modules/library/LibraryTableModel.java184
-rw-r--r--src/uk/org/ury/frontend/modules/library/LibraryViewer.java159
-rw-r--r--src/uk/org/ury/frontend/modules/library/LibraryViewer.properties22
-rw-r--r--src/uk/org/ury/frontend/modules/library/LibraryViewerPanel.java219
-rw-r--r--src/uk/org/ury/frontend/modules/library/library_viewer_gui.xml32
-rw-r--r--src/uk/org/ury/frontend/modules/menu/DemoMenu.java64
-rw-r--r--src/uk/org/ury/frontend/modules/menu/DemoMenuPanel.java68
-rw-r--r--src/uk/org/ury/frontend/modules/show/ChannelPanel.java84
-rw-r--r--src/uk/org/ury/frontend/modules/show/ShowViewer.java118
-rw-r--r--src/uk/org/ury/frontend/modules/show/ShowViewerPanel.java133
-rw-r--r--src/uk/org/ury/frontend/modules/show/TrackBin.java56
-rw-r--r--src/uk/org/ury/frontend/modules/show/channel_panel.xml36
-rw-r--r--src/uk/org/ury/frontend/modules/show/show_viewer_gui.xml43
-rw-r--r--src/uk/org/ury/frontend/modules/show/show_viewer_gui_old.xml46
-rw-r--r--src/uk/org/ury/frontend/modules/show/show_viewer_gui_panels.xml43
-rw-r--r--src/uk/org/ury/frontend/modules/show/track_bin.xml10
-rw-r--r--src/uk/org/ury/frontend/testrig/ApplicationLauncher.java27
-rw-r--r--src/uk/org/ury/frontend/testrig/Launcher.java17
27 files changed, 1870 insertions, 347 deletions
diff --git a/src/uk/org/ury/frontend/FrontendApplet.java b/src/uk/org/ury/frontend/FrontendApplet.java
index 8e0e229..375a260 100644
--- a/src/uk/org/ury/frontend/FrontendApplet.java
+++ b/src/uk/org/ury/frontend/FrontendApplet.java
@@ -11,7 +11,7 @@ import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import uk.org.ury.frontend.exceptions.LoadFailureException;
-import uk.org.ury.testrig.Launcher;
+import uk.org.ury.frontend.testrig.Launcher;
/**
* A frame that hosts a FrontendModulePanel, used for serving frontend panels in
diff --git a/src/uk/org/ury/frontend/FrontendFrame.java b/src/uk/org/ury/frontend/FrontendFrame.java
index 1683c9b..24a12cb 100644
--- a/src/uk/org/ury/frontend/FrontendFrame.java
+++ b/src/uk/org/ury/frontend/FrontendFrame.java
@@ -14,330 +14,270 @@ import javax.swing.UnsupportedLookAndFeelException;
import uk.org.ury.frontend.exceptions.LoadFailureException;
/**
- * A frame that hosts a FrontendModulePanel, used for serving frontend
- * panels in a window (application mode).
+ * A frame that hosts a FrontendModulePanel, used for serving frontend panels in
+ * a window (application mode).
*
* @author Matt Windsor
- *
+ *
*/
-public class FrontendFrame extends JFrame implements FrontendMaster
-{
- /**
- *
- */
-
- private static final long serialVersionUID = 740928181256928433L;
-
- private FrontendBanner banner;
- private FrontendModulePanel child;
- private FrontendControlPanel cpanel;
-
-
- /**
- * Construct a new FrontendFrame given an initial frontend 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.
- */
-
- public
- FrontendFrame (String moduleName)
- {
- super ("URY newBAPS");
- try
- {
- loadModule (moduleName);
- }
- catch (LoadFailureException e)
- {
- fatalError (e.getMessage ());
- }
- }
-
-
- /**
- * Set up the user interface of the frame.
- */
-
- public void
- setupUI ()
- {
- try
- {
- // Set System L&F
- UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName ());
- }
- catch (UnsupportedLookAndFeelException e)
- {
- // handle exception
- }
- catch (ClassNotFoundException e)
- {
- // handle exception
- }
- catch (InstantiationException e)
- {
- // handle exception
- }
- catch (IllegalAccessException e)
- {
- // handle exception
- }
-
- setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
-
- Container cp = getContentPane ();
-
- // Banner
- System.out.println (child);
- banner = new FrontendBanner (child.getModuleName ());
-
- // Composition
-
- cp.add (banner, BorderLayout.NORTH);
- cp.add (child, BorderLayout.CENTER);
-
- setPreferredSize (new Dimension (800, 600));
- setMinimumSize (new Dimension (800, 600));
-
- 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.
- *
- * @throws LoadFailureException if the class is
- * not found, or is not an implementor of
- * FrontendModule.
- */
-
- @Override
- public void
- loadModule (String moduleName)
- throws LoadFailureException
- {
- Class<?> moduleClass = null;
-
- try
- {
- moduleClass = Class.forName ("uk.org.ury." + moduleName);
- }
- catch (ClassNotFoundException e)
- {
- throw new LoadFailureException ("Could not load module: "
- + e.getMessage ());
- }
-
-
- if (FrontendModule.class.isAssignableFrom (moduleClass) == false)
- {
- throw new LoadFailureException ("Could not load module: Not a FrontendModule");
- }
- else
- {
- FrontendModulePanel temp = child;
-
- try
- {
- child = ((FrontendModule) moduleClass.newInstance ()).runFrontend (this);
- }
- catch (InstantiationException e)
- {
- throw new LoadFailureException ("Could not load module: "
- + e.getMessage ());
- }
- catch (IllegalAccessException e)
- {
- throw new LoadFailureException ("Could not load module: "
- + e.getMessage ());
- }
-
- if (temp != null)
- remove (temp);
-
- add (child);
- child.setMaster (this);
-
- if (banner != null)
- banner.setTitle (child.getModuleName ());
-
- 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.
- *
- * @throws LoadFailureException if the class is
- * not found, or is not an implementor of
- * FrontendModule.
- */
-
- @Override
- public void
- loadModule (String moduleName, String cPanelName)
- throws LoadFailureException
- {
- 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.
- *
- * @throws LoadFailureException if the class is
- * not found, or is not an implementor of
- * FrontendControlPanel.
- */
-
- private void
- loadControlPanel (String cPanelName, FrontendModulePanel parent,
- FrontendModulePanel child)
- throws LoadFailureException
- {
- Class<?> cPanelClass = null;
-
- try
- {
- cPanelClass = Class.forName ("uk.org.ury." + cPanelName);
- }
- catch (ClassNotFoundException e)
- {
- throw new LoadFailureException ("Could not load control panel: "
- + e.getMessage ());
- }
-
-
- if (FrontendControlPanel.class.isAssignableFrom (cPanelClass))
- {
- FrontendControlPanel temp = cpanel;
-
- try
- {
- cpanel = ((FrontendControlPanel) cPanelClass.newInstance ());
- }
- catch (InstantiationException e)
- {
- throw new LoadFailureException ("Could not load control panel: "
- + e.getMessage ());
- }
- catch (IllegalAccessException e)
- {
- throw new LoadFailureException ("Could not load control panel: "
- + e.getMessage ());
- }
-
- 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.getModuleName ());
-
- if (cpanel != null)
- add (cpanel, BorderLayout.SOUTH);
-
- this.cpanel = cpanel;
-
- pack ();
- repaint ();
- }
-
-
- /**
- * Report a fatal error,
- *
- * @param message The message, eg the exception message, to report
- * to the user.
- */
-
- @Override
- public void
- fatalError (String message)
- {
- FrontendError.reportFatal (message, this);
- }
-
-
- /**
- * @return the resource directory.
- */
-
- @Override
- public String
- getResourceDirectory ()
- {
- return "res/";
- }
+public class FrontendFrame extends JFrame implements FrontendMaster {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 740928181256928433L;
+
+ private FrontendBanner banner;
+ private FrontendModulePanel child;
+ private FrontendControlPanel cpanel;
+
+ /**
+ * Construct a new FrontendFrame given an initial frontend 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.
+ */
+ public FrontendFrame(String moduleName) {
+ super("URY newBAPS");
+ try {
+ loadModule(moduleName);
+ } catch (LoadFailureException e) {
+ fatalError(e.getMessage());
+ }
+ }
+
+ /**
+ * Set up the user interface of the frame.
+ */
+ public void setupUI() {
+ try {
+ // Set System L&F
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+ } catch (UnsupportedLookAndFeelException e) {
+ // handle exception
+ } catch (ClassNotFoundException e) {
+ // handle exception
+ } catch (InstantiationException e) {
+ // handle exception
+ } catch (IllegalAccessException e) {
+ // handle exception
+ }
+
+ setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+ Container cp = getContentPane();
+
+ // Banner
+ System.out.println(child);
+ banner = new FrontendBanner(child.getModuleName());
+
+ // Composition
+ cp.add(banner, BorderLayout.NORTH);
+ cp.add(child, BorderLayout.CENTER);
+
+ setPreferredSize(new Dimension(800, 600));
+ setMinimumSize(new Dimension(800, 600));
+
+ 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.
+ *
+ * @throws LoadFailureException
+ * if the class is not found, or is not an implementor of
+ * FrontendModule.
+ */
+ @Override
+ public void loadModule(String moduleName) throws LoadFailureException {
+ Class<?> moduleClass = null;
+
+ try {
+ moduleClass = Class.forName("uk.org.ury.frontend.modules."
+ + moduleName);
+ } catch (ClassNotFoundException e) {
+ throw new LoadFailureException("Could not load module: "
+ + e.getMessage());
+ }
+
+ if (FrontendModule.class.isAssignableFrom(moduleClass) == false) {
+ throw new LoadFailureException(
+ "Could not load module: Not a FrontendModule");
+ } else {
+ FrontendModulePanel temp = child;
+
+ try {
+ child = ((FrontendModule) moduleClass.newInstance())
+ .runFrontend(this);
+ } catch (InstantiationException e) {
+ throw new LoadFailureException("Could not load module: "
+ + e.getMessage());
+ } catch (IllegalAccessException e) {
+ throw new LoadFailureException("Could not load module: "
+ + e.getMessage());
+ }
+
+ if (temp != null)
+ remove(temp);
+
+ add(child);
+ child.setMaster(this);
+
+ if (banner != null)
+ banner.setTitle(child.getModuleName());
+
+ 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.
+ *
+ * @throws LoadFailureException
+ * if the class is not found, or is not an implementor of
+ * FrontendModule.
+ */
+ @Override
+ public void loadModule(String moduleName, String cPanelName)
+ throws LoadFailureException {
+ 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.
+ *
+ * @throws LoadFailureException
+ * if the class is not found, or is not an implementor of
+ * FrontendControlPanel.
+ */
+ private void loadControlPanel(String cPanelName,
+ FrontendModulePanel parent, FrontendModulePanel child)
+ throws LoadFailureException {
+ Class<?> cPanelClass = null;
+
+ try {
+ cPanelClass = Class.forName("uk.org.ury.frontend.cpanels." + cPanelName);
+ } catch (ClassNotFoundException e) {
+ throw new LoadFailureException("Could not load control panel: "
+ + e.getMessage());
+ }
+
+ if (FrontendControlPanel.class.isAssignableFrom(cPanelClass)) {
+ FrontendControlPanel temp = cpanel;
+
+ try {
+ cpanel = ((FrontendControlPanel) cPanelClass.newInstance());
+ } catch (InstantiationException e) {
+ throw new LoadFailureException("Could not load control panel: "
+ + e.getMessage());
+ } catch (IllegalAccessException e) {
+ throw new LoadFailureException("Could not load control panel: "
+ + e.getMessage());
+ }
+
+ 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.getModuleName());
+
+ if (cpanel != null)
+ add(cpanel, BorderLayout.SOUTH);
+
+ this.cpanel = cpanel;
+
+ pack();
+ repaint();
+ }
+
+ /**
+ * Report a fatal error,
+ *
+ * @param message
+ * The message, eg the exception message, to report to the user.
+ */
+ @Override
+ public void fatalError(String message) {
+ FrontendError.reportFatal(message, this);
+ }
+
+ /**
+ * @return the resource directory.
+ */
+ @Override
+ public String getResourceDirectory() {
+ return "res/";
+ }
}
diff --git a/src/uk/org/ury/frontend/FrontendModule.java b/src/uk/org/ury/frontend/FrontendModule.java
index 4d1e3bf..8298ac5 100644
--- a/src/uk/org/ury/frontend/FrontendModule.java
+++ b/src/uk/org/ury/frontend/FrontendModule.java
@@ -4,38 +4,32 @@
package uk.org.ury.frontend;
/**
- * Interface for all system modules that are to be reachable from
- * the frontend array.
+ * Interface for all system modules that are to be reachable from the frontend
+ * array.
*
* Frontend-exposed modules must:
*
* - be runnable standalone, as either an application or an applet;
*
- * - contain their user interface in a subclass of FrontendModulePanel
- * which can be embedded either in a FrontendFrame, a web page
- * or another module;
- *
+ * - contain their user interface in a subclass of FrontendModulePanel which can
+ * be embedded either in a FrontendFrame, a web page or another module;
+ *
* - use the frontend error reporting systems.
*
- * An abstract implementation of this interface,
- * AbstractFrontendModule, is provided to simplify the creation of
- * frontend modules.
+ * An abstract implementation of this interface, AbstractFrontendModule, is
+ * provided to simplify the creation of frontend modules.
*
* @author Matt Windsor
- *
+ *
*/
-
-public interface FrontendModule
-{
- /**
- * 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);
+public interface FrontendModule {
+ /**
+ * 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/client/Client.java b/src/uk/org/ury/frontend/client/Client.java
new file mode 100644
index 0000000..9606d89
--- /dev/null
+++ b/src/uk/org/ury/frontend/client/Client.java
@@ -0,0 +1,60 @@
+package uk.org.ury.frontend.client;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+
+import java.util.Map;
+
+import uk.org.ury.common.protocol.ProtocolUtils;
+import uk.org.ury.common.protocol.exceptions.DecodeFailureException;
+
+public class Client {
+ /**
+ * Get a raw response from the server.
+ *
+ * @param file
+ * The "file", including path and query string, to fetch from the
+ * server.
+ *
+ * @return The response from the server, as a key-value map.
+ *
+ * @throws DecodeFailureException
+ * if the decode failed.
+ */
+ public Map<?, ?> get(String file) throws DecodeFailureException {
+ URL url = null;
+ URLConnection uc = null;
+ String result = "";
+
+ try {
+ url = new URL("http://localhost:8000" + file);
+ } catch (MalformedURLException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ try {
+ uc = url.openConnection();
+
+ BufferedReader in = new BufferedReader(new InputStreamReader(
+ uc.getInputStream()));
+
+ String inputLine;
+
+ for (inputLine = in.readLine(); inputLine != null; inputLine = in
+ .readLine()) {
+ result += inputLine;
+ }
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ return ProtocolUtils.decode(result);
+ }
+}
diff --git a/src/uk/org/ury/frontend/client/test/ClientTest.java b/src/uk/org/ury/frontend/client/test/ClientTest.java
new file mode 100644
index 0000000..d75a0ac
--- /dev/null
+++ b/src/uk/org/ury/frontend/client/test/ClientTest.java
@@ -0,0 +1,57 @@
+/**
+ *
+ */
+package uk.org.ury.frontend.client.test;
+
+import java.util.Map;
+
+import junit.framework.Assert;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import uk.org.ury.common.protocol.Directive;
+import uk.org.ury.common.protocol.exceptions.DecodeFailureException;
+import uk.org.ury.frontend.client.Client;
+
+/**
+ * JUnit test for the low-level client logic.
+ *
+ * @author Matt Windsor
+ */
+public class ClientTest {
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @Before
+ public void setUp() throws Exception {
+ }
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ /**
+ * Test method for {@link uk.org.ury.frontend.client.Client#get(java.lang.String)}.
+ */
+ @Test
+ public void testGet() {
+ Client client = new Client();
+
+ Map<?, ?> response = null;
+
+ try {
+ response = client.get("/server/ServerRequestHandler?function=test");
+ } catch (DecodeFailureException e) {
+ e.printStackTrace();
+ }
+
+ Assert.assertEquals("Test succeeded.",
+ response.get(Directive.INFO.toString()));
+ }
+}
diff --git a/src/uk/org/ury/frontend/cpanels/menu/DemoControlPanel.java b/src/uk/org/ury/frontend/cpanels/menu/DemoControlPanel.java
new file mode 100644
index 0000000..7ef0907
--- /dev/null
+++ b/src/uk/org/ury/frontend/cpanels/menu/DemoControlPanel.java
@@ -0,0 +1,47 @@
+package uk.org.ury.frontend.cpanels.menu;
+
+
+import uk.org.ury.frontend.FrontendControlPanel;
+import uk.org.ury.frontend.exceptions.UICreationFailureException;
+
+
+/**
+ * Control panel for the demo system.
+ *
+ * @author Matt Windsor
+ *
+ */
+
+public class DemoControlPanel extends FrontendControlPanel
+{
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 7558888612002013312L;
+
+
+ /**
+ * Constructs a new DemoControlPanel.
+ *
+ * @throws UICreationFailureException if the UI creation fails.
+ */
+
+ public
+ DemoControlPanel ()
+ throws UICreationFailureException
+ {
+ 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/frontend/cpanels/menu/demo_control_panel.xml b/src/uk/org/ury/frontend/cpanels/menu/demo_control_panel.xml
new file mode 100644
index 0000000..a9b5329
--- /dev/null
+++ b/src/uk/org/ury/frontend/cpanels/menu/demo_control_panel.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<panel>
+ <hbox border="EmptyBorder(0,5,5,5)">
+ <button id="backButton" text="Back to Demo Menu" mnemonic="VK_B" action="back" />
+ <button id="aboutButton" text="About..." mnemonic="VK_A" action="about" />
+ </hbox>
+</panel>
diff --git a/src/uk/org/ury/frontend/cpanels/show/LibraryControlPanel.java b/src/uk/org/ury/frontend/cpanels/show/LibraryControlPanel.java
new file mode 100644
index 0000000..a3d7512
--- /dev/null
+++ b/src/uk/org/ury/frontend/cpanels/show/LibraryControlPanel.java
@@ -0,0 +1,48 @@
+package uk.org.ury.frontend.cpanels.show;
+
+
+import uk.org.ury.frontend.FrontendControlPanel;
+import uk.org.ury.frontend.exceptions.UICreationFailureException;
+
+
+/**
+ * Control panel for the demo system.
+ *
+ * @author Matt Windsor
+ *
+ */
+
+public class LibraryControlPanel extends FrontendControlPanel
+{
+
+ /**
+ *
+ */
+
+ private static final long serialVersionUID = -4260057656619439704L;
+
+
+ /**
+ * Construct a new LibraryControlPanel.
+ *
+ * @throws UICreationFailureException if the UI creation fails.
+ */
+
+ public
+ LibraryControlPanel ()
+ throws UICreationFailureException
+ {
+ 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/frontend/cpanels/show/library_control_panel.xml b/src/uk/org/ury/frontend/cpanels/show/library_control_panel.xml
new file mode 100644
index 0000000..bdf8af0
--- /dev/null
+++ b/src/uk/org/ury/frontend/cpanels/show/library_control_panel.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<panel>
+ <hbox border="EmptyBorder(0,5,5,5)">
+ <button id="backButton" text="Back to Show" mnemonic="VK_B" action="back" />
+ <button id="c1Button" text="Add to Channel 1" mnemonic="VK_1" action="addch1" />
+ <button id="c2Button" text="Add to Channel 2" mnemonic="VK_2" action="addch2" />
+ <button id="c3Button" text="Add to Channel 3" mnemonic="VK_3" action="addch3" />
+ </hbox>
+</panel>
diff --git a/src/uk/org/ury/frontend/modules/library/LibraryTableModel.java b/src/uk/org/ury/frontend/modules/library/LibraryTableModel.java
new file mode 100644
index 0000000..334eb8b
--- /dev/null
+++ b/src/uk/org/ury/frontend/modules/library/LibraryTableModel.java
@@ -0,0 +1,184 @@
+/**
+ *
+ */
+package uk.org.ury.frontend.modules.library;
+
+import java.util.List;
+
+import javax.swing.table.AbstractTableModel;
+
+import uk.org.ury.backend.database.exceptions.MissingPropertyException;
+import uk.org.ury.common.library.item.LibraryItem;
+import uk.org.ury.common.library.item.LibraryItemProperty;
+
+
+/**
+ * A table model for the library viewer.
+ *
+ * @author Matt Windsor
+ */
+
+public class LibraryTableModel extends AbstractTableModel
+{
+
+ /**
+ *
+ */
+
+ private static final long serialVersionUID = -1744980619128903509L;
+
+ private List<LibraryItem> data;
+
+
+ /**
+ * Construct a new table model.
+ *
+ * @param data The list of data on which the model will be based.
+ */
+
+ public
+ LibraryTableModel (List<LibraryItem> data)
+ {
+ this.data = data;
+ }
+
+
+ /* (non-Javadoc)
+ * @see javax.swing.table.TableModel#getColumnCount()
+ */
+
+ @Override
+ public int
+ getColumnCount ()
+ {
+ return 6;
+ }
+
+
+ /* (non-Javadoc)
+ * @see javax.swing.table.TableModel#getRowCount()
+ */
+
+ @Override
+ public int
+ getRowCount ()
+ {
+ return data.size ();
+ }
+
+
+ /**
+ * @param c The column whose class should be investigated.
+ *
+ * @return the column class of column c.
+ */
+
+ @Override
+ public Class<?>
+ getColumnClass (int c)
+ {
+ return getValueAt (0, c).getClass ();
+ }
+
+
+ /* (non-Javadoc)
+ * @see javax.swing.table.TableModel#getValueAt(int, int)
+ */
+
+ @Override
+ public Object
+ getValueAt (int rowIndex, int columnIndex)
+ {
+ LibraryItem li = data.get (rowIndex);
+
+ try
+ {
+ String[] columnData = {li.get (LibraryItemProperty.TITLE),
+ li.get (LibraryItemProperty.ARTIST),
+ li.get (LibraryItemProperty.ALBUM)};
+
+ switch (columnIndex)
+ {
+ default: // Title, artist, album, unknown
+
+ if (columnIndex >= columnData.length)
+ return "Unknown";
+ else
+ return columnData[columnIndex];
+
+ 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;
+ }
+ }
+ catch (MissingPropertyException e)
+ {
+ return "Unknown";
+ }
+ }
+
+
+ /* (non-Javadoc)
+ * @see javax.swing.table.TableModel#getColumnName(int, int)
+ */
+
+ @Override
+ public String
+ getColumnName (int index)
+ {
+ switch (index)
+ {
+ case 0:
+ return "Title";
+ case 1:
+ return "Artist";
+ case 2:
+ return "Album";
+ case 3:
+ return "Medium";
+ case 4:
+ return "Clean?";
+ case 5:
+ return "On system?";
+ default:
+ return "ERROR";
+ }
+ }
+}
diff --git a/src/uk/org/ury/frontend/modules/library/LibraryViewer.java b/src/uk/org/ury/frontend/modules/library/LibraryViewer.java
new file mode 100644
index 0000000..c4a3630
--- /dev/null
+++ b/src/uk/org/ury/frontend/modules/library/LibraryViewer.java
@@ -0,0 +1,159 @@
+/*
+ * LibraryViewer.java
+ * ------------------
+ *
+ * Part of the URY Frontend Platform
+ *
+ * V0.00 2011/03/20
+ *
+ * (C) 2011 URY Computing
+ */
+
+package uk.org.ury.frontend.modules.library;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import uk.org.ury.common.library.exceptions.EmptySearchException;
+import uk.org.ury.common.library.item.LibraryItem;
+import uk.org.ury.common.library.item.LibraryItemProperty;
+import uk.org.ury.common.protocol.Directive;
+import uk.org.ury.common.protocol.ProtocolUtils;
+import uk.org.ury.common.protocol.exceptions.DecodeFailureException;
+import uk.org.ury.common.protocol.exceptions.InvalidMessageException;
+import uk.org.ury.frontend.AbstractFrontendModule;
+import uk.org.ury.frontend.FrontendMaster;
+import uk.org.ury.frontend.FrontendModulePanel;
+import uk.org.ury.frontend.client.Client;
+import uk.org.ury.frontend.exceptions.UICreationFailureException;
+
+/**
+ * Module for investigating the track library.
+ *
+ * The <code>LibraryViewer</code> and its corresponding user
+ * interface, <code>LibraryViewerPanel</code>, provide a
+ * user interface for querying the server's library services
+ * for track information.
+ *
+ * Subclasses of this module provide editing features for
+ * the track library.
+ *
+ * @author Matt Windsor
+ */
+public class LibraryViewer extends AbstractFrontendModule {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -2782366476480563739L;
+ private List<LibraryItem> libraryList;
+ private LibraryViewerPanel panel;
+
+ /**
+ * Constructs a new LibraryViewer as a frontend object.
+ */
+ public LibraryViewer() {
+ libraryList = new ArrayList<LibraryItem>();
+ panel = null;
+ }
+
+ /**
+ * Runs the library viewer frontend.
+ */
+ @Override
+ public FrontendModulePanel runFrontend(FrontendMaster master) {
+ try {
+ panel = new LibraryViewerPanel(this, master);
+ } catch (UICreationFailureException e) {
+ master.fatalError(e.getMessage());
+ }
+
+ return panel;
+ }
+
+ /**
+ * Does a library search.
+ *
+ * This will update the library list to reflect the results of the search.
+ *
+ * @param search
+ * The string fragment to use in searches. Cannot be empty or
+ * null.
+ *
+ * @throws EmptySearchException
+ * if the search string is empty or null (from
+ * LibraryUtils.search).
+ *
+ * @throws InvalidMessageException
+ * if the response from the server is invalid.
+ */
+ public void doSearch(String search) throws EmptySearchException,
+ InvalidMessageException {
+ // TODO: fan out?
+
+ if (search == null || search == "")
+ throw new EmptySearchException();
+
+ Client cl = new Client();
+ Map<?, ?> response = null;
+ libraryList.clear();
+
+ try {
+ response = cl
+ .get("/library/tracks?search="
+ + search);
+ } catch (DecodeFailureException e) {
+ throw new InvalidMessageException(e.getMessage());
+ }
+
+ /*
+ * Check to see if this is Map<String, ?> by looking for the status,
+ * which should always be in a valid response.
+ */
+
+ if (ProtocolUtils.responseIsOK(response) == false)
+ throw new InvalidMessageException(
+ (String) response.get(Directive.REASON.toString()));
+
+ // Should contain a list of items, even if there are no items.
+ if (response.containsKey(Directive.ITEMS.toString()) == false)
+ throw new InvalidMessageException("No item set returned.");
+
+ if ((response.get(Directive.ITEMS.toString()) instanceof List<?>) == false)
+ throw new InvalidMessageException("Malformed item list.");
+
+ for (Object obj : (List<?>) response.get(Directive.ITEMS.toString())) {
+ Map<LibraryItemProperty, String> properties = new HashMap<LibraryItemProperty, String>();
+
+ if (obj instanceof Map<?, ?> == false)
+ throw new InvalidMessageException("Malformed item.");
+
+ Set<?> keySet = ((Map<?, ?>) obj).keySet();
+
+ // Check to make sure this item has only String-String mappings.
+ for (Object key : keySet) {
+ if ((key instanceof String && ((Map<?, ?>) obj).get(key) instanceof String) == false)
+ throw new InvalidMessageException("Not a valid property.");
+ else if (LibraryItemProperty.valueOf((String) key) == null)
+ throw new InvalidMessageException("Property type " + key
+ + " not recognised.");
+ else
+ properties.put(LibraryItemProperty.valueOf((String) key),
+ (String) ((Map<?, ?>) obj).get(key));
+
+ }
+
+ libraryList.add(new LibraryItem(properties));
+ }
+ }
+
+ /**
+ * @return the current library list.
+ */
+
+ public List<LibraryItem> getLibraryList() {
+ return libraryList;
+ }
+}
diff --git a/src/uk/org/ury/frontend/modules/library/LibraryViewer.properties b/src/uk/org/ury/frontend/modules/library/LibraryViewer.properties
new file mode 100644
index 0000000..bb88988
--- /dev/null
+++ b/src/uk/org/ury/frontend/modules/library/LibraryViewer.properties
@@ -0,0 +1,22 @@
+// Module name
+MODULE_NAME = Library Viewer Demo
+
+// Search errors
+// 1st parameter: search term, 2nd parameter: failure reason etc.
+ERR_UNKNOWN = Unknown error.
+ERR_SEARCH_FAILED = Search for '%1$s' failed: %2$s
+ERR_EMPTY_SEARCH = Please type in a search term.
+ERR_NO_RESULTS = Sorry, but no results were found for '%1$s'.
+
+// Search messages
+// 1st parameter: search term
+MSG_SEARCHING = Searching for '%1$s', please wait...
+
+// Labels
+LBL_SEARCHFOR = Search for:
+
+// Buttons
+BTN_SEARCH = Start Search
+
+// Hint
+HINT = To narrow your search, type part or all of the record title or artist into the box above. \ No newline at end of file
diff --git a/src/uk/org/ury/frontend/modules/library/LibraryViewerPanel.java b/src/uk/org/ury/frontend/modules/library/LibraryViewerPanel.java
new file mode 100644
index 0000000..37c134a
--- /dev/null
+++ b/src/uk/org/ury/frontend/modules/library/LibraryViewerPanel.java
@@ -0,0 +1,219 @@
+/*
+ * LibraryViewerPanel.java
+ * -----------------------
+ *
+ * Part of the URY Frontend Platform
+ *
+ * V0.00 2011/03/20
+ *
+ * (C) 2011 URY Computing
+ */
+
+package uk.org.ury.frontend.modules.library;
+
+import java.util.ResourceBundle;
+import java.util.concurrent.ExecutionException;
+
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.JTextField;
+import javax.swing.SwingWorker;
+
+import uk.org.ury.common.library.exceptions.EmptySearchException;
+import uk.org.ury.common.protocol.exceptions.InvalidMessageException;
+import uk.org.ury.frontend.FrontendMaster;
+import uk.org.ury.frontend.FrontendModulePanel;
+import uk.org.ury.frontend.HintField;
+import uk.org.ury.frontend.exceptions.UICreationFailureException;
+
+/**
+ * Frontend panel providing access to an underlying library viewer.
+ *
+ * @author Matt Windsor
+ * @author Nathan Lasseter
+ */
+public class LibraryViewerPanel extends FrontendModulePanel {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -2441616418398056712L;
+
+ /* Panel widgets exposed by the SwiXML user interface. */
+
+ private JTable resultsTable;
+ private JScrollPane resultsPane;
+
+ private JPanel messagePanel;
+ private JLabel messageLabel;
+
+ private JPanel searchingPanel;
+ private JLabel searchingLabel;
+
+ private JTextField searchField;
+ private JButton searchButton;
+ private JLabel searchForLabel;
+
+ private HintField hint;
+
+ /*
+ * This contains the last search failure message, for use in letting the
+ * user know what happened.
+ */
+
+ private String searchFailureMessage;
+
+ // Resource bundle.
+
+ private ResourceBundle rb;
+
+ /**
+ * Construct a new LibraryViewerPanel.
+ *
+ * @param viewer
+ * The LibraryViewer controlling this LibraryViewerPanel.
+ *
+ * @param master
+ * The FrontendMaster driving the frontend.
+ *
+ * @throws UICreationFailureException
+ * if the UI creation fails.
+ */
+
+ public LibraryViewerPanel(LibraryViewer viewer, FrontendMaster master)
+ throws UICreationFailureException {
+ /*
+ * The UI implementation is contained in library_viewer_gui.xml.
+ *
+ * See this file for more details.
+ */
+ super(viewer, "library_viewer_gui.xml", master);
+
+ // Fill in locale-specific data.
+ rb = ResourceBundle
+ .getBundle("uk.org.ury.frontend.modules.library.LibraryViewer");
+
+ searchFailureMessage = rb.getString("ERR_UNKNOWN");
+
+ searchingLabel.setText(rb.getString("MSG_SEARCHING"));
+ searchForLabel.setText(rb.getString("LBL_SEARCHFOR"));
+ searchButton.setText(rb.getString("BTN_SEARCH"));
+ hint.setText(rb.getString("HINT"));
+
+ // Fine-tune table
+ resultsTable.setAutoCreateRowSorter(true);
+ }
+
+ /**
+ * @return the name of the panel.
+ *
+ * @see uk.org.ury.frontend.FrontendModulePanel#getModuleName()
+ */
+ @Override
+ public String getModuleName() {
+ return rb.getString("MODULE_NAME");
+ }
+
+ /**
+ * Action method for performing a search, bound by the UI XML manifest to
+ * the search field and button.
+ */
+ public void search() {
+ /*
+ * We can't let the user search while another search is going on, but
+ * it's not good to let the search "freeze" the UI.
+ *
+ * Hence the search function disables all sensitive parts of the
+ * interface and launches a search as a background process.
+ *
+ * We also swap the results table or no-results panel out for a panel
+ * that says "Searching...", in the interests of user-friendliness.
+ */
+ searchField.setEnabled(false);
+ searchButton.setEnabled(false);
+ resultsPane.setVisible(false);
+ messagePanel.setVisible(false);
+ searchingPanel.setVisible(true);
+ searchingLabel.setText(String.format(rb.getString("MSG_SEARCHING"),
+ searchField.getText()));
+
+ final LibraryViewer master = (LibraryViewer) getModule();
+
+ SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {
+ private String searchTerm = "";
+
+ /**
+ * Perform a task in a separate thread from event-dispatch.
+ *
+ * In this case, perform a search.
+ *
+ * @return whether or not the search was successful.
+ */
+ @Override
+ public Boolean doInBackground() {
+ searchTerm = searchField.getText();
+
+ try {
+ master.doSearch(searchTerm);
+ } catch (InvalidMessageException e) {
+ searchFailureMessage = String.format(
+ rb.getString("ERR_SEARCH_FAILED"), searchTerm,
+ e.getMessage());
+ return false;
+ } catch (EmptySearchException e) {
+ searchFailureMessage = rb.getString("ERR_EMPTY_SEARCH");
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Perform post-search cleanup and finalisation.
+ */
+ @Override
+ public void done() {
+ // Figure out whether or not the search succeeded.
+ boolean hasSucceeded = false;
+
+ try {
+ hasSucceeded = this.get();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ } catch (ExecutionException e) {
+ searchFailureMessage = String.format(
+ rb.getString("ERR_SEARCH_FAILED"), searchTerm,
+ e.getMessage());
+ }
+
+ /*
+ * Re-enable widgets and swap panels according to whether or not
+ * results were found.
+ */
+ searchField.setEnabled(true);
+ searchButton.setEnabled(true);
+ searchingPanel.setVisible(false);
+
+ if (hasSucceeded == false) {
+ messageLabel.setText(searchFailureMessage);
+ messagePanel.setVisible(true);
+ } else if (master.getLibraryList().size() == 0) {
+ messageLabel.setText(String.format(
+ rb.getString("ERR_NO_RESULTS"), searchTerm));
+ messagePanel.setVisible(true);
+ } else {
+ // Force table update with new results.
+ resultsTable.setModel(new LibraryTableModel(master
+ .getLibraryList()));
+
+ messagePanel.setVisible(false);
+ resultsPane.setVisible(true);
+ }
+ }
+ };
+
+ worker.execute();
+ }
+}
diff --git a/src/uk/org/ury/frontend/modules/library/library_viewer_gui.xml b/src/uk/org/ury/frontend/modules/library/library_viewer_gui.xml
new file mode 100644
index 0000000..ce30a1d
--- /dev/null
+++ b/src/uk/org/ury/frontend/modules/library/library_viewer_gui.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<panel layout="BorderLayout">
+ <hbox constraints="BorderLayout.NORTH" border="EmptyBorder(5,5,5,5)">
+ <label id="searchForLabel" labelfor="searchField" displayedmnemonic="VK_F" />
+ <hbox border="EmptyBorder(0,5,0,5)">
+ <textfield id="searchField" mnemonic="VK_F" action="search" />
+ </hbox>
+ <button id="searchButton" mnemonic="VK_S" action="search" />
+ </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"
+ 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="You shouldn't see this."
+ constraints="BorderLayout.CENTER" horizontalalignment="CENTER" />
+ </panel>
+ </hbox>
+
+ <hbox constraints="BorderLayout.SOUTH" border="EmptyBorder(5,5,5,5)">
+ <hint id="hint" />
+ </hbox>
+</panel>
diff --git a/src/uk/org/ury/frontend/modules/menu/DemoMenu.java b/src/uk/org/ury/frontend/modules/menu/DemoMenu.java
new file mode 100644
index 0000000..2210ef8
--- /dev/null
+++ b/src/uk/org/ury/frontend/modules/menu/DemoMenu.java
@@ -0,0 +1,64 @@
+package uk.org.ury.frontend.modules.menu;
+
+import uk.org.ury.frontend.AbstractFrontendModule;
+import uk.org.ury.frontend.FrontendMaster;
+import uk.org.ury.frontend.FrontendModulePanel;
+import uk.org.ury.frontend.exceptions.LoadFailureException;
+
+
+/**
+ * Application frontend, for testing early-stage frontend code.
+ *
+ * @author Matt Windsor
+ *
+ */
+
+public class DemoMenu extends AbstractFrontendModule
+{
+ /**
+ *
+ */
+ private static final long serialVersionUID = -5264235507636809476L;
+ private FrontendMaster master;
+
+
+ /**
+ *
+ */
+
+ public void
+ loadModule (String module)
+ {
+ try
+ {
+ master.loadModule (module, "testrig.DemoControlPanel");
+ }
+ catch (LoadFailureException e)
+ {
+ master.fatalError (e.getMessage ());
+ }
+ }
+
+
+ /**
+ * Run the demo menu, creating a user interface.
+ */
+
+ public void
+ run ()
+ {
+
+ }
+
+
+ /**
+ * Run the demo menu in frontend mode.
+ */
+
+ @Override
+ public FrontendModulePanel
+ runFrontend (FrontendMaster master)
+ {
+ return new DemoMenuPanel (master);
+ }
+}
diff --git a/src/uk/org/ury/frontend/modules/menu/DemoMenuPanel.java b/src/uk/org/ury/frontend/modules/menu/DemoMenuPanel.java
new file mode 100644
index 0000000..3520f2a
--- /dev/null
+++ b/src/uk/org/ury/frontend/modules/menu/DemoMenuPanel.java
@@ -0,0 +1,68 @@
+package uk.org.ury.frontend.modules.menu;
+
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JButton;
+
+import uk.org.ury.frontend.FrontendMaster;
+import uk.org.ury.frontend.FrontendModulePanel;
+import uk.org.ury.frontend.exceptions.LoadFailureException;
+
+public class DemoMenuPanel extends FrontendModulePanel {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 5268978856289909262L;
+
+ /**
+ * Construct a new DemoMenuPanel.
+ *
+ * @param inMaster
+ * The new frontend master of the panel, if any.
+ */
+ public DemoMenuPanel(FrontendMaster inMaster) {
+ super(null, inMaster);
+
+ 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) {
+ try {
+ master.loadModule("library.LibraryViewer",
+ "menu.DemoControlPanel");
+ } catch (LoadFailureException e) {
+ master.fatalError(e.getMessage());
+ }
+ }
+ });
+
+ sb.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent arg0) {
+ try {
+ master.loadModule("show.ShowViewer",
+ "menu.DemoControlPanel");
+ } catch (LoadFailureException e) {
+ master.fatalError(e.getMessage());
+ }
+ }
+ });
+
+ add(lb);
+ add(sb);
+ }
+
+ /**
+ * @return the name of the module.
+ */
+ @Override
+ public String getModuleName() {
+ return "Demo Menu";
+ }
+}
diff --git a/src/uk/org/ury/frontend/modules/show/ChannelPanel.java b/src/uk/org/ury/frontend/modules/show/ChannelPanel.java
new file mode 100644
index 0000000..150f1bc
--- /dev/null
+++ b/src/uk/org/ury/frontend/modules/show/ChannelPanel.java
@@ -0,0 +1,84 @@
+/**
+ *
+ */
+package uk.org.ury.frontend.modules.show;
+
+import java.awt.event.KeyEvent;
+
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JList;
+
+import uk.org.ury.common.show.ShowChannel;
+import uk.org.ury.frontend.FrontendPanel;
+import uk.org.ury.frontend.exceptions.UICreationFailureException;
+
+
+/**
+ * A panel displaying channel information.
+ *
+ * @author Matt Windsor.
+ */
+
+public class ChannelPanel extends FrontendPanel
+{
+ /**
+ *
+ */
+ private static final long serialVersionUID = 897125684384350966L;
+
+
+ /* Components created and exposed by the XML engine. */
+
+ 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.
+ *
+ * @throws UICreationFailureException if the UI creation fails.
+ */
+
+ public
+ ChannelPanel (int number, ShowChannel channel)
+ throws UICreationFailureException
+ {
+ super ("channel_panel.xml", null);
+
+
+ // Tweak buttons to add function key mnemonics, if function keys are available.
+
+ if (number <= 3)
+ {
+ int base = (number - 1) * 4;
+
+ playButton.setText ("Play (F" + (base + 1) + ")");
+ playButton.setMnemonic (KeyEvent.VK_F1 + (base ));
+ playButton.setDisplayedMnemonicIndex (7);
+
+ pauseButton.setText ("Stop (F" + (base + 2) + ")");
+ pauseButton.setMnemonic (KeyEvent.VK_F2 + (base ));
+ pauseButton.setDisplayedMnemonicIndex (7);
+
+ stopButton.setText ("Pause (F" + (base + 3) + ")");
+ stopButton.setMnemonic (KeyEvent.VK_F3 + (base ));
+ stopButton.setDisplayedMnemonicIndex (8);
+ }
+
+ // Test stuff
+ itemList.setModel (channel);
+ channelName.setText ("Channel " + number);
+ }
+}
diff --git a/src/uk/org/ury/frontend/modules/show/ShowViewer.java b/src/uk/org/ury/frontend/modules/show/ShowViewer.java
new file mode 100644
index 0000000..641ee3a
--- /dev/null
+++ b/src/uk/org/ury/frontend/modules/show/ShowViewer.java
@@ -0,0 +1,118 @@
+/*
+ * ShowViewer.java
+ * ---------------
+ *
+ * Part of the URY Frontend Platform
+ *
+ * V0.00 2011/03/20
+ *
+ * (C) 2011 URY Computing
+ */
+
+package uk.org.ury.frontend.modules.show;
+
+import java.util.List;
+
+import uk.org.ury.backend.config.ConfigReader;
+import uk.org.ury.backend.database.DatabaseDriver;
+import uk.org.ury.backend.database.UserClass;
+import uk.org.ury.backend.database.exceptions.MissingCredentialsException;
+import uk.org.ury.backend.database.exceptions.QueryFailureException;
+import uk.org.ury.common.show.ShowChannel;
+import uk.org.ury.common.show.ShowUtils;
+import uk.org.ury.common.show.item.ShowItem;
+import uk.org.ury.frontend.AbstractFrontendModule;
+import uk.org.ury.frontend.FrontendMaster;
+import uk.org.ury.frontend.FrontendModulePanel;
+import uk.org.ury.frontend.exceptions.UICreationFailureException;
+
+/**
+ * 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 ConfigReader config;
+
+ /**
+ * Construct a new ShowViewer as a frontend object.
+ */
+ public ShowViewer() {
+ channels = new ShowChannel[ShowUtils.NUM_CHANNELS];
+ }
+
+ /**
+ * Run the library viewer frontend.
+ */
+ @Override
+ public FrontendModulePanel runFrontend(FrontendMaster master) {
+ dd = null;
+ config = null;
+
+ try {
+ config = new ConfigReader(master.getResourceDirectory()
+ + "conf.xml");
+ } catch (MissingCredentialsException e) {
+ System.out.println(e);
+ }
+
+ try {
+ dd = new DatabaseDriver(config, UserClass.READ_ONLY);
+ } catch (MissingCredentialsException e) {
+ // TODO: Privilege de-escalation
+ master.fatalError(e.getMessage());
+ } catch (Exception f) {
+ master.fatalError(f.getMessage());
+ }
+
+ for (int i = 0; i < channels.length; i++) {
+ channels[i] = new ShowChannel();
+
+ try {
+ for (ShowItem item : ShowUtils.getChannelList(dd, 4696, i)) {
+ channels[i].add(item);
+ }
+ } catch (QueryFailureException e) {
+ master.fatalError(e.getMessage());
+ }
+ }
+
+ try {
+ panel = new ShowViewerPanel(this, master);
+ } catch (UICreationFailureException e) {
+ master.fatalError(e.getMessage());
+ }
+
+ return panel;
+ }
+
+ /**
+ * @return the channel array.
+ */
+ public ShowChannel[] getChannels() {
+ // TODO Auto-generated method stub
+ return channels;
+ }
+
+ /**
+ * @return the list of bin names.
+ *
+ * @throws QueryFailureException
+ * if the underlying database query fails.
+ */
+ public List<String> getBins() throws QueryFailureException {
+ return ShowUtils.getPublicFolders(dd);
+ }
+}
diff --git a/src/uk/org/ury/frontend/modules/show/ShowViewerPanel.java b/src/uk/org/ury/frontend/modules/show/ShowViewerPanel.java
new file mode 100644
index 0000000..c4eb6e2
--- /dev/null
+++ b/src/uk/org/ury/frontend/modules/show/ShowViewerPanel.java
@@ -0,0 +1,133 @@
+/**
+ *
+ */
+package uk.org.ury.frontend.modules.show;
+
+import java.awt.GridLayout;
+import java.util.List;
+
+import javax.swing.JPanel;
+
+import uk.org.ury.backend.database.exceptions.QueryFailureException;
+import uk.org.ury.common.show.ShowChannel;
+import uk.org.ury.frontend.FrontendMaster;
+import uk.org.ury.frontend.FrontendModulePanel;
+import uk.org.ury.frontend.exceptions.LoadFailureException;
+import uk.org.ury.frontend.exceptions.UICreationFailureException;
+
+
+/**
+ * Frontend panel providing access to an underlying show viewer.
+ *
+ * The various show user interfaces (show editor, playout etc.)
+ * are derived from this.
+ *
+ * @author Matt Windsor, Nathan Lasseter
+ */
+
+public class ShowViewerPanel extends FrontendModulePanel
+{
+ /**
+ *
+ */
+ private static final long serialVersionUID = -2441616418398056712L;
+
+
+ /* Panel widgets exposed by the SwiXML user interface. */
+
+ private JPanel channelGroupPanel;
+ private JPanel binGroupPanel;
+
+
+ /**
+ * Construct a new ShowViewerPanel.
+ *
+ * The panel will interface with the given show viewer and is
+ * expected to be placed as a sub-component in the given
+ * FrontendMaster.
+ *
+ * @param viewer The ShowViewer controlling this LibraryViewerPanel.
+ *
+ * @param master The FrontendMaster driving the frontend.
+ *
+ * @throws UICreationFailureException if the UI creation fails.
+ */
+
+ public
+ ShowViewerPanel (ShowViewer viewer, FrontendMaster master)
+ throws UICreationFailureException
+ {
+ 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++;
+ }
+
+ channelGroupPanel.setLayout (new GridLayout (1, channelNumber - 1));
+
+
+ // TEST
+ List<String> binNames = null;
+
+ try
+ {
+ binNames = viewer.getBins ();
+ }
+ catch (QueryFailureException e)
+ {
+ master.fatalError (e.getMessage ());
+ }
+
+ TrackBin tb;
+
+ for (String name : binNames)
+ {
+ tb = new TrackBin (name);
+
+ binGroupPanel.add (tb);
+ }
+
+ binGroupPanel.setLayout (new GridLayout (1, binNames.size ()));
+ }
+
+
+ /**
+ * @return the name of the panel.
+ *
+ * @see uk.org.ury.frontend.FrontendModulePanel#getModuleName()
+ */
+
+ @Override
+ public String
+ getModuleName ()
+ {
+ return "Show Viewer Demo";
+ }
+
+
+ /**
+ * Initialise the library viewer for the purposes of adding tracks
+ * and/or browsing the library.
+ */
+
+ public void
+ search ()
+ {
+ try
+ {
+ master.loadModule ("library.LibraryViewer",
+ "show.LibraryControlPanel");
+ }
+ catch (LoadFailureException e)
+ {
+ master.fatalError (e.getMessage ());
+ }
+ }
+}
diff --git a/src/uk/org/ury/frontend/modules/show/TrackBin.java b/src/uk/org/ury/frontend/modules/show/TrackBin.java
new file mode 100644
index 0000000..96b67f4
--- /dev/null
+++ b/src/uk/org/ury/frontend/modules/show/TrackBin.java
@@ -0,0 +1,56 @@
+/**
+ *
+ */
+package uk.org.ury.frontend.modules.show;
+
+import javax.swing.JLabel;
+
+import uk.org.ury.frontend.FrontendPanel;
+import uk.org.ury.frontend.exceptions.UICreationFailureException;
+
+
+/**
+ * A panel displaying track bin contents.
+ *
+ * @author Matt Windsor.
+ */
+
+public class TrackBin extends FrontendPanel
+{
+ /**
+ *
+ */
+ private static final long serialVersionUID = -5414923374901972511L;
+
+
+ /* Components created and exposed by the XML engine. */
+
+ private JLabel binName;
+
+
+ /**
+ * Construct a new TrackBin.
+ *
+ * This constructor reads the channel panel layout from the
+ * XML manifest "track_bin.xml" in the same directory as
+ * this class file.
+ *
+ * TODO: add track list into constructor
+ *
+ * @param name The name of the bin.
+ *
+ * @throws UICreationFailureException if the UI creation fails.
+ */
+
+ public
+ TrackBin (String name)
+ throws UICreationFailureException
+ {
+ super ("track_bin.xml", null);
+
+ // Tweak name.
+
+ binName.setText (name);
+
+ }
+}
diff --git a/src/uk/org/ury/frontend/modules/show/channel_panel.xml b/src/uk/org/ury/frontend/modules/show/channel_panel.xml
new file mode 100644
index 0000000..bf576ce
--- /dev/null
+++ b/src/uk/org/ury/frontend/modules/show/channel_panel.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<panel border="EmptyBorder(5,5,5,5)" layout="BorderLayout">
+ <subbanner id="channelName" text="Channel x"
+ constraints="BorderLayout.NORTH" />
+ <vbox constraints="BorderLayout.CENTER">
+ <scrollpane id="itemScroller" constraints="BorderLayout.CENTER">
+ <list id="itemList" visiblerowcount="1" />
+ </scrollpane>
+ </vbox>
+ <vbox constraints="BorderLayout.SOUTH">
+ <panel layout="GridLayout(1,3)">
+ <button id="playButton" text="Play" />
+ <button id="pauseButton" text="Pause" />
+ <button id="stopButton" text="Stop" />
+ </panel>
+ <panel layout="GridLayout(3, 1)">
+ <label text="Name of track" />
+ <hbox border="EtchedBorder">
+ <label text="Duration chart" />
+ </hbox>
+ <hbox>
+ <glue />
+ <hbox border="EmptyBorder(5,5,5,5)">
+ <label text="Elapsed: " />
+ <label text="0:00:00" font="Verdana-BOLD-14" />
+ </hbox>
+ <glue />
+ <hbox border="EmptyBorder(5,5,5,5)">
+ <label text="Remaining: " />
+ <label text="0:00:00" font="Verdana-BOLD-14" />
+ </hbox>
+ <glue />
+ </hbox>
+ </panel>
+ </vbox>
+</panel> \ No newline at end of file
diff --git a/src/uk/org/ury/frontend/modules/show/show_viewer_gui.xml b/src/uk/org/ury/frontend/modules/show/show_viewer_gui.xml
new file mode 100644
index 0000000..90b8cb5
--- /dev/null
+++ b/src/uk/org/ury/frontend/modules/show/show_viewer_gui.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<panel layout="BorderLayout">
+ <hbox constraints="BorderLayout.NORTH" border="EmptyBorder(5,5,5,5)">
+ <button id="loadButton" text="Load Show or Template..." mnemonic="VK_L"
+ action="load" />
+ <button id="searchButton" text="Search Record Library" mnemonic="VK_S"
+ action="search" />
+ <glue />
+ <button id="helpButton" text="Help..." mnemonic="VK_H"
+ action="help" />
+ <button id="feedbackButton" text="Feedback..." mnemonic="VK_F"
+ action="feedback" />
+ </hbox>
+
+ <panel layout="BorderLayout" constraints="BorderLayout.CENTER">
+ <panel layout="BorderLayout" constraints="BorderLayout.NORTH">
+ <subbanner text="Useful Tracks"
+ constraints="BorderLayout.NORTH" />
+ <scrollpane id="binScrollPane"
+ constraints="BorderLayout.CENTER">
+ <panel id="binGroupPanel" />
+ </scrollpane>
+ </panel>
+ <panel layout="BorderLayout" constraints="BorderLayout.CENTER">
+ <subbanner text="Sound Channels"
+ constraints="BorderLayout.NORTH" />
+ <scrollpane id="channelScrollPane"
+ constraints="BorderLayout.CENTER">
+ <panel id="channelGroupPanel" />
+ </scrollpane>
+ </panel>
+ <panel layout="BorderLayout" constraints="BorderLayout.SOUTH">
+ <subbanner text="Quick Notes"
+ constraints="BorderLayout.NORTH" />
+ <textarea id="noteArea" border="LoweredBevelBorder"
+ text="Type quick notes here..." rows="3" />
+ </panel>
+ </panel>
+
+ <hbox constraints="BorderLayout.SOUTH" border="EmptyBorder(5,5,5,5)">
+ <hint text="For help, click the Help button." />
+ </hbox>
+</panel>
diff --git a/src/uk/org/ury/frontend/modules/show/show_viewer_gui_old.xml b/src/uk/org/ury/frontend/modules/show/show_viewer_gui_old.xml
new file mode 100644
index 0000000..d11e579
--- /dev/null
+++ b/src/uk/org/ury/frontend/modules/show/show_viewer_gui_old.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<panel layout="BorderLayout">
+ <hbox constraints="BorderLayout.NORTH" border="EmptyBorder(5,5,5,5)">
+ <button id="loadButton" text="Load Show or Template..." mnemonic="VK_L"
+ action="load" />
+ <button id="searchButton" text="Search Record Library" mnemonic="VK_S"
+ action="search" />
+ <glue />
+ <button id="helpButton" text="Help..." mnemonic="VK_H"
+ action="help" />
+ <button id="feedbackButton" text="Feedback..." mnemonic="VK_F"
+ action="feedback" />
+ </hbox>
+
+ <splitpane constraints="BorderLayout.CENTER" border="EmptyBorder(0,5,0,5)"
+ id="mainSplit" orientation="0">
+ <splitpane orientation="0" id="binSplit">
+ <panel layout="BorderLayout">
+ <subbanner text="Useful Tracks"
+ constraints="BorderLayout.NORTH" />
+ <scrollpane id="binScrollPane"
+ constraints="BorderLayout.CENTER">
+ <panel id="binGroupPanel" />
+ </scrollpane>
+ </panel>
+ <panel layout="BorderLayout">
+ <subbanner text="Sound Channels"
+ constraints="BorderLayout.NORTH" />
+ <scrollpane id="channelScrollPane"
+ constraints="BorderLayout.CENTER">
+ <panel id="channelGroupPanel" />
+ </scrollpane>
+ </panel>
+ </splitpane>
+ <panel layout="BorderLayout">
+ <subbanner text="Quick Notes"
+ constraints="BorderLayout.NORTH" />
+ <textarea id="noteArea" border="LoweredBevelBorder"
+ text="Type quick notes here..." rows="3" />
+ </panel>
+ </splitpane>
+
+ <hbox constraints="BorderLayout.SOUTH" border="EmptyBorder(5,5,5,5)">
+ <hint text="For help, click the Help button." />
+ </hbox>
+</panel>
diff --git a/src/uk/org/ury/frontend/modules/show/show_viewer_gui_panels.xml b/src/uk/org/ury/frontend/modules/show/show_viewer_gui_panels.xml
new file mode 100644
index 0000000..eda711b
--- /dev/null
+++ b/src/uk/org/ury/frontend/modules/show/show_viewer_gui_panels.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<panel layout="BorderLayout">
+ <hbox constraints="BorderLayout.NORTH" border="EmptyBorder(5,5,5,5)">
+ <button id="loadButton" text="Load Show or Template..." mnemonic="VK_L"
+ action="load" />
+ <button id="searchButton" text="Search Record Library" mnemonic="VK_S"
+ action="search" />
+ <glue />
+ <button id="helpButton" text="Help..." mnemonic="VK_H"
+ action="help" />
+ <button id="feedbackButton" text="Feedback..." mnemonic="VK_F"
+ action="feedback" />
+ </hbox>
+
+ <panel constraints="BorderLayout.CENTER" layout="BorderLayout>
+ <panel layout="BorderLayout" constraints="BorderLayout.NORTH">
+ <subbanner text="Useful Tracks"
+ constraints="BorderLayout.NORTH" />
+ <scrollpane id="binScrollPane"
+ constraints="BorderLayout.CENTER">
+ <panel id="binGroupPanel" />
+ </scrollpane>
+ </panel>
+ <panel layout="BorderLayout" constraints="BorderLayout.CENTER">
+ <subbanner text="Sound Channels"
+ constraints="BorderLayout.NORTH" />
+ <scrollpane id="channelScrollPane"
+ constraints="BorderLayout.CENTER">
+ <panel id="channelGroupPanel" />
+ </scrollpane>
+ </panel>
+ <panel layout="BorderLayout" constraints="BorderLayout.SOUTH">
+ <subbanner text="Quick Notes"
+ constraints="BorderLayout.NORTH" />
+ <textarea id="noteArea" border="LoweredBevelBorder"
+ text="Type quick notes here..." rows="3" />
+ </panel>
+ </panel>
+
+ <hbox constraints="BorderLayout.SOUTH" border="EmptyBorder(5,5,5,5)">
+ <hint text="For help, click the Help button." />
+ </hbox>
+</panel>
diff --git a/src/uk/org/ury/frontend/modules/show/track_bin.xml b/src/uk/org/ury/frontend/modules/show/track_bin.xml
new file mode 100644
index 0000000..d1ff9da
--- /dev/null
+++ b/src/uk/org/ury/frontend/modules/show/track_bin.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<panel border="EmptyBorder(5,5,5,5)" layout="BorderLayout">
+ <subbanner id="binName" text="Bin"
+ constraints="BorderLayout.NORTH" />
+ <vbox>
+ <scrollpane id="itemScroller">
+ <list id="itemList" visiblerowcount="5" />
+ </scrollpane>
+ </vbox>
+</panel> \ No newline at end of file
diff --git a/src/uk/org/ury/frontend/testrig/ApplicationLauncher.java b/src/uk/org/ury/frontend/testrig/ApplicationLauncher.java
new file mode 100644
index 0000000..4a194ac
--- /dev/null
+++ b/src/uk/org/ury/frontend/testrig/ApplicationLauncher.java
@@ -0,0 +1,27 @@
+/**
+ *
+ */
+package uk.org.ury.frontend.testrig;
+
+import uk.org.ury.frontend.FrontendFrame;
+
+/**
+ * An application-based entry point into the frontend.
+ *
+ * If provided with no arguments, this will launch the main menu.
+ *
+ * @author Matt Windsor
+ */
+public class ApplicationLauncher implements Launcher {
+ /**
+ * Main method.
+ *
+ * @param args
+ * The command-line arguments to the program. These will
+ * currently be ignored.
+ */
+ public static void main(String[] args) {
+ FrontendFrame fr = new FrontendFrame(DEFAULT_MODULE_NAME);
+ fr.setupUI();
+ }
+}
diff --git a/src/uk/org/ury/frontend/testrig/Launcher.java b/src/uk/org/ury/frontend/testrig/Launcher.java
new file mode 100644
index 0000000..8e92831
--- /dev/null
+++ b/src/uk/org/ury/frontend/testrig/Launcher.java
@@ -0,0 +1,17 @@
+/**
+ *
+ */
+package uk.org.ury.frontend.testrig;
+
+
+/**
+ * Interface for entry points into the frontend.
+ *
+ * @author Matt Windsor
+ */
+
+
+public interface Launcher
+{
+ public String DEFAULT_MODULE_NAME = "menu.DemoMenu";
+}