--- jsampler/trunk/src/org/jsampler/view/fantasia/MainFrame.java 2008/09/08 00:19:27 1767 +++ jsampler/trunk/src/org/jsampler/view/fantasia/MainFrame.java 2008/12/24 17:29:47 1818 @@ -23,20 +23,25 @@ package org.jsampler.view.fantasia; import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Composite; import java.awt.Dialog; import java.awt.Dimension; import java.awt.Frame; import java.awt.Graphics; +import java.awt.Graphics2D; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; -import java.awt.Point; +import java.awt.Paint; +import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.io.BufferedReader; import java.io.File; @@ -44,45 +49,43 @@ import java.io.FileReader; import java.util.Vector; -import java.util.logging.Level; import javax.swing.BorderFactory; -import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JCheckBoxMenuItem; -import javax.swing.JComponent; -import javax.swing.JDialog; import javax.swing.JFileChooser; -import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JScrollPane; import javax.swing.JSplitPane; -import javax.swing.JToggleButton; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; import javax.swing.Timer; -import javax.swing.UIManager; -import net.sf.juife.TitleBar; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; import org.jsampler.CC; import org.jsampler.HF; import org.jsampler.LSConsoleModel; import org.jsampler.Server; -import org.jsampler.view.JSChannel; import org.jsampler.view.JSChannelsPane; -import org.jsampler.view.JSMainFrame; import org.jsampler.view.LscpFileFilter; +import org.jsampler.view.SessionViewConfig; + +import org.jsampler.view.fantasia.basic.FantasiaPainter; +import org.jsampler.view.fantasia.basic.FantasiaPanel; +import org.jsampler.view.fantasia.basic.FantasiaSubPanel; +import org.jsampler.view.std.JSBackendLogFrame; import org.jsampler.view.std.JSConnectDlg; import org.jsampler.view.std.JSDetailedErrorDlg; import org.jsampler.view.std.JSQuitDlg; import org.jsampler.view.std.JSamplerHomeChooser; +import org.jsampler.view.std.StdMainFrame; +import org.jsampler.view.std.StdUtils; import static org.jsampler.view.fantasia.A4n.a4n; import static org.jsampler.view.fantasia.FantasiaI18n.i18n; @@ -94,25 +97,29 @@ * * @author Grigor Iliev */ -public class MainFrame extends JSMainFrame { +public class MainFrame extends StdMainFrame { private final StandardBar standardBar = new StandardBar(); private final FantasiaMenuBar menuBar = new FantasiaMenuBar(); - private final JPanel rootPane = new JPanel(); - private final MainPane mainPane = new MainPane(); + private final JPanel rootPane = new RootPane(); + private final BottomPane bottomPane; + private final MainPane mainPane; + private final PianoKeyboardPane pianoKeyboardPane; private final JMenu recentScriptsMenu = new JMenu(i18n.getMenuLabel("actions.recentScripts")); private final JSplitPane hSplitPane; - private final LeftSidePane leftSidePane = new LeftSidePane(); - private final RightSidePane rightSidePane = new RightSidePane(); + private final LeftSidePane leftSidePane; + private final RightSidePane rightSidePane; private final JPanel rightPane; //private final StatusBar statusBar = new StatusBar(); private final LSConsoleFrame lsConsoleFrame = new LSConsoleFrame(); private final Vector recentScripts = new Vector(); + + private final JSBackendLogFrame backendLogFrame = new JSBackendLogFrame(); private final JCheckBoxMenuItem cbmiToolBarVisible = @@ -124,17 +131,26 @@ private final JCheckBoxMenuItem cbmiRightSidePaneVisible = new JCheckBoxMenuItem(i18n.getMenuLabel("view.rightSidePane")); + private final JCheckBoxMenuItem cbmiMidiKeyboardVisible = + new JCheckBoxMenuItem(i18n.getMenuLabel("view.midiKeyboard")); + private final Timer guiTimer = new Timer(1000, null); /** Creates a new instance of MainFrame */ public MainFrame() { setTitle(i18n.getLabel("MainFrame.title")); - + //setUndecorated(true); if(Res.iconAppIcon != null) setIconImage(Res.iconAppIcon.getImage()); + CC.setMainFrame(this); // TODO: + mainPane = new MainPane(); + leftSidePane = new LeftSidePane(); + rightSidePane = new RightSidePane(); + + setSelectedChannelsPane(mainPane.getChannelsPane(0)); + getContentPane().add(standardBar, BorderLayout.NORTH); - //getContentPane().add(statusBar, BorderLayout.SOUTH); rightPane = createRightPane(); @@ -145,16 +161,35 @@ ); hSplitPane.setResizeWeight(0.5); - rootPane.setLayout(new BorderLayout()); - rootPane.setBorder(BorderFactory.createEmptyBorder(6, 0, 0, 0)); - rootPane.setOpaque(false); - rootPane.add(hSplitPane); + pianoKeyboardPane = new PianoKeyboardPane(); - addMenu(); + for(int i = 0; i < mainPane.getChannelsPaneCount(); i++) { + addChannelsPane(mainPane.getChannelsPane(i)); + getChannelsPane(i).addListSelectionListener(pianoKeyboardPane); + } - addChannelsPane(mainPane.getChannelsPane()); - getContentPane().add(rootPane); + int h = preferences().getIntProperty("midiKeyboard.height"); + setMidiKeyboardHeight(h); + + PropertyChangeListener l = new PropertyChangeListener() { + public void + propertyChange(PropertyChangeEvent e) { + int h = preferences().getIntProperty("midiKeyboard.height"); + setMidiKeyboardHeight(h); + } + }; + + CC.preferences().addPropertyChangeListener("midiKeyboard.height", l); + + bottomPane = new BottomPane(); + + hSplitPane.setOpaque(false); + rootPane.add(hSplitPane); + rootPane.add(bottomPane, BorderLayout.SOUTH); + add(rootPane); + + addMenu(); int i = preferences().getIntProperty("MainFrame.hSplitDividerLocation", 220); hSplitPane.setDividerLocation(i); @@ -166,7 +201,9 @@ private JPanel createRightPane() { - JPanel p = new JPanel(); + JPanel p = new FantasiaPanel(); + p.setOpaque(false); + GridBagLayout gridbag = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); @@ -186,7 +223,7 @@ c.gridy = 0; c.weightx = 0.0; c.weighty = 1.0; - c.insets = new Insets(0, 3, 0, 3); + c.insets = new Insets(0, 0, 0, 3); c.fill = GridBagConstraints.VERTICAL; gridbag.setConstraints(mainPane, c); p.add(mainPane); @@ -196,37 +233,13 @@ private void setSavedSize() { - String s = preferences().getStringProperty("MainFrame.sizeAndLocation"); - if(s == null) { + Rectangle r = StdUtils.getWindowBounds("MainFrame"); + if(r == null) { setDefaultSizeAndLocation(); return; } - pack(); - try { - int i = s.indexOf(','); - int x = Integer.parseInt(s.substring(0, i)); - - s = s.substring(i + 1); - i = s.indexOf(','); - int y = Integer.parseInt(s.substring(0, i)); - - s = s.substring(i + 1); - i = s.indexOf(','); - int width = Integer.parseInt(s.substring(0, i)); - - s = s.substring(i + 1); - int height = Integer.parseInt(s); - - setBounds(x, y, width, height); - } catch(Exception x) { - String msg = "Parsing of window size and location string failed"; - CC.getLogger().log(Level.INFO, msg, x); - setDefaultSizeAndLocation(); - } - if(preferences().getBoolProperty("MainFrame.windowMaximized")) { - setExtendedState(getExtendedState() | MAXIMIZED_BOTH); - } + setBounds(r); } private void @@ -238,6 +251,7 @@ /** Invoked when this window is about to close. */ + @Override protected void onWindowClose() { boolean b = preferences().getBoolProperty(CONFIRM_APP_QUIT); @@ -263,12 +277,7 @@ return; } - java.awt.Point p = getLocation(); - Dimension d = getSize(); - StringBuffer sb = new StringBuffer(); - sb.append(p.x).append(',').append(p.y).append(','); - sb.append(d.width).append(',').append(d.height); - preferences().setStringProperty("MainFrame.sizeAndLocation", sb.toString()); + StdUtils.saveWindowBounds("MainFrame", getBounds()); String[] list = recentScripts.toArray(new String[recentScripts.size()]); preferences().setStringListProperty(RECENT_LSCP_SCRIPTS, list); @@ -277,9 +286,24 @@ if(lsConsoleFrame != null) getLSConsolePane().saveConsoleHistory(); } + if(getBackendLogFrame() != null) getBackendLogFrame().stopTimer(); + if(getLSConsolePane() != null) getLSConsolePane().disconnect(); + super.onWindowClose(); } + @Override + public void + setVisible(boolean b) { + if(b == isVisible()) return; + + super.setVisible(b); + + if(b && preferences().getBoolProperty("MainFrame.windowMaximized")) { + setExtendedState(getExtendedState() | MAXIMIZED_BOTH); + } + } + private void addMenu() { JMenu m; @@ -431,6 +455,65 @@ cbmiRightSidePaneVisible.setSelected(b); showDevicesPane(b); + m.addSeparator(); + + m.add(cbmiMidiKeyboardVisible); + + cbmiMidiKeyboardVisible.addActionListener(new ActionListener() { + public void + actionPerformed(ActionEvent e) { + setMidiKeyboardVisible(cbmiMidiKeyboardVisible.getState()); + } + }); + + b = preferences().getBoolProperty("midiKeyboard.visible"); + cbmiMidiKeyboardVisible.setSelected(b); + setMidiKeyboardVisible(b); + + + // Channels + m = new FantasiaMenu(i18n.getMenuLabel("channels")); + + mi = new JMenuItem(i18n.getMenuLabel("channels.newChannel")); + mi.addActionListener(new ActionListener() { + public void + actionPerformed(ActionEvent e) { + CC.getSamplerModel().addBackendChannel(); + } + }); + m.add(mi); + + m.addSeparator(); + + MenuManager.ChannelViewGroup group = new MenuManager.ChannelViewGroup(); + MenuManager.getMenuManager().registerChannelViewGroup(group); + + for(JMenuItem menuItem : group.getMenuItems()) m.add(menuItem); + + m.addSeparator(); + + m.add(new JMenuItem(a4n.moveChannelsOnTop)); + m.add(new JMenuItem(a4n.moveChannelsUp)); + m.add(new JMenuItem(a4n.moveChannelsDown)); + m.add(new JMenuItem(a4n.moveChannelsAtBottom)); + + m.add(new ToPanelMenu()); + + m.addSeparator(); + + mi = new JMenuItem(a4n.selectAllChannels); + mi.setIcon(null); + mi.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, KeyEvent.CTRL_MASK)); + m.add(mi); + + mi = new JMenuItem(a4n.deselectChannels); + mi.setIcon(null); + mi.setAccelerator(KeyStroke.getKeyStroke ( + KeyEvent.VK_A, KeyEvent.CTRL_MASK | KeyEvent.SHIFT_MASK + )); + m.add(mi); + + menuBar.add(m); // Window m = new FantasiaMenu(i18n.getMenuLabel("window")); @@ -444,6 +527,30 @@ mi.setIcon(null); m.add(mi); + m.addSeparator(); + + final JMenuItem mi2 = new JMenuItem(i18n.getMenuLabel("window.backendLog")); + m.add(mi2); + mi2.addActionListener(new ActionListener() { + public void + actionPerformed(ActionEvent e) { + if(getBackendLogFrame().isVisible()) { + getBackendLogFrame().setVisible(false); + } + + getBackendLogFrame().setVisible(true); + } + }); + + mi2.setEnabled(CC.getBackendProcess() != null); + + CC.addBackendProcessListener(new ActionListener() { + public void + actionPerformed(ActionEvent e) { + mi2.setEnabled(CC.getBackendProcess() != null); + } + }); + // Help m = new FantasiaMenu(i18n.getMenuLabel("help")); @@ -461,33 +568,57 @@ menuBar.add(m); } + public static class ToPanelMenu extends FantasiaMenu implements ListSelectionListener { + public + ToPanelMenu() { + super(i18n.getMenuLabel("channels.toPanel")); + setEnabled(CC.getMainFrame().getSelectedChannelsPane().hasSelectedChannel()); + + CC.getMainFrame().addChannelsPaneSelectionListener(this); + + for(int i = 0; i < CC.getMainFrame().getChannelsPaneCount(); i++) { + JSChannelsPane p = CC.getMainFrame().getChannelsPane(i); + add(new JMenuItem(new A4n.MoveChannelsToPanel(p))); + p.addListSelectionListener(this); + } + } + + @Override + public void + valueChanged(ListSelectionEvent e) { + setEnabled(CC.getMainFrame().getSelectedChannelsPane().hasSelectedChannel()); + } + } + public RightSidePane getRightSidePane() { return rightSidePane; } + @Override + public A4n + getA4n() { return A4n.a4n; } + /** - * This method does nothing, because Fantasia has exactly - * one pane containing sampler channels, which can not be changed. + * This method does nothing, because Fantasia has constant + * number of panes containing sampler channels, which can not be changed. */ + @Override public void insertChannelsPane(JSChannelsPane pane, int idx) { } - /** - * This method always returns the JSChannelsPane at index 0, - * because the Fantasia view has exactly one pane containing sampler channels. - * @return The JSChannelsPane at index 0. - */ + @Override public JSChannelsPane - getSelectedChannelsPane() { return getChannelsPane(0); } + getSelectedChannelsPane() { return mainPane.getSelectedChannelsPane(); } - /** - * This method does nothing because the Fantasia view has - * exactly one pane containing sampler channels which is always shown. - */ + @Override public void - setSelectedChannelsPane(JSChannelsPane pane) { } + setSelectedChannelsPane(JSChannelsPane pane) { + mainPane.setSelectedChannelsPane(pane); + fireChannelsPaneSelectionChanged(); + } + @Override public void installJSamplerHome() { JSamplerHomeChooser chooser = new JSamplerHomeChooser(this); @@ -497,6 +628,7 @@ CC.changeJSamplerHome(chooser.getJSamplerHome()); } + @Override public void showDetailedErrorMessage(Frame owner, String err, String details) { JSDetailedErrorDlg dlg = new JSDetailedErrorDlg ( @@ -505,6 +637,7 @@ dlg.setVisible(true); } + @Override public void showDetailedErrorMessage(Dialog owner, String err, String details) { JSDetailedErrorDlg dlg = new JSDetailedErrorDlg ( @@ -517,6 +650,7 @@ * Gets the server address to which to connect. If the server should be * manually selected, a dialog asking the user to choose a server is displayed. */ + @Override public Server getServer() { boolean b = preferences().getBoolProperty(MANUAL_SERVER_SELECT_ON_STARTUP); @@ -528,11 +662,13 @@ * manually selected, a dialog asking the user to choose a server is displayed. * @param manualSelect Determines whether the server should be manually selected. */ + @Override public Server getServer(boolean manualSelect) { if(manualSelect) { JSConnectDlg dlg = new JSConnectDlg(); dlg.setVisible(true); + return dlg.getSelectedServer(); } @@ -558,6 +694,9 @@ protected LSConsoleFrame getLSConsoleFrame() { return lsConsoleFrame; } + public JSBackendLogFrame + getBackendLogFrame() { return backendLogFrame; } + protected boolean runScript() { String s = preferences().getStringProperty("lastScriptLocation"); @@ -574,7 +713,8 @@ return true; } - private void + @Override + public void runScript(String script) { runScript(new File(script)); } private void @@ -586,6 +726,8 @@ return; } + String prefix = "#jsampler.fantasia: "; + Vector v = new Vector(); BufferedReader br = new BufferedReader(fr); try { @@ -593,6 +735,7 @@ while(s != null) { getLSConsoleModel().setCommandLineText(s); getLSConsoleModel().execCommand(); + if(s.startsWith(prefix)) v.add(s.substring(prefix.length())); s = br.readLine(); } } catch(Exception e) { @@ -605,6 +748,10 @@ recentScripts.insertElementAt(s, 0); updateRecentScriptsMenu(); + + CC.getViewConfig().setSessionViewConfig( + new SessionViewConfig(v.toArray(new String[v.size()])) + ); } protected void @@ -706,6 +853,37 @@ }); } + public void + setMidiKeyboardVisible(boolean b) { + preferences().setBoolProperty("midiKeyboard.visible", b); + pianoKeyboardPane.setVisible(b); + + if(cbmiMidiKeyboardVisible.isSelected() != b) { + cbmiMidiKeyboardVisible.setSelected(b); + } + + if(standardBar.btnMidiKeyboard.isSelected() != b) { + standardBar.btnMidiKeyboard.setSelected(b); + } + + if(pianoKeyboardPane.btnPower.isSelected() != b) { + pianoKeyboardPane.btnPower.setSelected(b); + } + + rootPane.validate(); + rootPane.repaint(); + } + + public void + setMidiKeyboardHeight(int height) { + Dimension d = pianoKeyboardPane.getPreferredSize(); + d = new Dimension(d.width, height); + pianoKeyboardPane.setPreferredSize(d); + pianoKeyboardPane.setMinimumSize(d); + pianoKeyboardPane.revalidate(); + pianoKeyboardPane.repaint(); + } + private void sidePanesVisibilityChanged() { boolean leftSidePaneVisible = cbmiLeftSidePaneVisible.isSelected(); @@ -731,6 +909,7 @@ RecentScriptHandler(String script) { this.script = script; } + @Override public void actionPerformed(ActionEvent e) { runScript(script); @@ -745,25 +924,82 @@ super(s); setFont(getFont().deriveFont(java.awt.Font.BOLD)); setOpaque(false); + setContentAreaFilled(false); } } private class FantasiaMenuBar extends JMenuBar { - private Insets pixmapInsets = new Insets(6, 6, 0, 6); - private Insets pixmapInsets2 = new Insets(6, 6, 6, 6); - FantasiaMenuBar() { setOpaque(false); + setBorder(BorderFactory.createEmptyBorder(2, 6, 0, 0)); } + @Override protected void paintComponent(Graphics g) { - super.paintComponent(g); + //super.paintComponent(g); + Graphics2D g2 = (Graphics2D)g; + + Paint oldPaint = g2.getPaint(); + Composite oldComposite = g2.getComposite(); + + double h = getSize().getHeight(); + double w = getSize().getWidth(); + + FantasiaPainter.paintGradient(g2, 0.0, 0.0, w - 1, h - 1, FantasiaPainter.color6, FantasiaPainter.color5); + + FantasiaPainter.Border b; + + if(standardBar.isVisible()) { - PixmapPane.paintComponent(this, g, Res.gfxMenuBarBg, pixmapInsets); + b = new FantasiaPainter.Border(true, true, false, true); + FantasiaPainter.paintBoldOuterBorder(g2, 0, 0, w - 1, h + 1, b); } else { - PixmapPane.paintComponent(this, g, Res.gfxRoundBg14, pixmapInsets2); + b = new FantasiaPainter.Border(true, true, true, true); + FantasiaPainter.paintBoldOuterBorder(g2, 0, 0, w - 1, h - 1, b); } + + g2.setPaint(oldPaint); + g2.setComposite(oldComposite); + } + } + + class RootPane extends FantasiaSubPanel { + private final Color color1 = new Color(0x454545); + private final Color color2 = new Color(0x2e2e2e); + + RootPane() { + setLayout(new BorderLayout()); + setBorder(BorderFactory.createEmptyBorder(9, 10, 6, 10)); + setOpaque(false); + + } + + @Override + public void + paintComponent(Graphics g) { + Graphics2D g2 = (Graphics2D)g; + + Paint oldPaint = g2.getPaint(); + Composite oldComposite = g2.getComposite(); + + double h = getSize().getHeight(); + double w = getSize().getWidth(); + + FantasiaPainter.paintBorder(g2, 0, -3, w - 1, h - 1, 6, false); + paintComponent(g2, 5, 1, w - 10, h - 6, color1, color2); + + g2.setPaint(oldPaint); + g2.setComposite(oldComposite); + } + } + + class BottomPane extends FantasiaPanel { + BottomPane() { + setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + setOpaque(false); + add(pianoKeyboardPane); + } } }