This commit is contained in:
Anton Tarasov 2008-03-20 14:26:38 +03:00
commit 6898039064
2 changed files with 134 additions and 194 deletions

View File

@ -6492,7 +6492,7 @@ public abstract class Component implements ImageObserver, MenuContainer,
// will need some help.
Container parent = this.parent;
if (parent != null && parent.peer instanceof LightweightPeer) {
nativeInLightFixer = new NativeInLightFixer();
relocateComponent();
}
}
invalidate();
@ -6603,10 +6603,6 @@ public abstract class Component implements ImageObserver, MenuContainer,
}
}
if (nativeInLightFixer != null) {
nativeInLightFixer.uninstall();
}
ComponentPeer p = peer;
if (p != null) {
boolean isLightweight = isLightweight();
@ -8514,8 +8510,6 @@ public abstract class Component implements ImageObserver, MenuContainer,
setComponentOrientation(orientation);
}
transient NativeInLightFixer nativeInLightFixer;
/**
* Checks that this component meets the prerequesites to be focus owner:
* - it is enabled, visible, focusable
@ -8541,188 +8535,25 @@ public abstract class Component implements ImageObserver, MenuContainer,
}
/**
* This odd class is to help out a native component that has been
* embedded in a lightweight component. Moving lightweight
* components around and changing their visibility is not seen
* by the native window system. This is a feature for lightweights,
* but a problem for native components that depend upon the
* lightweights. An instance of this class listens to the lightweight
* parents of an associated native component (the outer class).
*
* @author Timothy Prinzing
* Fix the location of the HW component in a LW container hierarchy.
*/
final class NativeInLightFixer implements ComponentListener, ContainerListener {
NativeInLightFixer() {
lightParents = new Vector();
install(parent);
}
void install(Container parent) {
lightParents.clear();
Container p = parent;
boolean isLwParentsVisible = true;
// stash a reference to the components that are being observed so that
// we can reliably remove ourself as a listener later.
for (; p.peer instanceof LightweightPeer; p = p.parent) {
// register listeners and stash a reference
p.addComponentListener(this);
p.addContainerListener(this);
lightParents.addElement(p);
isLwParentsVisible &= p.isVisible();
final void relocateComponent() {
synchronized (getTreeLock()) {
if (peer == null) {
return;
}
// register with the native host (native parent of associated native)
// to get notified if the top-level lightweight is removed.
nativeHost = p;
p.addContainerListener(this);
// kick start the fixup. Since the event isn't looked at
// we can simulate movement notification.
componentMoved(null);
if (!isLwParentsVisible) {
synchronized (getTreeLock()) {
if (peer != null) {
peer.hide();
}
}
}
}
void uninstall() {
if (nativeHost != null) {
removeReferences();
}
}
// --- ComponentListener -------------------------------------------
/**
* Invoked when one of the lightweight parents has been resized.
* This doesn't change the position of the native child so it
* is ignored.
*/
public void componentResized(ComponentEvent e) {
}
/**
* Invoked when one of the lightweight parents has been moved.
* The native peer must be told of the new position which is
* relative to the native container that is hosting the
* lightweight components.
*/
public void componentMoved(ComponentEvent e) {
synchronized (getTreeLock()) {
int nativeX = x;
int nativeY = y;
for(Component c = parent; (c != null) &&
(c.peer instanceof LightweightPeer);
c = c.parent) {
nativeX += c.x;
nativeY += c.y;
}
if (peer != null) {
peer.setBounds(nativeX, nativeY, width, height,
ComponentPeer.SET_LOCATION);
}
}
}
/**
* Invoked when a lightweight parent component has been
* shown. The associated native component must also be
* shown if it hasn't had an overriding hide done on it.
*/
public void componentShown(ComponentEvent e) {
if (shouldShow()) {
synchronized (getTreeLock()) {
if (peer != null) {
peer.show();
}
}
}
}
/**
* Invoked when one of the lightweight parents become visible.
* Returns true if component and all its lightweight
* parents are visible.
*/
private boolean shouldShow() {
boolean isLwParentsVisible = visible;
for (int i = lightParents.size() - 1;
i >= 0 && isLwParentsVisible;
i--)
int nativeX = x;
int nativeY = y;
for (Component cont = getContainer();
cont != null && cont.isLightweight();
cont = cont.getContainer())
{
isLwParentsVisible &=
((Container) lightParents.elementAt(i)).isVisible();
nativeX += cont.x;
nativeY += cont.y;
}
return isLwParentsVisible;
peer.setBounds(nativeX, nativeY, width, height,
ComponentPeer.SET_LOCATION);
}
/**
* Invoked when component has been hidden.
*/
public void componentHidden(ComponentEvent e) {
if (visible) {
synchronized (getTreeLock()) {
if (peer != null) {
peer.hide();
}
}
}
}
// --- ContainerListener ------------------------------------
/**
* Invoked when a component has been added to a lightweight
* parent. This doesn't effect the native component.
*/
public void componentAdded(ContainerEvent e) {
}
/**
* Invoked when a lightweight parent has been removed.
* This means the services of this listener are no longer
* required and it should remove all references (ie
* registered listeners).
*/
public void componentRemoved(ContainerEvent e) {
Component c = e.getChild();
if (c == Component.this) {
removeReferences();
} else {
int n = lightParents.size();
for (int i = 0; i < n; i++) {
Container p = (Container) lightParents.elementAt(i);
if (p == c) {
removeReferences();
break;
}
}
}
}
/**
* Removes references to this object so it can be
* garbage collected.
*/
void removeReferences() {
int n = lightParents.size();
for (int i = 0; i < n; i++) {
Container c = (Container) lightParents.elementAt(i);
c.removeComponentListener(this);
c.removeContainerListener(this);
}
nativeHost.removeContainerListener(this);
lightParents.clear();
nativeHost = null;
}
Vector lightParents;
Container nativeHost;
}
/**

View File

@ -832,16 +832,8 @@ public class Container extends Component {
}
if (!comp.isLightweight() && isLightweight()) {
// If component is heavyweight and one of the containers is lightweight
// some NativeInLightFixer activity should be performed
if (!curParent.isLightweight()) {
// Moving from heavyweight container to lightweight container - should create NativeInLightFixer
// since addNotify does this
comp.nativeInLightFixer = new NativeInLightFixer();
} else {
// Component already has NativeInLightFixer - just reinstall it
// because hierarchy changed and he needs to rebuild list of parents to listen.
comp.nativeInLightFixer.install(this);
}
// the location of the component should be fixed.
comp.relocateComponent();
}
}
}
@ -3953,6 +3945,83 @@ public class Container extends Component {
}
}
private void recursiveShowHeavyweightChildren() {
if (!hasHeavyweightDescendants() || !isVisible()) {
return;
}
for (int index = 0; index < getComponentCount(); index++) {
Component comp = getComponent(index);
if (comp.isLightweight()) {
if (comp instanceof Container) {
((Container)comp).recursiveShowHeavyweightChildren();
}
} else {
if (comp.isVisible()) {
ComponentPeer peer = comp.getPeer();
if (peer != null) {
peer.show();
}
}
}
}
}
private void recursiveHideHeavyweightChildren() {
if (!hasHeavyweightDescendants()) {
return;
}
for (int index = 0; index < getComponentCount(); index++) {
Component comp = getComponent(index);
if (comp.isLightweight()) {
if (comp instanceof Container) {
((Container)comp).recursiveHideHeavyweightChildren();
}
} else {
if (comp.isVisible()) {
ComponentPeer peer = comp.getPeer();
if (peer != null) {
peer.hide();
}
}
}
}
}
private void recursiveRelocateHeavyweightChildren(Point origin) {
for (int index = 0; index < getComponentCount(); index++) {
Component comp = getComponent(index);
if (comp.isLightweight()) {
if (comp instanceof Container &&
((Container)comp).hasHeavyweightDescendants())
{
final Point newOrigin = new Point(origin);
newOrigin.translate(comp.getX(), comp.getY());
((Container)comp).recursiveRelocateHeavyweightChildren(newOrigin);
}
} else {
ComponentPeer peer = comp.getPeer();
if (peer != null) {
peer.setBounds(origin.x + comp.getX(), origin.y + comp.getY(),
comp.getWidth(), comp.getHeight(),
ComponentPeer.SET_LOCATION);
}
}
}
}
/*
* Consider the heavyweight container hides or shows the HW descendants
* automatically. Therefore we care of LW containers' visibility only.
*/
private boolean isRecursivelyVisibleUpToHeavyweightContainer() {
if (!isLightweight()) {
return true;
}
return isVisible() && (getContainer() == null ||
getContainer().isRecursivelyVisibleUpToHeavyweightContainer());
}
@Override
void mixOnShowing() {
synchronized (getTreeLock()) {
if (mixingLog.isLoggable(Level.FINE)) {
@ -3961,6 +4030,10 @@ public class Container extends Component {
boolean isLightweight = isLightweight();
if (isLightweight && isRecursivelyVisibleUpToHeavyweightContainer()) {
recursiveShowHeavyweightChildren();
}
if (!isLightweight || (isLightweight && hasHeavyweightDescendants())) {
recursiveApplyCurrentShape();
}
@ -3969,6 +4042,42 @@ public class Container extends Component {
}
}
@Override
void mixOnHiding(boolean isLightweight) {
synchronized (getTreeLock()) {
if (mixingLog.isLoggable(Level.FINE)) {
mixingLog.fine("this = " + this +
"; isLightweight=" + isLightweight);
}
if (isLightweight) {
recursiveHideHeavyweightChildren();
}
super.mixOnHiding(isLightweight);
}
}
@Override
void mixOnReshaping() {
synchronized (getTreeLock()) {
if (mixingLog.isLoggable(Level.FINE)) {
mixingLog.fine("this = " + this);
}
if (isLightweight() && hasHeavyweightDescendants()) {
final Point origin = new Point(getX(), getY());
for (Container cont = getContainer();
cont != null && cont.isLightweight();
cont = cont.getContainer())
{
origin.translate(cont.getX(), cont.getY());
}
recursiveRelocateHeavyweightChildren(origin);
}
super.mixOnReshaping();
}
}
@Override
void mixOnZOrderChanging(int oldZorder, int newZorder) {
synchronized (getTreeLock()) {
if (mixingLog.isLoggable(Level.FINE)) {