diff options
Diffstat (limited to 'src/uk/org/ury/frontend')
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"; +} |