package org.freeplane.core.ui.ribbon;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Window;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import org.freeplane.core.resources.ResourceController;
import org.freeplane.core.ui.components.OneTouchCollapseResizer;
import org.freeplane.core.ui.components.UITools;
import org.freeplane.core.ui.ribbon.StructureTree.StructurePath;
import org.freeplane.core.ui.ribbon.event.AboutToPerformEvent;
import org.freeplane.core.ui.ribbon.event.IActionEventListener;
import org.freeplane.core.ui.ribbon.special.EdgeStyleContributorFactory;
import org.freeplane.core.ui.ribbon.special.FilterConditionsContributorFactory;
import org.freeplane.core.ui.ribbon.special.FontStyleContributorFactory;
import org.freeplane.core.ui.ribbon.special.ViewSettingsContributorFactory;
import org.freeplane.core.ui.ribbon.special.ZoomContributorFactory;
import org.freeplane.core.util.LogUtils;
import org.freeplane.core.util.TextUtils;
import org.freeplane.features.mode.ModeController;
import org.pushingpixels.flamingo.api.common.icon.ImageWrapperResizableIcon;
import org.pushingpixels.flamingo.api.common.icon.ResizableIcon;
import org.pushingpixels.flamingo.api.ribbon.JRibbon;
import org.pushingpixels.flamingo.internal.ui.ribbon.appmenu.JRibbonApplicationMenuButton;
public class RibbonBuilder {
private final HashMap<String, IRibbonContributorFactory> contributorFactories = new HashMap<String, IRibbonContributorFactory>();
final StructureTree structure;
private final RootContributor rootContributor;
private final RibbonStructureReader reader;
private final JRibbon ribbon;
private final ModeController mode;
private final RibbonAcceleratorManager accelManager;
private boolean enabled = true;
private RibbonMapChangeAdapter changeAdapter;
private RibbonActionEventHandler raeHandler;
public RibbonBuilder(ModeController mode, JRibbon ribbon) {
structure = new StructureTree();
this.rootContributor = new RootContributor(ribbon);
this.ribbon = ribbon;
this.mode = mode;
reader = new RibbonStructureReader(this);
accelManager = new RibbonAcceleratorManager(this);
registerContributorFactory("separator", new RibbonSeparatorContributorFactory());
registerContributorFactory("ribbon_menu", new RibbonMenuContributorFactory());
registerContributorFactory("ribbon_taskbar", new RibbonTaskbarContributorFactory());
registerContributorFactory("primary_entry", new RibbonMenuPrimaryContributorFactory(this));
registerContributorFactory("entry_group", new RibbonMenuSecondaryGroupContributorFactory());
registerContributorFactory("footer_entry", new RibbonMenuFooterContributorFactory(this));
registerContributorFactory("ribbon_task", new RibbonTaskContributorFactory());
registerContributorFactory("ribbon_band", new RibbonBandContributorFactory());
registerContributorFactory("ribbon_action", new RibbonActionContributorFactory(this));
registerContributorFactory("fontStyleContributor", new FontStyleContributorFactory());
registerContributorFactory("edgeStyleContributor", new EdgeStyleContributorFactory());
registerContributorFactory("ribbon_flowband", new FlowRibbonBandContributorFactory());
registerContributorFactory("zoomContributor", new ZoomContributorFactory(this));
registerContributorFactory("viewSettingsContributor", new ViewSettingsContributorFactory());
registerContributorFactory("filterConditionsContributor", new FilterConditionsContributorFactory());
updateApplicationMenuButton(ribbon);
}
public void updateApplicationMenuButton(JRibbon ribbon) {
for(Component comp : ribbon.getComponents()) {
if(comp instanceof JRibbonApplicationMenuButton) {
String appName = ResourceController.getResourceController().getProperty("ApplicationName", "Freeplane");
URL location = ResourceController.getResourceController().getResource("/images/"+appName.trim()+"_app_menu_128.png");
if (location != null) {
ResizableIcon icon = ImageWrapperResizableIcon.getIcon(location, new Dimension(32, 32));
((JRibbonApplicationMenuButton) comp).setIcon(icon);
((JRibbonApplicationMenuButton) comp).setBackground(Color.blue);
}
}
}
}
public void add(ARibbonContributor contributor, StructurePath path, int position) {
if(contributor == null || path == null) {
throw new IllegalArgumentException("NULL");
}
synchronized (structure) {
structure.insert(path, contributor, position);
}
}
public void registerContributorFactory(String key, IRibbonContributorFactory factory) {
synchronized (contributorFactories) {
this.contributorFactories.put(key, factory);
}
}
public IRibbonContributorFactory getContributorFactory(String key) {
return this.contributorFactories.get(key);
}
public void buildRibbon() {
Window f = SwingUtilities.getWindowAncestor(ribbon);
if(!isEnabled()) {
return;
}
try {
getAcceleratorManager().loadAcceleratorPresets(new FileInputStream(getAcceleratorManager().getPresetsFile()));
}
catch (IOException ex) {
}
getMapChangeAdapter().clear();
synchronized (structure) {
final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
try {
rootContributor.contribute(new RibbonBuildContext(this), null);
}
finally {
Thread.currentThread().setContextClassLoader(contextClassLoader);
}
}
f.setMinimumSize(new Dimension(640,240));
f.pack();
}
public boolean isEnabled() {
return enabled ;
}
public void setEnabled(boolean b) {
enabled = b;
}
public void setMinimized(boolean b) {
ribbon.setMinimized(b);
OneTouchCollapseResizer otcr = OneTouchCollapseResizer.findResizerFor(ribbon);
if(otcr != null) {
otcr.recalibrate();
}
}
public boolean isMinimized() {
return ribbon.isMinimized();
}
public void updateRibbon(URL xmlResource) {
//final URL xmlSource = ResourceController.getResourceController().getResource(xmlResource);
if (xmlResource != null) {
final boolean isUserDefined = xmlResource.getProtocol().equalsIgnoreCase("file");
try{
reader.loadStructure(xmlResource);
}
catch (RuntimeException e){
if(isUserDefined){
LogUtils.warn(e);
String myMessage = TextUtils.format("ribbon_error", xmlResource.getPath(), e.getMessage());
UITools.backOtherWindows();
JOptionPane.showMessageDialog(UITools.getFrame(), myMessage, "Freeplane", JOptionPane.ERROR_MESSAGE);
System.exit(-1);
}
throw e;
}
}
}
public boolean containsPath(StructurePath path) {
synchronized (structure) {
return structure.contains(path);
}
}
public ModeController getMode() {
return mode;
}
public RibbonAcceleratorManager getAcceleratorManager() {
return accelManager;
}
public RibbonMapChangeAdapter getMapChangeAdapter() {
if(changeAdapter == null) {
changeAdapter = new RibbonMapChangeAdapter();
}
return changeAdapter;
}
public RibbonActionEventHandler getRibbonActionEventHandler() {
if(raeHandler == null) {
raeHandler = new RibbonActionEventHandler();
}
return raeHandler;
}
public static class RibbonActionEventHandler {
private List<IActionEventListener> listeners = new ArrayList<IActionEventListener>();
public void fireAboutToPerformEvent(AboutToPerformEvent event) {
synchronized (listeners) {
IActionEventListener[] aListeners = listeners.toArray(new IActionEventListener[0]);
for(int i=aListeners.length-1; i >= 0; i--) {
aListeners[i].aboutToPerform(event);
}
}
}
public void addListener(IActionEventListener listener) {
synchronized (listeners) {
if(!listeners.contains(listener)) {
listeners.add(listener);
}
}
}
public void removeListener(IActionEventListener listener) {
synchronized (listeners) {
listeners.remove(listener);
}
}
}
public JRibbon getRibbonRootComponent() {
return ribbon;
}
}