cwindow.java

来自「This is a resource based on j2me embedde」· Java 代码 · 共 745 行 · 第 1/2 页

JAVA
745
字号
     * @return element of the window layers list that contains swept     *   layer, it can be used for further layer processing     */    CLayerElement sweepLayer(CLayer layer) {        if (layer != null) {            if (CGraphicsQ.DEBUG) {                System.err.println("Sweep Layer: " + layer);            }            synchronized (layers) {                CLayerElement le = layers.find(layer);                if (le != null) {                    // IMPL NOTE: when a layer gets removed (or has its setVisible(false))                    // called, the parent window must loop through all the other                    // layers and mark them as dirty if they intersect with the                    // layer being removed (or having its visibility changed).                    layer.addDirtyRegion();                    sweepAndMarkDirtyLayer(le, true);                    return le;                }            }        }        return null;    }    /**     * Propagate dirty region of the layer to other layers in the stack.     * The method should be called for dirty layers only.     * The dirty layer can be invisible in the case it has been     * hidden since the previous paint.     *     * IMPL_NOTE: The layer been removed or set to invisible state since     *   the previous paint is considered as "hidden", thus it should be     *   entirely dirty and must affect other visible layers accordingly.        *     * @param le dirty layer element to be propagated to other layers     * @param hidden indicates whether the dirty layer has been hidden     *   since the previous repaint     * @return the highest layer element above le with modified dirty     *   region, or null if none     */    private CLayerElement sweepAndMarkDirtyLayer(            CLayerElement le, boolean hidden) {        if (CGraphicsQ.DEBUG) {            System.err.println("Sweep and mark dirty layer: " +                le.getLayer());        }        CLayer l2;        CLayerElement res = null;        CLayer l = le.getLayer();        // Prepare absolute dirty region coordinates of layer l        int dx = l.bounds[X];        int dy = l.bounds[Y];        int dh, dw;        if (l.isEmptyDirtyRegions()) {            dw = l.bounds[W];            dh = l.bounds[H];        } else {            dx += l.dirtyBounds[X];            dy += l.dirtyBounds[Y];            dw = l.dirtyBounds[W];            dh = l.dirtyBounds[H];        }        // Sweep dirty region to upper layers        for (CLayerElement le2 = le.getUpper();                le2 != null; le2 = le2.getUpper()) {                        l2 = le2.getLayer();            if (l2.visible) {                if (l2.addDirtyRegion(                        dx-l2.bounds[X], dy-l2.bounds[Y], dw, dh)) {                    // Remember the highest changed layer                    res = le2;                }            }        }        // Sweep non-opaque dirty region to undelying layers        if (!l.opaque || hidden) {            for (CLayerElement le2 = le.getLower();                    le2 != null; le2 = le2.getLower()) {                l2 = le2.getLayer();                if (l2.visible) {                    l2.addDirtyRegion(                        dx-l2.bounds[X], dy-l2.bounds[Y], dw, dh);                }            }            // A newly hidden layer should be dirty only for the first            // succeeded paint, it should be cleaned as soon as underlying            // layers are properly marked as dirty.             if (hidden) {                l.cleanDirty();            }        }        return res;    }    // Heuristic Explanation: Any layer that needs painting also    // requires all layers below and above that region to be painted.    // This is required because layers may be transparent or even    // partially translucent - thus they require that all layers beneath    // and above them be repainted as well.    // To accomplish this we loop through the stack of layers from the top    // most to the bottom most. If a layer is "dirty" (has its dirty bit    // set), we find all layers that intersect with the dirty region and    // we mark that layer to be painted as well. If that layer is already    // marked to be painted and has its own dirty region, we union    // the existing region with the new region. If that layer does    // not have a dirty region, we simply set a new one. In the case a    // dirty region is modified for a higher layer been processed already    // we need to restart the loop from the modified layer.    // After doing this initial iteration, all layers will now be    // marked dirty where appropriate and have their individual dirty    // regions set. We then make another iteration from the bottom    // most layer to the top, painting the dirty region of each layer.    /**     * First Pass: We do sweep and mark of all layers requiring a repaint,     * the areas behind a visible opaque layers need no repaint     */    private void sweepAndMarkLayers() {        if (CGraphicsQ.DEBUG) {            System.err.println("[Sweep and mark layers]");        }        CLayer l;        CLayerElement changed;        CLayerElement le = layers.getTop();        while (le != null) {            l = le.getLayer();            if (l.visible && l.opaque) {                cleanLowerDirtyRegions(le);            }            // The dirty layer can be invisible, that means it            // has been hidden since the previous paint.            if (l.isDirty()) {                // In the case higher layer was changed we need to                // restart all the algorithm from the changed layer                changed = sweepAndMarkDirtyLayer(le, !l.visible);                if (changed != null) {                    if (CGraphicsQ.DEBUG) {                        System.err.println("Restart sweep and mark: " +                            changed.getLayer());                    }                    le = changed;                    changed = null;                    continue;                }            }            // Go to next lower layer            le = le.getLower();        }    }    /**     * Copy dirty layer references to array for further painting.     * The copying is needed to not keep lock on layers list when     * layers painting will happen. Dirty states of the layers are     * cleaned after the copying. Layers painting can change layers     * state again, but it will be served on next repaint only.     */    private void copyAndCleanDirtyLayers() {        if (CGraphicsQ.DEBUG) {            System.err.println("[Copy dirty layers]");        }        CLayer l;        dirtyCount = 0;        int layersCount = layers.size();        // Heuristics to increase array for copied dirty layers        if (layersCount > dirtyMaxCount) {            dirtyMaxCount += layersCount;            dirtyLayers = new CLayer[dirtyMaxCount];        }        // Copy dirty layer references and reset dirty layer states        for (CLayerElement le = layers.getBottom();                le != null; le = le.getUpper()) {            l = le.getLayer();            if (l.visible && l.isDirty()) {                l.copyAndCleanDirtyState();                dirtyLayers[dirtyCount++] = l;            } else { // !(visible && dirty)                if (CGraphicsQ.DEBUG) {                    System.err.println("Skip Layer: " + l);                }            } // if        } // for    }    /**     * Second Pass: We sweep through the layers from the bottom to     * the top and paint each one that is marked as dirty     *     * Note, that the painting for copied layers is done here to     * not hold the layers lock during the painting.     *     * @param g The graphics object to use to paint this window.     * @param refreshQ The custom queue which holds the set of refresh     *        regions needing to be blitted to the screen     */    private void paintLayers(Graphics g, CGraphicsQ refreshQ) {        if (CGraphicsQ.DEBUG) {            System.err.println("[Paint dirty layers]");        }        for (int i = 0; i < dirtyCount; i++) {            CLayer l = dirtyLayers[i];            // Prepare relative dirty region coordinates            // of the current layer            int dx = l.dirtyBoundsCopy[X];            int dy = l.dirtyBoundsCopy[Y];            int dw = l.dirtyBoundsCopy[W];            int dh = l.dirtyBoundsCopy[H];            // Before we call into the layer to paint, we            // translate the graphics context into the layer's            // coordinate space            g.translate(l.boundsCopy[X], l.boundsCopy[Y]);            if (CGraphicsQ.DEBUG) {                System.err.println("Painting Layer: " + l);                System.err.println("\tClip: " +                    dx + ", " + dy + ", " + dw + ", " + dh);            }            // Clip the graphics to only contain the dirty region of            // the layer (if the dirty region isn't set, clip to the            // whole layer contents).            g.clipRect(dx, dy, dw, dh);            refreshQ.queueRefresh(                l.boundsCopy[X] + dx, l.boundsCopy[Y] + dy, dw, dh);            l.paint(g);            // We restore our graphics context to prepare            // for the next layer            g.translate(-g.getTranslateX(), -g.getTranslateY());            g.translate(tranX, tranY);            // We reset our clip to this window's bounds again.            g.setClip(bounds[X], bounds[Y], bounds[W], bounds[H]);            g.setFont(font);            g.setColor(color);        } // for    }    /**     * Sets all visible layers to dirty state.     * The method is needed on system events like screen rotation,     * when generic layers system is not capabel to properly analyze     * layers changes, e.g. of move/resize kind. It could be fixed in     * the future and this method will be out of use.      */    public void setAllDirty() {        synchronized(layers) {            CLayer l;            for (CLayerElement le = layers.getBottom();                    le != null; le = le.getUpper()) {                l = le.getLayer();                if (l.visible) {                    l.addDirtyRegion();                } // if            } // for        } // synchronized    }    /**     * Paint this window. This method should not generally be overridden by     * subclasses. This method carefully stores the clip, translation, and     * color before calling into subclasses. The graphics context should be     * translated such that it is in this window's coordinate space (0,0 is     * the top left corner of this window).      *     * @param g The graphics object to use to paint this window.     * @param refreshQ The custom queue which holds the set of refresh     *        regions needing to be blitted to the screen     */    public void paint(Graphics g, CGraphicsQ refreshQ) {        // We reset our dirty flag first. Any layers that become        // dirty in the duration of this method will then cause it        // to toggle back to true for the subsequent pass.        // IMPL NOTE: when layers start to do complex animation, there will        // likely need to be better atomic handling of the dirty state,        // and layers becoming dirty and getting painted        this.dirty = false;        // Store the clip, translate, font, color        cX = g.getClipX();        cY = g.getClipY();        cW = g.getClipWidth();        cH = g.getClipHeight();        tranX = g.getTranslateX();        tranY = g.getTranslateY();        font = g.getFont();        color = g.getColor();        // We set the basic clip to the size of this window        g.setClip(bounds[X], bounds[Y], bounds[W], bounds[H]);        synchronized (layers) {            sweepAndMarkLayers();            copyAndCleanDirtyLayers();        }        paintLayers(g, refreshQ);        // We restore the original clip. The original font, color, etc.        // have already been restored        g.setClip(cX, cY, cW, cH);    }    /**     * Establish a background. This method will evaluate the parameters     * and create a background which is appropriate. If the image is non-null,     * the image will be used to create the background. If the image is null,     * the values for the colors will be used and the background will be     * painted in fill color instead. If the image is null, and the background     * color is a negative value, this layer will become transparent and no     * background will be painted.     *     * @param bgImage the image to use for the background tile (or null)     * @param bgColor if the image is null, use this color as a background     *                fill color     */    synchronized void setBackground(Image bgImage, int bgColor) {          bgLayer.setBackground(bgImage, bgColor);    }        /**     * Returns true if any layer of this window is in need of repainting.     *     * @return true if any layer of this window is marked as 'dirty'      *         and needs repainting.     */    public boolean isDirty() {        return this.dirty;    }        /**     * Mark this window as being dirty and requiring a repaint.     */        public void setDirty() {        this.dirty = true;    }    /** Constant used to reference the '0' index of the bounds array */    public static final int X = 0;        /** Constant used to reference the '1' index of the bounds array */    public static final int Y = 1;        /** Constant used to reference the '2' index of the bounds array */    public static final int W = 2;        /** Constant used to reference the '3' index of the bounds array */    public static final int H = 3;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?