package org.jtheque.views.impl.components.menu; /* * Copyright JTheque (Baptiste Wicht) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import org.jtheque.features.Feature; import org.jtheque.features.FeatureService; import org.jtheque.features.FeatureListener; import org.jtheque.i18n.Internationalizable; import org.jtheque.i18n.LanguageService; import org.jtheque.i18n.InternationalizableContainer; import org.jtheque.images.ImageService; import org.jtheque.utils.bean.Numbers; import org.jtheque.utils.collections.CollectionUtils; import org.jtheque.utils.ui.SwingUtils; import javax.swing.AbstractButton; import javax.swing.JMenu; import javax.swing.JMenuBar; import java.io.Serializable; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.List; /** * A menu bar for the main view. * * @author Baptiste Wicht */ public final class JThequeMenuBar extends JMenuBar implements FeatureListener, InternationalizableContainer { private final Collection<Internationalizable> internationalizables = CollectionUtils.newList(25); private final Comparator<Feature> featureComparator = new ByPositionComparator(); private final ImageService imageService; private final LanguageService languageService; private final FeatureService featureService; /** * Construct a JThequeMenuBar. * * @param imageService The resource service. * @param languageService The language service. * @param featureService The feature service. */ public JThequeMenuBar(ImageService imageService, LanguageService languageService, FeatureService featureService) { super(); this.imageService = imageService; this.languageService = languageService; this.featureService = featureService; languageService.addInternationalizable(this); } /** * Build the menu. */ public void buildMenu() { List<Feature> features = CollectionUtils.copyOf(featureService.getFeatures()); Collections.sort(features, featureComparator); for (Feature feature : features) { addFeature(feature); } featureService.addFeatureListener(this); } /** * Add a feature. * * @param feature The feature to add. */ private void addFeature(Feature feature) { JThequeMenu menu = new JThequeMenu(feature.getTitleKey()); addInternationalizable(menu); addSubFeatures(feature, menu); menu.refreshText(languageService); add(menu); } /** * Add the sub features of the feature to the given menu. * * @param feature The feature to get the sub features from. * @param menu The menu to add the subfeatures to. */ private void addSubFeatures(Feature feature, JMenu menu) { List<Feature> subFeatures = CollectionUtils.copyOf(feature.getSubFeatures()); Collections.sort(subFeatures, featureComparator); for (Feature subFeature : subFeatures) { addFeature(menu, subFeature); } } /** * Add a feature. * * @param menu The JMenu. * @param feature The feature. */ private void addFeature(JMenu menu, Feature feature) { switch (feature.getType()) { case ACTION: addMenuItem(menu, feature); break; case SEPARATED_ACTION: addSeparator(menu); addMenuItem(menu, feature); break; case SEPARATED_ACTIONS: addSeparator(menu); addActions(menu, feature); break; case ACTIONS: addActions(menu, feature); break; } } /** * Add a menu item to the menu. * * @param menu The menu to add the item to. * @param feature The feature to add to the menu. */ private void addMenuItem(JMenu menu, Feature feature) { feature.getAction().refreshText(languageService); menu.add(new JThequeMenuItem(feature.getAction())); } /** * Add actions to the menu. * * @param menu The menu to add the actions to. * @param feature The feature to add to the menu. */ private void addActions(JMenu menu, Feature feature) { JThequeMenu subMenu = new JThequeMenu(feature.getTitleKey()); addInternationalizable(subMenu); if (feature.getIcon() != null) { subMenu.setIcon(imageService.getIcon(feature.getIcon())); } for (Feature subFeature : feature.getSubFeatures()) { addFeature(subMenu, subFeature); } subMenu.refreshText(languageService); menu.add(subMenu); } /** * Add a separator to the menu. * * @param menu The menu. */ private static void addSeparator(JMenu menu) { if (menu.getItemCount() > 0) { menu.addSeparator(); } } @Override public void featureAdded(Feature feature) { SwingUtils.inEdt(new Runnable(){ @Override public void run() { removeAll(); buildMenu(); SwingUtils.refresh(JThequeMenuBar.this); } }); } @Override public void featureRemoved(Feature feature) { for (int i = 0; i < getMenuCount(); i++) { final JMenu menu = getMenu(i); if (isCorrespondingMenu(feature, menu)) { SwingUtils.inEdt(new Runnable() { @Override public void run() { remove(menu); } }); break; } } } /** * Indicate if the menu correspond to the feature * * @param feature The feature to test. * @param menu The menu to test. * * @return true if the menu is corresponding to the feature else false. */ private boolean isCorrespondingMenu(Feature feature, AbstractButton menu) { return menu != null && menu.getText().equals(languageService.getMessage(feature.getTitleKey())); } @Override public void featureModified(final Feature feature) { for (int i = 0; i < getMenuCount(); i++) { final JMenu menu = getMenu(i); if (isCorrespondingMenu(feature, menu)) { SwingUtils.inEdt(new Runnable() { @Override public void run() { menu.removeAll(); addSubFeatures(feature, menu); } }); break; } } } @Override public void addInternationalizable(Internationalizable internationalizable) { internationalizables.add(internationalizable); } @Override public void refreshText(LanguageService languageService) { for (Internationalizable internationalizable : internationalizables) { internationalizable.refreshText(languageService); } SwingUtils.refresh(this); } /** * A comparator to sort the Features by position. * * @author Baptiste Wicht */ private static final class ByPositionComparator implements Comparator<Feature>, Serializable { private static final long serialVersionUID = 2723796561895917073L; @Override public int compare(Feature feature, Feature other) { return Numbers.compare(feature.getPosition(), other.getPosition()); } } }