package com.frinika.sequencer.gui.partview; import com.frinika.audio.gui.MeterPanel; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.Observable; import java.util.Observer; import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JTextField; import javax.swing.UIManager; import javax.swing.event.MouseInputAdapter; import com.frinika.project.gui.ProjectFrame; import com.frinika.sequencer.model.AudioLane; import com.frinika.sequencer.model.Lane; import com.frinika.sequencer.model.MenuPlugable; import com.frinika.sequencer.model.MenuPlugin; import com.frinika.sequencer.model.MidiLane; import com.frinika.sequencer.model.ProjectLane; import com.frinika.sequencer.model.RecordableLane; import com.frinika.sequencer.model.SoloManager; import com.frinika.sequencer.model.SynthLane; import com.frinika.sequencer.model.TextLane; import java.util.Vector; import static com.frinika.localization.CurrentLocale.getMessage; /** * left of each lane has a laneheaderitem. * * Placement of these is done by LaneHeaderPanel * * Do we need to subclass this ? * * @author pjl * */ public class LaneHeaderItem extends JPanel implements Observer, MenuPlugable { /** * */ private static final long serialVersionUID = 1L; JButton close = new JButton(); JTextField voice; JButton mutate = new JButton(); MyButton mute; MyButton solo; MyButton prerender; MyButton looped; // Jens MyButton record; MeterPanel meterPanel; Color selectedColor; Color defaultColor; boolean selected = false; Lane lane; LaneView voiceView; private boolean notify = true; // private int dy=-1; // ProjectContainer project; ProjectFrame frame; // Jens Color voice_selected_background; Color voice_unselected_background; JLabel midiLaneLabel; SoloManager soloManager; LaneHeaderPanel parent; public LaneHeaderItem(final ProjectFrame frame, final LaneHeaderPanel parent, final Lane lane, int index) { this.lane = lane; this.parent = parent; soloManager = frame.getProjectContainer().getSoloManager(); if (lane instanceof SynthLane) { float[] rgb = getBackground().getRGBColorComponents(new float[3]); rgb[0] *= 0.95; rgb[1] *= 0.95; rgb[2] *= 0.95; setBackground(new Color(rgb[0], rgb[1], rgb[2])); } this.defaultColor = getBackground(); this.selectedColor = Color.PINK; // this.project=project; this.frame = frame; // Jens if (lane instanceof MidiLane) { voiceView = new MidiVoiceView((MidiLane) lane, frame); } else if (lane instanceof AudioLane) { voiceView = new AudioLaneView((AudioLane) lane); AudioLane al = ((AudioLane) lane); al.getMixerControls().getSoloControl().addObserver(this); al.getMixerControls().getMuteControl().addObserver(this); } else if (lane instanceof TextLane) { // Jens voiceView = new TextLaneView((TextLane) lane, frame); } else if (lane instanceof ProjectLane) { voiceView = new ProjectView((ProjectLane) frame.getProjectContainer().getProjectLane()); } else if (lane instanceof SynthLane) { voiceView = new SynthLaneView(lane); SynthLane al = ((SynthLane) lane); if (al.getMixerControls() != null) // If it isn't a synthesizer // then it has no mixer controls { al.getMixerControls().getSoloControl().addObserver(this); al.getMixerControls().getMuteControl().addObserver(this); } } else { voiceView = new LaneView(lane); } if (lane instanceof RecordableLane) { meterPanel = new MeterPanel(); } Insets insets = new Insets(0, 0, 0, 0); this.setLayout(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); c.weightx = 0; c.ipadx = 4; Icon icon = lane.getIcon(); JLabel label = new JLabel(icon); add(label, c); if (lane instanceof MidiLane) { midiLaneLabel = label; midiLaneLabel.addMouseListener(new MouseListener() { public void mouseClicked(MouseEvent e) { if (((MidiLane) lane).isDrumLane()) { ((MidiLane) lane).setType(MidiLane.MELODIC); } else { ((MidiLane) lane).setType(MidiLane.DRUM); } repaint(); } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public void mousePressed(MouseEvent e) { } public void mouseReleased(MouseEvent e) { } }); } c.ipady = 0; c.ipadx = 4; c.weightx = 1; voice = new JTextField(lane.getName(), 8); voice_selected_background = voice.getBackground(); voice.setBackground(getBackground()); voice_unselected_background = voice.getBackground(); voice.setBorder(BorderFactory.createEmptyBorder(3, 2, 3, 2)); this.voice.setMargin(insets); this.voice.setToolTipText("Click to select this lane"); setToolTipText("Click to select this lane"); this.voice.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { lane.setName(voice.getText()); if (notify) { lane.getProject().getLaneSelection().setSelected(lane); lane.getProject().getLaneSelection().notifyListeners(); } voice.setBorder(BorderFactory.createEmptyBorder(3, 2, 3, 2)); } }); voice.setToolTipText(getMessage("laneheader.tooltip.voice_name")); this.voice.addFocusListener(new FocusListener() { public void focusGained(FocusEvent e) { if (notify) { lane.getProject().getLaneSelection().setSelected(lane); lane.getProject().getLaneSelection().notifyListeners(); } } public void focusLost(FocusEvent e) { lane.setName(voice.getText()); voice.setBorder(BorderFactory.createEmptyBorder(3, 2, 3, 2)); } }); voice.addMouseListener(new MouseInputAdapter() { @Override public void mousePressed(MouseEvent e) { // System.out.println(" Mouse Press in lane header "); if (e.getClickCount() == 2) { // System.out.println(" DOUBLE CLICK"); voice.setBorder(BorderFactory.createLineBorder(Color.BLACK)); return; } if (e.getButton() == MouseEvent.BUTTON3) { showContextMenu(e.getX(), e.getY()); e.consume(); return; } frame.getProjectContainer().getLaneSelection().clearSelection(); frame.getProjectContainer().getLaneSelection().addSelected(lane); frame.getProjectContainer().getLaneSelection().notifyListeners(); grabFocus(); } }); setFocusable(true); Color bordercolor = UIManager.getColor("Panel.background").darker(); if (index == 0) { this.setBorder(BorderFactory.createMatteBorder(1, 0, 1, 0, bordercolor)); } else { this.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, bordercolor)); } // this.setBorder(BorderFactory.createLineBorder(Color.black)); c.insets = new Insets(0, 0, 0, 1); c.fill = GridBagConstraints.HORIZONTAL; add(voice, c); c.fill = GridBagConstraints.NONE; if (lane instanceof MidiLane) { this.prerender = new MyButton("P", Color.BLUE); this.prerender.setMargin(insets); this.prerender.setToolTipText("Pre-render this voice"); prerender.setFocusable(false); this.prerender.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ((MidiLane) lane).getPlayOptions().preRendered = (!((MidiLane) lane).getPlayOptions().preRendered); if (notify) { lane.getProject().getLaneSelection().setSelected(lane); lane.getProject().getLaneSelection().notifyListeners(); } frame.repaintViews(); setState(); } }); } if (lane instanceof MidiLane) { this.looped = new MyButton("L", Color.YELLOW); this.looped.setMargin(insets); this.looped.setToolTipText("Loop this voice"); looped.setFocusable(false); this.looped.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ((MidiLane) lane).getPlayOptions().looped = (!((MidiLane) lane).getPlayOptions().looped); if (notify) { lane.getProject().getLaneSelection().setSelected(lane); lane.getProject().getLaneSelection().notifyListeners(); } frame.repaintViews(); setState(); } }); } if (lane instanceof RecordableLane) { this.mute = new MyButton("M", Color.ORANGE); this.mute.setMargin(insets); this.mute.setToolTipText("Mute this voice"); mute.setFocusable(false); this.mute.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { RecordableLane rl = (RecordableLane) lane; // rl.setMute(!rl.isMute()); soloManager.toggleMute(rl); if (notify) { lane.getProject().getLaneSelection().setSelected(lane); lane.getProject().getLaneSelection().notifyListeners(); } parent.repaint(); // setState(); } }); this.solo = new MyButton("S", Color.GREEN); this.solo.setMargin(insets); this.solo.setToolTipText("Solo this voice"); solo.setFocusable(false); this.solo.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { RecordableLane rl = (RecordableLane) lane; // rl.setMute(!rl.isMute()); soloManager.toggleSolo(rl); // ((RecordableLane) lane).setSolo(!((RecordableLane) lane) // .isSolo()); if (notify) { lane.getProject().getLaneSelection().setSelected(lane); lane.getProject().getLaneSelection().notifyListeners(); } parent.repaint(); //setState(); } }); if (lane instanceof SynthLane) { this.record = new MyButton("P", Color.BLUE); } else { this.record = new MyButton("R", Color.RED); } this.record.setMargin(insets); this.record.setFocusable(false); // this.record.setToolTipText(getMessage("sequencer.lane.record_arm_tip")); // record.setBackground(Color.RED); this.record.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { RecordableLane rl = (RecordableLane) lane; rl.setRecording(!rl.isRecording()); if (notify) { lane.getProject().getLaneSelection().setSelected(lane); lane.getProject().getLaneSelection().notifyListeners(); } setState(); } }); c.weightx = 0; if (lane instanceof MidiLane) { add(looped, c); } // Jens if (lane instanceof MidiLane) { add(prerender, c); } boolean show_msr = true; if (lane instanceof SynthLane) { if (!((SynthLane) lane).isSynthesizer()) { show_msr = false; } } if (show_msr) { add(record, c); add(mute, c); add(solo, c); } } if (meterPanel != null) { c.anchor = GridBagConstraints.EAST; c.fill = GridBagConstraints.VERTICAL; // c.weightx=.5; c.insets = new Insets(2, 2, 2, 2); c.ipadx = 0; c.ipady = 0; c.weighty = 1.0; add(meterPanel, c); } } static Vector<MenuPlugin> menuPlugins = new Vector<MenuPlugin>(); /** * Allow custom menus to be added. * * This will appear at the top of the right button popup menu. * * @param menuPlugin */ public static void addPluginRightButtonMenu(MenuPlugin menuPlugin) { LaneHeaderItem.menuPlugins.add(menuPlugin); } /** * Shows the right-click context menu of the current component. * * @param frame * @param invoker * @param x * @param y */ public void showContextMenu(int x, int y) { // build popup-menu from menuPrefix and own items if (menuPlugins == null) { return; } JPopupMenu popup = new JPopupMenu(); for (MenuPlugin plugin : menuPlugins) { plugin.initContextMenu(popup, this); } //initContextMenu(frame, popup); popup.show(this, x, y); } @Override public void paintComponent(Graphics g) { setState(); super.paintComponent(g); } void setState() { // avoid selecting notify = false; if (!this.voice.hasFocus()) { this.voice.setText(lane.getName()); this.voice.setCaretPosition(0); } if (this.lane.isSelected()) { if (!this.selected) { // setBackground(this.selectedColor); setBackground(this.voice_selected_background); voice.setBackground(voice_selected_background); this.selected = true; } } else { if (this.selected) { setBackground(this.defaultColor); voice.setBackground(voice_unselected_background); if (voice.hasFocus()) { grabFocus(); } this.selected = false; } } if (lane instanceof RecordableLane) { // weird inverse logic to get color right TODO create my own button RecordableLane rl = (RecordableLane) lane; record.draw(rl.isRecording()); mute.draw(rl.isMute(), soloManager.isMute(rl)); solo.draw(soloManager.isSolo(rl)); if (lane instanceof MidiLane) { looped.draw(((MidiLane) lane).getPlayOptions().looped); } // Jens if (lane instanceof MidiLane) { prerender.draw(((MidiLane) lane).getPlayOptions().preRendered); } // Jens } if (lane instanceof MidiLane) { midiLaneLabel.setIcon(lane.getIcon()); midiLaneLabel.validate(); // if (!((MidiLane) lane).isDrumLane()) { // // System.out.println(" set icon note"); // midiLaneLabel.setIcon(iconNoteLane); // midiLaneLabel.validate(); // } else { // // System.out.println(" set icon drum"); // midiLaneLabel.setIcon(iconDrumLane); // midiLaneLabel.validate(); // } } notify = true; } static double dBmax = 20.0 * Math.log10(1.0); static double dBmin = dBmax - 40.0; static double dBrange = dBmax - dBmin; public void updateMeter() { if (meterPanel == null) { return; } Graphics g = meterPanel.getGraphics(); if (g == null) { return; } RecordableLane r = (RecordableLane) lane; double val = r.getMonitorValue(); double dBval = 20.0 * Math.log10(val + 1e-40); double fact = (dBval - dBmin) / dBrange; // System.out.println(fact); if (val >= 1.0) { meterPanel.updateMeter(fact, Color.RED); } else { meterPanel.updateMeter(fact, Color.GREEN); } } class MyButton extends JButton { private static final long serialVersionUID = 1L; private Color onCol; private Color userOnCol; MyButton(String t, Color onCol) { super(t); this.onCol = onCol.brighter(); this.userOnCol = onCol; /* * setUI(new MetalButtonUI()); setBorderPainted(true); * setContentAreaFilled(false); setOpaque(false); setBorder( * BorderFactory.createCompoundBorder( * BorderFactory.createLineBorder(Color.GRAY), * BorderFactory.createEmptyBorder(2,2,2,2))); */ } void draw(boolean on) { // setOpaque(on); if (on) { setBackground(userOnCol); } else { setBackground(defaultColor); } } void draw(boolean on, boolean userOn) { // setOpaque(on); // assert( ! (on && !userOn)); if (userOn) { setBackground(userOnCol); } else if (on) { setBackground(onCol); } else { setBackground(defaultColor); } } } public void update(Observable o, Object arg) { repaint(); } public Lane getLane() { return lane; } }