2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * Created by IntelliJ IDEA.
23 package com
.intellij
.ide
;
25 import com
.intellij
.openapi
.diagnostic
.Logger
;
26 import org
.jetbrains
.annotations
.NonNls
;
30 import java
.awt
.image
.VolatileImage
;
31 import java
.lang
.ref
.WeakReference
;
32 import java
.lang
.reflect
.Field
;
36 * see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6209673
38 public class IdeRepaintManager
extends RepaintManager
{
39 private static final Logger LOG
= Logger
.getInstance("#com.intellij.ide.HackyRepaintManager");
41 private Map
<GraphicsConfiguration
, VolatileImage
> myImagesMap
;
42 @NonNls private static final String FAULTY_FIELD_NAME
= "volatileMap";
44 WeakReference
<JComponent
> myLastComponent
;
46 public Image
getVolatileOffscreenBuffer(Component c
, int proposedWidth
, int proposedHeight
) {
47 final Image buffer
= super.getVolatileOffscreenBuffer(c
, proposedWidth
, proposedHeight
);
52 @SuppressWarnings({"unchecked"})
53 private void clearLeakyImages() {
54 if (myImagesMap
== null) {
56 Field volMapField
= RepaintManager
.class.getDeclaredField(FAULTY_FIELD_NAME
);
57 volMapField
.setAccessible(true);
58 myImagesMap
= (Map
<GraphicsConfiguration
, VolatileImage
>)volMapField
.get(this);
65 if (myImagesMap
.size() > 3) {
66 for (VolatileImage image
: myImagesMap
.values()) {
74 public void addInvalidComponent(final JComponent invalidComponent
) {
75 checkThreadViolations(invalidComponent
);
77 super.addInvalidComponent(invalidComponent
);
81 public void addDirtyRegion(final JComponent c
, final int x
, final int y
, final int w
, final int h
) {
82 checkThreadViolations(c
);
84 super.addDirtyRegion(c
, x
, y
, w
, h
);
87 private void checkThreadViolations(JComponent c
) {
88 if (!SwingUtilities
.isEventDispatchThread() && c
.isShowing()) {
89 boolean repaint
= false;
90 boolean fromSwing
= false;
91 boolean imageUpdate
= false;
92 final Exception exception
= new Exception();
93 StackTraceElement
[] stackTrace
= exception
.getStackTrace();
94 for (StackTraceElement st
: stackTrace
) {
95 if (repaint
&& st
.getClassName().startsWith("javax.swing.")) {
98 if (repaint
&& "imageUpdate".equals(st
.getMethodName())) {
101 if ("repaint".equals(st
.getMethodName())) {
107 //assuming it is java.awt.image.ImageObserver.imageUpdate(...)
108 //image was asynchronously updated, that's ok
111 if (repaint
&& !fromSwing
) {
112 //no problems here, since repaint() is thread safe
115 //ignore the last processed component
116 if (myLastComponent
!= null && c
== myLastComponent
.get()) {
119 myLastComponent
= new WeakReference
<JComponent
>(c
);
121 LOG
.warn("Access to realized (ever shown) UI components should be done only from the AWT event dispatch thread," +
122 " revalidate(), invalidate() & repaint() is ok from any thread", exception
);