001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Pavel Dolgov
019: * @version $Revision$
020: */package java.awt;
021:
022: import java.awt.event.PaintEvent;
023: import java.util.IdentityHashMap;
024: import java.util.Map;
025: import java.util.Map.Entry;
026:
027: import org.apache.harmony.awt.ClipRegion;
028: import org.apache.harmony.awt.gl.MultiRectArea;
029:
030: /**
031: * The collection of component regions that need to be painted
032: */
033: class RedrawManager {
034:
035: final Window window;
036:
037: private boolean paintNeeded;
038: private boolean updateNeeded;
039:
040: private final Map<Component, MultiRectArea> paintRegions = new IdentityHashMap<Component, MultiRectArea>();
041: private final Map<Component, MultiRectArea> updateRegions = new IdentityHashMap<Component, MultiRectArea>();
042:
043: public RedrawManager(Window window) {
044: this .window = window;
045: }
046:
047: public void addPaintRegion(Component c, Rectangle r) {
048: synchronized (this ) {
049: addRegion(paintRegions, c, r);
050: paintNeeded = true;
051: }
052: }
053:
054: public void addPaintRegion(Component c, MultiRectArea r) {
055: synchronized (this ) {
056: addRegion(paintRegions, c, r);
057: paintNeeded = true;
058: }
059: }
060:
061: public void addUpdateRegion(Component c, Rectangle r) {
062: synchronized (this ) {
063: addRegion(updateRegions, c, r);
064: updateNeeded = true;
065: }
066: }
067:
068: public void addUpdateRegion(Component c, MultiRectArea r) {
069: synchronized (this ) {
070: addRegion(updateRegions, c, r);
071: updateNeeded = true;
072: }
073: }
074:
075: public void addUpdateRegion(Component c) {
076: addUpdateRegion(c, new Rectangle(0, 0, c.w, c.h));
077: }
078:
079: /**
080: * Post paint events to the queue, with the clip from paintRegions
081: */
082: private void doPaint() {
083: postEvents(paintRegions, PaintEvent.PAINT);
084: paintRegions.clear();
085: paintNeeded = false;
086: }
087:
088: /**
089: * Translate update regions to HW ancestor,
090: * then post update events to the queue, with the clip from updateRegions
091: */
092: private void doUpdate() {
093: synchronized (this ) {
094: postEvents(updateRegions, PaintEvent.UPDATE);
095: updateRegions.clear();
096: updateNeeded = false;
097: }
098: }
099:
100: private static void addRegion(Map<Component, MultiRectArea> map,
101: Component c, Rectangle r) {
102: MultiRectArea area = map.get(c);
103: if (area != null) {
104: area.add(r);
105: } else {
106: area = new MultiRectArea(r);
107: map.put(c, area);
108: }
109:
110: }
111:
112: private static void addRegion(Map<Component, MultiRectArea> map,
113: Component c, MultiRectArea r) {
114: MultiRectArea area = map.get(c);
115: if (area != null) {
116: area.add(r);
117: } else {
118: area = new MultiRectArea(r);
119: map.put(c, area);
120: }
121:
122: }
123:
124: public boolean redrawAll() {
125: synchronized (this ) {
126: subtractPaintFromUpdate();
127:
128: boolean result = paintNeeded;
129: if (paintNeeded) {
130: doPaint();
131: }
132: if (updateNeeded) {
133: doUpdate();
134: }
135: return result;
136: }
137: }
138:
139: private void subtractPaintFromUpdate() {
140: for (Object name : paintRegions.entrySet()) {
141: Map.Entry<?, ?> entry = (Entry<?, ?>) name;
142: Component c = (Component) entry.getKey();
143: MultiRectArea paint = (MultiRectArea) entry.getValue();
144: MultiRectArea update = updateRegions.get(c);
145: if (update == null) {
146: continue;
147: }
148: update.substract(paint);
149: if (update.isEmpty()) {
150: updateRegions.remove(c);
151: }
152: }
153: }
154:
155: /**
156: * Post paint events for the collected regions
157: * @param regions - Map<Component, MultiRectArea> -
158: * regions that need to be painted
159: * @param eventId - PaintEvent.PAINT or PaintEvent.UPDATE
160: */
161: private static void postEvents(
162: Map<Component, MultiRectArea> regions, int eventId) {
163: for (Object name : regions.entrySet()) {
164: Map.Entry<?, ?> entry = (Entry<?, ?>) name;
165: Component c = (Component) entry.getKey();
166: if (!c.visible || !c.behaviour.isDisplayable()) {
167: continue;
168: }
169: MultiRectArea clip = (MultiRectArea) entry.getValue();
170: if (!clip.isEmpty()) {
171: postPaintEvent(c, clip, eventId);
172: }
173: }
174: }
175:
176: private static void postPaintEvent(Component c, MultiRectArea clip,
177: int eventId) {
178: PaintEvent event = new PaintEvent(c, eventId, new ClipRegion(
179: clip));
180: c.toolkit.getSystemEventQueueImpl().postEvent(event);
181: }
182:
183: /**
184: * Subtract the component's region that waits for painting
185: * from the provided component's area.
186: *
187: * @return the resulting region, or null if the result is empty
188: */
189: public MultiRectArea subtractPendingRepaintRegion(Component c,
190: MultiRectArea mra) {
191: if (mra.isEmpty()) {
192: return null;
193: }
194: int x = 0, y = 0;
195: while (c != null && c.behaviour.isLightweight()) {
196: x += c.x;
197: y += c.y;
198: c = c.parent;
199: }
200: if (c == null) {
201: return null;
202: }
203:
204: synchronized (this ) {
205: // Now c is heavyweight for sure
206: MultiRectArea paint = paintRegions.get(c);
207: MultiRectArea update = updateRegions.get(c);
208:
209: if (paint == null && update == null) {
210: return mra;
211: }
212: MultiRectArea diff = new MultiRectArea(mra);
213: diff.translate(x, y);
214:
215: if (paint != null) {
216: diff.substract(paint);
217: }
218: if (update != null) {
219: diff.substract(update);
220: }
221: if (diff.isEmpty()) {
222: return null;
223: }
224: diff.translate(-x, -y);
225: return diff;
226: }
227: }
228: }
|