Beispiel #1
0
 /**
  * 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
 }
Beispiel #2
0
  /**
   * 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();
    }
  }
Beispiel #3
0
 /**
  * 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
 }
Beispiel #4
0
 /**
  * Handle input from some type of device-dependent input method. This could be input from
  * something such as T9, or a phonebook lookup, etc.
  *
  * @param str the text to handle as direct input
  * @return true if this window or one of its layers processed the event
  */
 public boolean methodInput(String str) {
   CLayer layer;
   synchronized (layers) {
     for (CLayerElement le = layers.getTop(); le != null; le = le.getLower()) {
       layer = le.getLayer();
       if (layer.visible && layer.supportsInput && layer.methodInput(str)) {
         return true;
       }
     }
   } // sync
   return false;
 }
Beispiel #5
0
 /**
  * Allow this window to process key input. The type of key input will be press, release, repeat,
  * etc. The key code will identify which key generated the event. This method will return true if
  * the event was processed by this window or one of its layers, false otherwise.
  *
  * @param type the type of key event (press, release, repeat)
  * @param keyCode the identifier of the key which generated the event
  * @return true if this window or one of its layers processed the event
  */
 public boolean keyInput(int type, int keyCode) {
   CLayer layer;
   synchronized (layers) {
     for (CLayerElement le = layers.getTop(); le != null; le = le.getLower()) {
       layer = le.getLayer();
       if (layer.supportsInput && layer.keyInput(type, keyCode)) {
         return true;
       }
     }
   } // sync
   return false;
 }
Beispiel #6
0
  /**
   * Subtract this layer area from an underlying dirty regions. The method is designed to reduce
   * dirty regions of a layres below the opaque visible layer.
   *
   * @param le layer list element
   */
  private void cleanLowerDirtyRegions(CLayerElement le) {
    if (CGraphicsQ.DEBUG) {
      System.err.println("Clean dirty regions under opaque layer: " + le.getLayer());
    }

    CLayer l = le.getLayer();
    for (CLayerElement le2 = le.getLower(); le2 != null; le2 = le2.getLower()) {
      CLayer l2 = le2.getLayer();
      if (l2.isDirty()) {
        l2.subDirtyRegion(
            l.bounds[X] - l2.bounds[X], l.bounds[Y] - l2.bounds[Y], l.bounds[W], l.bounds[H]);
      }
    }
  }
Beispiel #7
0
 /**
  * Check whether layer is overlapped with a higher visible layer in the layer stack of the window
  *
  * @param l layer to check overlapping
  * @return true if overlapped, false otherwise
  */
 public boolean isOverlapped(CLayer l) {
   synchronized (layers) {
     CLayerElement le = layers.find(l);
     if (le != null) {
       CLayer l2;
       for (le = le.getUpper(); le != null; le = le.getUpper()) {
         l2 = le.getLayer();
         if (l2.isVisible() && l.intersects(l2)) {
           return true;
         }
       }
     }
   }
   return false;
 }
Beispiel #8
0
 /**
  * Remove a layer from this CWindow. This method will remove the given layer from the "deck" of
  * layers associated with this CWindow. If successfull, this method will return true, false
  * otherwise (for example, if the layer does not belong to this window).
  *
  * @param layer the layer to remove from this window
  * @return true if successful, false otherwise
  */
 public boolean removeLayer(CLayer layer) {
   synchronized (layers) {
     CLayerElement le = sweepLayer(layer);
     if (le != null) {
       if (CGraphicsQ.DEBUG) {
         System.err.println("Remove Layer: " + layer);
       }
       layer.owner = null;
       requestRepaint();
       layers.removeLayerElement(le);
       layer.removeNotify(this);
       return true;
     }
   }
   return false;
 }
Beispiel #9
0
 /**
  * Allow this window to process pointer input. The type of pointer input will be press, release,
  * drag, etc. The x and y coordinates will identify the point at which the pointer event occurred
  * in the coordinate system of this window. This window will translate the coordinates
  * appropriately for each layer contained in this window. This method will return true if the
  * event was processed by this window or one of its layers, false otherwise.
  *
  * @param type the type of pointer event (press, release, drag)
  * @param x the x coordinate of the location of the event
  * @param y the y coordinate of the location of the event
  * @return true if this window or one of its layers processed the event
  */
 public boolean pointerInput(int type, int x, int y) {
   CLayer layer;
   synchronized (layers) {
     for (CLayerElement le = layers.getTop(); le != null; le = le.getLower()) {
       layer = le.getLayer();
       if (layer.visible && layer.supportsInput && layer.handlePoint(x, y)) {
         // If the layer is visible, supports input, and
         // contains the point of the pointer press, we translate
         // the point into the layer's coordinate space and
         // pass on the input
         if (layer.pointerInput(type, x - layer.bounds[X], y - layer.bounds[Y])) {
           return true;
         }
       }
     }
   } // sync
   return false;
 }
Beispiel #10
0
 /**
  * Add a new CLayer to the "deck" of layers associated with this CWindow. This method will
  * sequentially add layers to the window, placing subsequently added layers on top of previously
  * added layers.
  *
  * @param layer the new layer to add to this window
  * @return true if new layer was added, false otherwise
  */
 public boolean addLayer(CLayer layer) {
   if (layer != null) {
     if (CGraphicsQ.DEBUG) {
       System.err.println("Add Layer: " + layer);
     }
     synchronized (layers) {
       if (layers.find(layer) == null) {
         layer.owner = this;
         layers.addLayer(layer);
         layer.addDirtyRegion();
         requestRepaint();
         layer.addNotify();
         return true;
       }
     }
   }
   return false;
 }
Beispiel #11
0
  /**
   * Second Pass: We sweep through the layers from the bottom to the top and paint each one that is
   * marked as dirty
   *
   * <p>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
  }
Beispiel #12
0
  /**
   * Move layer to anotger location
   *
   * @param newBounds new bounds for this layer
   * @param x New 'x' coordinate of the layer's origin
   * @param y New 'y' coordinate of the layer's origin
   * @param w New width of the layer
   * @param h New height of the layer
   * @return true if successful, false otherwise
   */
  public boolean relocateLayer(CLayer layer, int x, int y, int w, int h) {

    if (layer != null) {
      synchronized (layers) {
        if (sweepLayer(layer) != null) {
          if (CGraphicsQ.DEBUG) {
            System.err.println("Relocate Layer: " + layer);
          }
          int[] oldBounds = {layer.bounds[X], layer.bounds[Y], layer.bounds[W], layer.bounds[H]};

          if (oldBounds[X] != x || oldBounds[Y] != y || oldBounds[W] != w || oldBounds[H] != h) {
            layer.setBounds(x, y, w, h);
            layer.addDirtyRegion();
            requestRepaint();
            layer.relocateNotify(oldBounds);
            return true;
          }
        }
      }
    }
    return false;
  }
Beispiel #13
0
  /**
   * 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.
   *
   * <p>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;
  }
Beispiel #14
0
 /**
  * Update dirty regions of all visible layers in the stack regarding the entire area of the given
  * layer as being dirty. The method is needed to perform layer move/resize/remove opertion, since
  * other layers should be informed of changed area.
  *
  * @param layer the layer whose area should be reported as dirty to other stack layers
  * @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;
 }