/* * Copyright (c) 2005-2010 Flamingo Kirill Grouchnikov. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * o Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * o Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * o Neither the name of Flamingo Kirill Grouchnikov nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.pushingpixels.flamingo.internal.ui.ribbon; import java.util.*; import javax.swing.UIManager; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.plaf.UIResource; import org.pushingpixels.flamingo.api.common.*; import org.pushingpixels.flamingo.api.ribbon.*; /** * Control panel of a single {@link JRibbonBand}. This class is for internal use * only and should not be directly used by the applications. * * @author Kirill Grouchnikov */ public class JBandControlPanel extends AbstractBandControlPanel implements UIResource { public static class ControlPanelGroup { public String groupTitle; /** * Indication whether <code>this</code> control panel has galleries. */ private boolean hasGalleries; /** * Number of galleries in <code>this</code> control panel. */ private int galleryCount; /** * Mapping from priority to galleries. */ private Map<RibbonElementPriority, List<JRibbonGallery>> ribbonGalleries; /** * Mapping from gallery to priority. */ private Map<JRibbonGallery, RibbonElementPriority> ribbonGalleriesPriorities; /** * Mapping from priority to ribbon buttons. */ private Map<RibbonElementPriority, List<AbstractCommandButton>> ribbonButtons; /** * Mapping from ribbon button to priority. */ private Map<AbstractCommandButton, RibbonElementPriority> ribbonButtonsPriorities; private List<JRibbonComponent> coreComps; private Map<JRibbonComponent, Integer> coreCompRowSpans; public ControlPanelGroup(String groupTitle) { this.groupTitle = groupTitle; this.ribbonButtons = new HashMap<RibbonElementPriority, java.util.List<AbstractCommandButton>>(); this.ribbonButtonsPriorities = new HashMap<AbstractCommandButton, RibbonElementPriority>(); this.ribbonGalleries = new HashMap<RibbonElementPriority, java.util.List<JRibbonGallery>>(); this.ribbonGalleriesPriorities = new HashMap<JRibbonGallery, RibbonElementPriority>(); this.hasGalleries = false; this.galleryCount = 0; this.coreComps = new ArrayList<JRibbonComponent>(); this.coreCompRowSpans = new HashMap<JRibbonComponent, Integer>(); } public String getGroupTitle() { return groupTitle; } public void setGroupTitle(String newTitle) { if ((this.groupTitle == null) && (newTitle != null)) { throw new IllegalArgumentException( "Cannot set a title for an unnamed group"); } if ((this.groupTitle != null) && (newTitle == null)) { throw new IllegalArgumentException( "Cannot remove a title from a named group"); } this.groupTitle = newTitle; } public boolean isCoreContent() { return !this.coreComps.isEmpty(); } /** * Adds a new ribbon button to <code>this</code> control panel. * * @param ribbonButton * Ribbon button to add. * @param priority * Ribbon button priority. */ public synchronized void addCommandButton( AbstractCommandButton ribbonButton, RibbonElementPriority priority) { if (this.groupTitle != null) { throw new UnsupportedOperationException( "Can't add command buttons to ribbon band group with non-null title"); } if (this.isCoreContent()) { throw new UnsupportedOperationException( "Ribbon band groups do not support mixing JRibbonComponents and custom Flamingo components"); } if (!this.ribbonButtons.containsKey(priority)) { this.ribbonButtons.put(priority, new LinkedList<AbstractCommandButton>()); } List<AbstractCommandButton> al = this.ribbonButtons.get(priority); al.add(ribbonButton); this.ribbonButtonsPriorities.put(ribbonButton, priority); ribbonButton.setDisplayState(CommandButtonDisplayState.BIG); } /** * Adds a new in-ribbon gallery to <code>this</code> control panel. * * @param ribbonGallery * Ribbon gallery to add. * @param priority * Ribbon gallery priority. */ public synchronized void addRibbonGallery(JRibbonGallery ribbonGallery, RibbonElementPriority priority) { if (this.groupTitle != null) { throw new UnsupportedOperationException( "Can't add galleries to ribbon band group with non-null title"); } if (this.isCoreContent()) { throw new UnsupportedOperationException( "Ribbon band groups do not support mixing JRibbonComponents and custom Flamingo components"); } // check the name if (!this.ribbonGalleries.containsKey(priority)) { this.ribbonGalleries.put(priority, new LinkedList<JRibbonGallery>()); } List<JRibbonGallery> al = this.ribbonGalleries.get(priority); al.add(ribbonGallery); this.ribbonGalleriesPriorities.put(ribbonGallery, priority); ribbonGallery.setDisplayPriority(RibbonElementPriority.TOP); this.hasGalleries = true; this.galleryCount++; } /** * Sets new priority of a ribbon button in <code>this</code> control * panel. * * @param ribbonButton * Gallery button. * @param newPriority * New priority for the specified ribbon button. */ public synchronized void setPriority(JCommandButton ribbonButton, RibbonElementPriority newPriority) { RibbonElementPriority oldPriority = this.ribbonButtonsPriorities .get(ribbonButton); if (newPriority == oldPriority) return; this.ribbonButtons.get(oldPriority).remove(ribbonButton); if (!this.ribbonButtons.containsKey(newPriority)) { this.ribbonButtons.put(newPriority, new ArrayList<AbstractCommandButton>()); } this.ribbonButtons.get(newPriority).add(ribbonButton); } /** * Sets new priority of an in-ribbon gallery in <code>this</code> * control panel. * * @param ribbonGallery * In-ribbon gallery. * @param newPriority * New priority for the specified in-ribbon gallery. */ public synchronized void setPriority(JRibbonGallery ribbonGallery, RibbonElementPriority newPriority) { RibbonElementPriority oldPriority = this.ribbonGalleriesPriorities .get(ribbonGallery); if (newPriority == oldPriority) return; this.ribbonGalleries.get(oldPriority).remove(ribbonGallery); if (!this.ribbonGalleries.containsKey(newPriority)) { this.ribbonGalleries.put(newPriority, new ArrayList<JRibbonGallery>()); } this.ribbonGalleries.get(newPriority).add(ribbonGallery); } public void addRibbonComponent(JRibbonComponent comp, int rowSpan) { if (!this.ribbonButtonsPriorities.isEmpty() || !this.ribbonGalleries.isEmpty()) { throw new UnsupportedOperationException( "Ribbon band groups do not support mixing JRibbonComponents and custom Flamingo components"); } comp.setOpaque(false); this.coreComps.add(comp); this.coreCompRowSpans.put(comp, rowSpan); } /** * Retrieves all ribbon buttons of specified priority from * <code>this</code> control panel. * * @param priority * Priority. * @return All ribbon buttons of specified priority from * <code>this</code> control panel. */ public List<AbstractCommandButton> getRibbonButtons( RibbonElementPriority priority) { List<AbstractCommandButton> result = this.ribbonButtons .get(priority); if (result == null) return EMPTY_GALLERY_BUTTONS_LIST; return result; } /** * Retrieves all in-ribbon galleries of specified priority from * <code>this</code> control panel. * * @param priority * Priority. * @return All in-ribbon galleries of specified priority from * <code>this</code> control panel. */ public List<JRibbonGallery> getRibbonGalleries( RibbonElementPriority priority) { List<JRibbonGallery> result = this.ribbonGalleries.get(priority); if (result == null) return EMPTY_RIBBON_GALLERIES_LIST; return result; } /** * Returns indication whether <code>this</code> control panel has * in-ribbon galleries. * * @return <code>true</code> if <code>this</code> control panel has * in-ribbon galleries, <code>false</code> otherwise. */ public boolean hasRibbonGalleries() { return this.hasGalleries; } /** * Returns the number of in-ribbon galleries in <code>this</code> * control panel. * * @return Number of in-ribbon galleries in <code>this</code> control * panel. */ public int getRibbonGalleriesCount() { return this.galleryCount; } public List<JRibbonComponent> getRibbonComps() { return this.coreComps; } public Map<JRibbonComponent, Integer> getRibbonCompsRowSpans() { return this.coreCompRowSpans; } } /** * Maps from gallery name to gallery. */ private Map<String, JRibbonGallery> galleryNameMap; private LinkedList<ControlPanelGroup> controlPanelGroups; /** * Empty list of buttons. */ public static final List<AbstractCommandButton> EMPTY_GALLERY_BUTTONS_LIST = new LinkedList<AbstractCommandButton>(); /** * Empty list of galleries. */ public static final List<JRibbonGallery> EMPTY_RIBBON_GALLERIES_LIST = new LinkedList<JRibbonGallery>(); /** * The UI class ID string. */ public static final String uiClassID = "BandControlPanelUI"; /** * Creates a control panel for specified ribbon band. * * @param ribbonBand * Ribbon band. */ public JBandControlPanel() { super(); this.controlPanelGroups = new LinkedList<ControlPanelGroup>(); this.galleryNameMap = new HashMap<String, JRibbonGallery>(); } /** * Sets the new UI delegate. * * @param ui * New UI delegate. */ public void setUI(BandControlPanelUI ui) { super.setUI(ui); } /* * (non-Javadoc) * * @see javax.swing.JPanel#updateUI() */ @Override public void updateUI() { if (UIManager.get(getUIClassID()) != null) { setUI((BandControlPanelUI) UIManager.getUI(this)); } else { setUI(new BasicBandControlPanelUI()); } } /* * (non-Javadoc) * * @see javax.swing.JPanel#getUI() */ @Override public BandControlPanelUI getUI() { return (BandControlPanelUI) ui; } /* * (non-Javadoc) * * @see javax.swing.JPanel#getUIClassID() */ @Override public String getUIClassID() { return uiClassID; } /** * Adds a new ribbon button to <code>this</code> control panel. * * @param ribbonButton * Ribbon button to add. * @param priority * Ribbon button priority. */ public synchronized void addCommandButton( AbstractCommandButton ribbonButton, RibbonElementPriority priority) { if (this.controlPanelGroups.size() == 0) this.startGroup(); this.controlPanelGroups.getLast().addCommandButton(ribbonButton, priority); super.add(ribbonButton); } /** * Adds a new in-ribbon gallery to <code>this</code> control panel. * * @param ribbonGallery * Ribbon gallery to add. * @param priority * Ribbon gallery priority. */ public synchronized void addRibbonGallery(JRibbonGallery ribbonGallery, RibbonElementPriority priority) { // check the name String galleryName = ribbonGallery.getName(); if ((galleryName == null) || (galleryName.isEmpty())) { throw new IllegalArgumentException( "Ribbon gallery name null or empty"); } if (this.galleryNameMap.containsKey(galleryName)) { throw new IllegalArgumentException( "Another riboon gallery with the same name already exists"); } if (this.controlPanelGroups.size() == 0) this.startGroup(); this.controlPanelGroups.getLast().addRibbonGallery(ribbonGallery, priority); this.galleryNameMap.put(galleryName, ribbonGallery); super.add(ribbonGallery); } /** * Sets new priority of a ribbon button in <code>this</code> control panel. * * @param ribbonButton * Gallery button. * @param newPriority * New priority for the specified ribbon button. */ public synchronized void setPriority(JCommandButton ribbonButton, RibbonElementPriority newPriority) { if (this.controlPanelGroups.size() == 0) this.startGroup(); this.controlPanelGroups.getLast() .setPriority(ribbonButton, newPriority); } /** * Sets new priority of an in-ribbon gallery in <code>this</code> control * panel. * * @param ribbonGallery * In-ribbon gallery. * @param newPriority * New priority for the specified in-ribbon gallery. */ public synchronized void setPriority(JRibbonGallery ribbonGallery, RibbonElementPriority newPriority) { if (this.controlPanelGroups.size() == 0) this.startGroup(); this.controlPanelGroups.getLast().setPriority(ribbonGallery, newPriority); } public void addRibbonComponent(JRibbonComponent comp) { this.addRibbonComponent(comp, 1); } public void addRibbonComponent(JRibbonComponent comp, int rowSpan) { if (this.controlPanelGroups.size() == 0) this.startGroup(); this.controlPanelGroups.getLast().addRibbonComponent(comp, rowSpan); super.add(comp); } public List<ControlPanelGroup> getControlPanelGroups() { return Collections.unmodifiableList(this.controlPanelGroups); } public int getControlPanelGroupCount() { if (this.controlPanelGroups == null) return 1; return this.controlPanelGroups.size(); } public String getControlPanelGroupTitle(int controlPanelGroupIndex) { if (this.controlPanelGroups == null) return null; return this.controlPanelGroups.get(controlPanelGroupIndex).groupTitle; } public int startGroup() { return this.startGroup(null); } public int startGroup(String groupTitle) { ControlPanelGroup controlPanelGroup = new ControlPanelGroup(groupTitle); this.controlPanelGroups.addLast(controlPanelGroup); this.fireChanged(); return this.controlPanelGroups.size() - 1; } public void setGroupTitle(int groupIndex, String groupTitle) { this.controlPanelGroups.get(groupIndex).setGroupTitle(groupTitle); this.fireChanged(); } /** * Returns the ribbon gallery based on its name. * * @param galleryName * Ribbon gallery name. * @return Ribbon gallery. */ public JRibbonGallery getRibbonGallery(String galleryName) { return this.galleryNameMap.get(galleryName); } public void addChangeListener(ChangeListener l) { this.listenerList.add(ChangeListener.class, l); } public void removeChangeListener(ChangeListener l) { this.listenerList.remove(ChangeListener.class, l); } protected void fireChanged() { // Guaranteed to return a non-null array Object[] listeners = listenerList.getListenerList(); ChangeEvent ce = new ChangeEvent(this); // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == ChangeListener.class) { ((ChangeListener) listeners[i + 1]).stateChanged(ce); } } } public List<JRibbonComponent> getRibbonComponents(int groupIndex) { return Collections.unmodifiableList(this.controlPanelGroups.get( groupIndex).getRibbonComps()); } }