blob: 5feba48d066e4c155bd5a690e177b0df6f116916 [file] [log] [blame]
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* 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.
*/
package com.intellij.util.ui.update;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.project.DumbAwareRunnable;
import com.intellij.openapi.util.Disposer;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import java.lang.ref.WeakReference;
public class UiNotifyConnector implements Disposable, HierarchyListener{
@NotNull
private final WeakReference<Component> myComponent;
private Activatable myTarget;
public UiNotifyConnector(@NotNull final Component component, @NotNull final Activatable target) {
myComponent = new WeakReference<Component>(component);
myTarget = target;
if (component.isShowing()) {
showNotify();
} else {
hideNotify();
}
component.addHierarchyListener(this);
}
public void hierarchyChanged(HierarchyEvent e) {
if (isDisposed()) return;
if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) > 0) {
final Runnable runnable = new DumbAwareRunnable() {
public void run() {
final Component c = myComponent.get();
if (isDisposed() || c == null) return;
if (c.isShowing()) {
showNotify();
}
else {
hideNotify();
}
}
};
final Application app = ApplicationManager.getApplication();
if (app != null && app.isDispatchThread()) {
app.invokeLater(runnable, ModalityState.current());
} else {
//noinspection SSBasedInspection
SwingUtilities.invokeLater(runnable);
}
}
}
protected void hideNotify() {
myTarget.hideNotify();
}
protected void showNotify() {
myTarget.showNotify();
}
public void dispose() {
if (isDisposed()) return;
myTarget.hideNotify();
final Component c = myComponent.get();
if (c != null) {
c.removeHierarchyListener(this);
}
myTarget = null;
myComponent.clear();
}
private boolean isDisposed() {
return myTarget == null;
}
public static class Once extends UiNotifyConnector {
private boolean myShown;
private boolean myHidden;
public Once(final Component component, final Activatable target) {
super(component, target);
}
protected final void hideNotify() {
super.hideNotify();
myHidden = true;
disposeIfNeeded();
}
protected final void showNotify() {
super.showNotify();
myShown = true;
disposeIfNeeded();
}
private void disposeIfNeeded() {
if (myShown && myHidden) {
Disposer.dispose(this);
}
}
}
public static void doWhenFirstShown(@NotNull JComponent c, @NotNull final Runnable runnable) {
new Once(c, new Activatable() {
public void showNotify() {
runnable.run();
}
public void hideNotify() {
}
});
}
}