//----------------------------------------------------------------------------// // // // B o a r d s P a n e // // // //----------------------------------------------------------------------------// // <editor-fold defaultstate="collapsed" desc="hdr"> // // Copyright © Hervé Bitteur and others 2000-2013. All rights reserved. // // This software is released under the GNU General Public License. // // Goto http://kenai.com/projects/audiveris to report bugs or suggestions. // //----------------------------------------------------------------------------// // </editor-fold> package omr.ui; import omr.ui.util.Panel; import omr.ui.util.SeparablePopupMenu; import static omr.ui.util.UIPredicates.*; import com.jgoodies.forms.builder.PanelBuilder; import com.jgoodies.forms.layout.CellConstraints; import com.jgoodies.forms.layout.FormLayout; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.awt.Component; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import javax.swing.JCheckBoxMenuItem; import javax.swing.JComponent; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.SwingConstants; /** * Class {@code BoardsPane} defines a view on a set of user {@link * Board} instances, where data related to current point, run, section, * glyph, etc can be displayed in dedicated boards. * * <p>There is one BoardsPane instance for each view of the same sheet, * each with its own collection of board instances. * * @author Hervé Bitteur */ public class BoardsPane { //~ Static fields/initializers --------------------------------------------- /** Usual logger utility */ private static final Logger logger = LoggerFactory.getLogger(BoardsPane.class); //~ Instance fields -------------------------------------------------------- /** The concrete UI component */ private final Panel component; /** Sequence of current boards, kept ordered by board preferred position */ private final List<Board> boards = new ArrayList<>(); /** Unique (application-wide) name for this pane. */ private String name; /** Mouse listener */ private MouseAdapter mouseAdapter = new MyMouseAdapter(); //~ Constructors ----------------------------------------------------------- //------------// // BoardsPane // //------------// /** * Create a BoardsPane, with initial boards. * * @param boards the initial collection of boards */ public BoardsPane (List<Board> boards) { this.boards.clear(); for (Board board : boards) { this.boards.add(board); board.setParent(this); } Collections.sort(this.boards); component = new Panel(); component.setNoInsets(); component.add(defineLayout()); component.addMouseListener(mouseAdapter); } //------------// // BoardsPane // //------------// /** * Create a BoardsPane, with initial boards. * * @param boards the initial collection of boards */ public BoardsPane (Board... boards) { this(Arrays.asList(boards)); } //~ Methods ---------------------------------------------------------------- //----------// // addBoard // //----------// /** * Dynamically add a board into BoardsPane structure. * * @param board the board instance to add */ public void addBoard (Board board) { // Avoid duplicates if (getBoard(board.getName()) != null) { return; } boards.add(board); board.setParent(this); Collections.sort(this.boards); update(); } //---------// // connect // //---------// /** * Invoked when the boardsPane has been selected, in order to * connect all the contained boards to their inputs. */ public void connect () { ///logger.warn("Connect " + this); for (Board board : boards) { if (board.isSelected()) { board.connect(); } else { board.disconnect(); } } } //------------// // disconnect // //------------// /** * Invoked when the boardsPane has been deselected. */ public void disconnect () { ///logger.info("-BoardPane " + name + " disconnect"); for (Board board : boards) { board.disconnect(); } } //--------------// // getComponent // //--------------// /** * Report the UI component. * * @return the concrete component */ public JComponent getComponent () { return component; } //---------// // getName // //---------// /** * Report the unique name for this boards pane. * * @return the declared name */ public String getName () { return name; } //-------------// // removeBoard // //-------------// /** * Dynamically remove a board from BoardsPane structure. * * @param board the board instance to remove */ public void removeBoard (Board board) { boards.remove(board); update(); } //---------// // setName // //---------// /** * Assign the unique name for this boards pane. * * @param name the assigned name */ public void setName (String name) { this.name = name; component.setName(name); } //----------// // toString // //----------// @Override public String toString () { StringBuilder sb = new StringBuilder("{"); sb.append(getClass().getSimpleName()); sb.append(" ") .append(name) .append(" ["); boolean first = true; for (Board board : boards) { if (first) { first = false; } else { sb.append(","); } sb.append(board.getName()); if (!board.isSelected()) { sb.append(":HIDDEN"); } } sb.append("]}"); return sb.toString(); } //--------// // update // //--------// /** * Modify the BoardsPane component composition. */ void update () { connect(); int count = component.getComponentCount(); Component comp = component.getComponent(count - 1); component.remove(comp); component.add(defineLayout()); component.revalidate(); component.repaint(); } //--------------// // defineLayout // //--------------// private JPanel defineLayout () { // Prepare layout elements final String panelInterline = Panel.getPanelInterline(); StringBuilder sbr = new StringBuilder(); boolean first = true; for (Board board : boards) { if (board.isSelected()) { if (first) { first = false; } else { sbr.append(", ") .append(panelInterline) .append(", "); } sbr.append("pref"); } } FormLayout layout = new FormLayout("pref", sbr.toString()); Panel panel = new Panel(); panel.setNoInsets(); PanelBuilder builder = new PanelBuilder(layout, panel); builder.setDefaultDialogBorder(); CellConstraints cst = new CellConstraints(); // Now add the desired components, using provided order int r = 1; for (Board board : boards) { if (board.isSelected()) { builder.add(board.getComponent(), cst.xy(1, r)); r += 2; } } JPanel boardsPanel = builder.getPanel(); boardsPanel.setBorder(null); return boardsPanel; } //----------// // getBoard // //----------// private Board getBoard (String title) { for (Board b : boards) { if (b.getName() .equals(title)) { return b; } } return null; } //~ Inner Classes ---------------------------------------------------------- //----------------// // MyMouseAdapter // //----------------// /** * Subclassed to offer mouse interaction. */ private class MyMouseAdapter extends MouseAdapter implements ItemListener { //~ Methods ------------------------------------------------------------ //------------------// // itemStateChanged // //------------------// /** * Triggered from popup menu. * * @param e menu item event */ @Override public void itemStateChanged (ItemEvent e) { JCheckBoxMenuItem item = (JCheckBoxMenuItem) e.getItem(); Board board = getBoard(item.getText()); board.setSelected(item.getState()); } //--------------// // mousePressed // //--------------// /** * Triggered when mouse is pressed. * * @param e mouse event */ @Override public void mousePressed (MouseEvent e) { if (isContextWanted(e)) { JPopupMenu popup = new SeparablePopupMenu(); // A title for this menu JMenuItem head = new JMenuItem("Boards for selection:"); head.setHorizontalAlignment(SwingConstants.CENTER); head.setEnabled(false); popup.add(head); popup.addSeparator(); for (Board board : boards) { JMenuItem item = new JCheckBoxMenuItem( board.getName(), board.isSelected()); item.addItemListener(this); item.setToolTipText( board.isSelected() ? "Deselect this board?" : "Select this board?"); popup.add(item); } popup.show(component, e.getX(), e.getY()); } } } }