/*
* Copyright (C) 2011 Peransin Nicolas. All rights reserved.
* Use is subject to license terms.
*/
package org.mypsycho.swing.app;
import java.awt.Component;
import java.awt.Container;
import java.awt.IllegalComponentStateException;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Locale;
import javax.swing.JComponent;
import javax.swing.RootPaneContainer;
import org.mypsycho.swing.ContainerPropagator;
import org.mypsycho.swing.app.utils.SwingHelper;
/**
* This component is in charge to injecte components and propagate Locale.
* <p>
* Locale in AWT in automatically defined by the parent component.
* </p><p>
* In Swing, Locale is not propagate from parent to branch in component tree
* (because of contrainst in MVC pattern where component is ready to be drawn
* since constructor, before being attached).
* </p>
* This bean listens at component tree of views and deals with automatic
* updates.
*
* @author Peransin Nicolas
*/
public class ComponentManager extends ContainerPropagator {
public static ApplicationContext getContext(JComponent c) {
return (ApplicationContext) c.getClientProperty(ApplicationContext.CLIENT_PROPERTY);
}
ApplicationContext context;
PropertyChangeListener localeListener;
public ComponentManager(ApplicationContext parent) {
// We do not rely on build listener,
// we do not want the update to be popagated to children
context = parent;
localeListener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getSource() instanceof Component) {
localeChange(evt);
}
}
};
}
public Application getApplication() {
return context.getApplication();
}
void localeChange(PropertyChangeEvent evt) {
// Propagate the locale BEFORE update injection,
// the children will be updated before a more specific context is injected
Locale locale = (Locale) evt.getNewValue();
if (evt.getSource() instanceof Container) {
Container target = (Container) evt.getSource();
Locale old = (Locale) evt.getOldValue();
int count = target.getComponentCount();
for (int i = 0; i < count; i++) {
Component child = target.getComponent(i);
if (Locales.isSwing(child)) {
if (!Locales.isForced(child)) {
child.setLocale(locale);
}
} else if (child.getLocale().equals(old)) { // always valid ??
child.setLocale(locale);
}
}
}
context.getResourceManager().inject(evt.getSource(), locale);
}
JComponent getMarkable(Component c) {
if (c instanceof JComponent) {
return (JComponent) c;
}
if (c instanceof RootPaneContainer) {
return ((RootPaneContainer) c).getRootPane();
}
return null;
}
@Override
protected void componentAdding(Component target) {
// Install resources
JComponent markable = getMarkable(target);
if (markable != null) {
markable.putClientProperty(ApplicationContext.CLIENT_PROPERTY, context);
markable.putClientProperty(ApplicationContext.RESOURCE_MARKER, true);
}
// Propagate the locale
Component parent = target.getParent();
if (!SwingHelper.isSwing(target) || !Locales.isForced(target)) {
Locale parentValue = getApplication().getLocale();
if (parent != null) {
try {
parentValue = parent.getLocale();
} catch (IllegalComponentStateException ignore) {
// headless, use the application value
}
}
target.setLocale(parentValue);
}
target.addPropertyChangeListener(Locales.LOCALE_PROP, localeListener);
}
/*
* (non-Javadoc)
*
* @see com.psycho.swing.ContainerPropagator#componentAdded(java.awt.Component)
*/
@Override
protected void componentAdded(Component target) {
context.getResourceManager().inject(target, target.getLocale());
if (target instanceof ApplicationComponent) {
((ApplicationComponent) target).register(getApplication());
}
JComponent markable = getMarkable(target);
if (markable != null) {
markable.putClientProperty(ApplicationContext.RESOURCE_MARKER, null);
}
}
/*
* (non-Javadoc)
*
* @see com.psycho.swing.ContainerPropagator#componentRemoving(java.awt.Component)
*/
@Override
protected void componentRemoving(Component target) {
target.removePropertyChangeListener(Locales.LOCALE_PROP, localeListener);
}
}