// Copyright (C) 2006 Steve Taylor. // Distributed under the Toot Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.toot.org/LICENSE_1_0.txt) package com.frinika.tootX.gui; import com.frinika.tootX.midi.MidiLearnIF; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Color; import java.awt.Image; import java.awt.image.BufferedImage; import java.awt.event.*; import javax.swing.*; import uk.org.toot.audio.mixer.*; import java.util.Observable; import java.util.Observer; import uk.org.toot.control.*; import uk.org.toot.audio.mixer.MixerControls; import uk.org.toot.audio.mixer.automation.AutomationControls; import uk.org.toot.control.ControlSelector; import uk.org.toot.control.automation.SnapshotAutomation; import uk.org.toot.swingui.audioui.AudioCompoundControlPanel; import uk.org.toot.swingui.audioui.mixerui.FullMixerPanel; import uk.org.toot.swingui.audioui.mixerui.MixerPanelFactory; import uk.org.toot.swingui.audioui.mixerui.PopupButton; import uk.org.toot.swingui.audioui.mixerui.SnapshotAutomationPopupMenu; import uk.org.toot.swingui.controlui.PanelFactory; import uk.org.toot.swingui.DisposablePanel; import static uk.org.toot.audio.mixer.MixerControlsIds.*; //import static uk.org.toot.localisation.Localisation.*; public class FrinikaMixerPanel extends DisposablePanel { private String currentStripName; /** * @link aggregationByValue * @supplierCardinality 1 */ private JPanel stripPanel; protected MixerControls mixerControls; protected ControlSelector topControlSelector; // private ControlSelector controlSelector; /** * @link aggregationByValue * @supplierCardinality 1*/ protected FullMixerPanel fullMixerPanel; protected PanelFactory topPanelFactory; private Observer mutationObserver = null; public FrinikaMixerPanel(final MixerControls mixerControls,MidiLearnIF midiLearnIF) { this.mixerControls = mixerControls; topPanelFactory = new FrinikaMixerPanelFactory(midiLearnIF) { protected boolean toggleMinimised(String name) { boolean ret = super.toggleMinimised(name); FrinikaMixerPanel.this.build(currentStripName); return ret; } protected boolean addGlue() { return true; } protected boolean canEdit() { return true; } }; setLayout(new BorderLayout()); fullMixerPanel = new FullMixerPanel(mixerControls) { protected void setCurrentStripName(String name) { if ( !name.equals(currentStripName) ) { currentStripName = name; FrinikaMixerPanel.this.build(currentStripName); } } protected void setCurrentBusName(String name) { super.setCurrentBusName(name); // not required with selecter // CompactMixerPanel.this.build(currentStripName); } protected void addTools(JToolBar bar) { // add top panel show button FrinikaMixerPanel.this.addTools(bar); super.addTools(bar); } }; ControlSelector controlSelector = fullMixerPanel.new SingleBusSelector(); fullMixerPanel.setControlSelector(controlSelector); topControlSelector = new ControlSelector() { public boolean select(Control c) { if ( c.getId() == AutomationControls.AUTOMATION_ID ) { return false; } return true; } }; add(fullMixerPanel, BorderLayout.CENTER); setup(); mutationObserver = new Observer() { public void update(Observable obs, Object arg) { if ( arg instanceof MixerControls.Mutation ) { // SwingUtilities.invokeLater() ??? seems to work w/o !!! MixerControls.Mutation m = (MixerControls.Mutation)arg; if ( m.getOperation() == MixerControls.Mutation.REMOVE && m.getControl().getName().equals(currentStripName) ) { // if the current strip is deleted, use Master strip FrinikaMixerPanel.this.build(mixerControls.getMainBusControls().getName()); } } } }; } protected void dispose() { // anonymous inner classes maintain a reference to this // so their references must be nulled to enable their garbage collection // which in turn enables this to be garbage collected topPanelFactory = null; fullMixerPanel = null; if ( stripPanel != null ) { stripPanel.removeAll(); stripPanel = null; } topControlSelector = null; removeAll(); } JToggleButton channelButton; protected void addTools(JToolBar bar) { final String hideString, showString; hideString = "Hide.Upper.Panel"; showString = "Show.Upper.Panel"; channelButton = new JToggleButton(); boolean showUpper=false; channelButton.setIcon(createUpperPanelIcon(!showUpper)); channelButton.setSelectedIcon(createUpperPanelIcon(showUpper)); channelButton.setSelected(showUpper); channelButton.setToolTipText(hideString); ActionListener actionListener = new ActionListener() { public void actionPerformed(ActionEvent e) { stripPanel.setVisible(channelButton.isSelected()); channelButton.setToolTipText( channelButton.isSelected() ? hideString : showString); } }; channelButton.addActionListener(actionListener); // !!! !!! remove? bar.add(channelButton); SnapshotAutomation snapshotAutomation = mixerControls.getSnapshotAutomation(); if ( snapshotAutomation != null ) { JPopupMenu snapshotPopup = new SnapshotAutomationPopupMenu(snapshotAutomation); JButton snapshotButton = new PopupButton(snapshotPopup); snapshotButton.setIcon(createSnapshotIcon(false)); snapshotButton.setToolTipText("Snapshot.Automation"); bar.add(snapshotButton); } } protected Icon createUpperPanelIcon(boolean selected) { int w = 24; int h = 20; Image image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); Graphics g = image.getGraphics(); // draw icon g.setColor(getBackground()); g.fillRect(0, 0, w-1, h-1); g.setColor(Color.BLACK); g.drawLine(0, 0, w-1, 0); int y = 0; if ( !selected ) { y = 6; g.drawLine(0, y, w-1, y); // upper panel } g.drawLine(0, h-1, w-1, h-1); for ( int x = 3; x < w; x += 5 ) { g.drawLine(x, h-1, x, y); // strips } g.dispose(); return new ImageIcon(image); } protected Icon createSnapshotIcon(boolean selected) { int w = 20; int h = 16; Image image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); Graphics g = image.getGraphics(); // draw icon g.setColor(getBackground()); g.fillRect(0, 0, w-1, h-1); g.setColor(Color.BLACK); g.drawRect(0, 0, w-1, h-1); g.drawOval(w-h+3, 4, h-8, h-8); g.setColor(Color.DARK_GRAY); g.fillOval(w-h+3, 4, h-8, h-8); g.setColor(Color.red); g.drawRect(3, 3, 2, 2); g.dispose(); return new ImageIcon(image); } protected void setup() { stripPanel = null; // needs setting here, not with decl CompoundControl stripControls = mixerControls.getStripControls(MAIN_STRIP, 0); if ( stripControls != null ) { build(stripControls.getName()); } } private int lastHeight; protected void build(String name) { CompoundControl stripControls = mixerControls.getStripControls(name); if ( stripControls != null ) { lastHeight = 0; if ( stripPanel != null ) { lastHeight = stripPanel.getSize().height; remove(stripPanel); } stripPanel = new AudioCompoundControlPanel(stripControls, BoxLayout.X_AXIS, topControlSelector, topPanelFactory, true, true) { public Dimension getPreferredSize() { Dimension d = super.getPreferredSize(); if ( d.height < lastHeight ) d.height = lastHeight; return d; } }; stripPanel.setVisible(channelButton.isSelected()); // stripPanel.add(Box.createRigidArea(new Dimension(0, lastHeight))); if ( stripPanel != null ) { add(stripPanel, BorderLayout.NORTH); // !!! should have horiz scrollbar if necessary currentStripName = name; } revalidate(); } } public void addNotify() { super.addNotify(); mixerControls.addObserver(mutationObserver); } public void removeNotify() { mixerControls.deleteObserver(mutationObserver); if ( doDispose ) mutationObserver = null; super.removeNotify(); } }