private void draw(
      Object parentGroup, GeometryIndex parentIndex, Polygon polygon, GraphicsContext graphics) {
    String groupName = baseName;
    if (parentIndex != null) {
      groupName += "." + editingService.getIndexService().format(parentIndex);
    }

    Composite bgGroup = getOrCreateGroup(parentGroup, groupName + ".background");
    Composite geometryGroup = getOrCreateGroup(parentGroup, groupName + ".geometries");

    // Draw the exterior ring:
    GeometryIndex shellIndex =
        editingService
            .getIndexService()
            .addChildren(parentIndex, GeometryIndexType.TYPE_GEOMETRY, 0);
    if (!polygon.isEmpty()) {
      if (styleService.getBackgroundStyle() != null
          && styleService.getBackgroundStyle().getFillOpacity() > 0) {
        graphics.drawPolygon(bgGroup, "background", polygon, findGeometryStyle(shellIndex));
      }
      draw(geometryGroup, shellIndex, polygon.getExteriorRing(), graphics);
    }

    // Draw the interior rings:
    for (int i = 0; i < polygon.getNumInteriorRing(); i++) {
      GeometryIndex holeIndex =
          editingService
              .getIndexService()
              .addChildren(parentIndex, GeometryIndexType.TYPE_GEOMETRY, i + 1);
      draw(geometryGroup, holeIndex, polygon.getInteriorRingN(i), graphics);
    }
  }
 private ShapeStyle findGeometryStyle(GeometryIndex index) {
   if (!editingService.getIndexStateService().isEnabled(index)) {
     return styleService.getBackgroundDisabledStyle();
   } else if (editingService.getIndexStateService().isMarkedForDeletion(index)) {
     return styleService.getBackgroundMarkedForDeletionStyle();
   }
   return styleService.getBackgroundStyle();
 }
  public void onGeometryEditMove(GeometryEditMoveEvent event) {

    // Find the elements that need updating:
    Map<GeometryIndex, Boolean> indicesToUpdate = new HashMap<GeometryIndex, Boolean>();
    for (GeometryIndex index : event.getIndices()) {
      if (!indicesToUpdate.containsKey(index)) {
        indicesToUpdate.put(index, false);
        if (!Geometry.POINT.equals(editingService.getGeometry().getGeometryType())
            && !Geometry.MULTI_POINT.equals(editingService.getGeometry().getGeometryType())) {
          try {
            List<GeometryIndex> neighbors = null;
            switch (editingService.getIndexService().getType(index)) {
              case TYPE_VERTEX:
                // Move current vertex to the back. This helps the delete operation.
                indicesToUpdate.put(index, true);
                neighbors =
                    editingService.getIndexService().getAdjacentEdges(event.getGeometry(), index);
                if (neighbors != null) {
                  for (GeometryIndex neighborIndex : neighbors) {
                    if (!indicesToUpdate.containsKey(neighborIndex)) {
                      indicesToUpdate.put(neighborIndex, false);
                    }
                  }
                }

                neighbors =
                    editingService
                        .getIndexService()
                        .getAdjacentVertices(event.getGeometry(), index);
                if (neighbors != null) {
                  for (GeometryIndex neighborIndex : neighbors) {
                    if (!indicesToUpdate.containsKey(neighborIndex)) {
                      indicesToUpdate.put(neighborIndex, false);
                    }
                  }
                }
                break;
              case TYPE_EDGE:
                neighbors =
                    editingService
                        .getIndexService()
                        .getAdjacentVertices(event.getGeometry(), index);
                if (neighbors != null) {
                  for (GeometryIndex neighborIndex : neighbors) {
                    if (!indicesToUpdate.containsKey(neighborIndex)) {
                      indicesToUpdate.put(neighborIndex, false);
                    }
                  }
                }
                break;
              default:
            }
          } catch (GeometryIndexNotFoundException e) {
            throw new IllegalStateException(e);
          }
        }
      }
    }

    // Check if we need to draw the background (nice, but slows down):
    if (styleService.getBackgroundStyle() != null
        && styleService.getBackgroundStyle().getFillOpacity() > 0) {
      if (event.getGeometry().getGeometryType().equals(Geometry.POLYGON)) {
        org.geomajas.gwt.client.spatial.geometry.Geometry transformed =
            mapWidget
                .getMapModel()
                .getMapView()
                .getWorldViewTransformer()
                .worldToPan(GeometryConverter.toGwt(event.getGeometry()));
        mapWidget
            .getVectorContext()
            .drawPolygon(
                groups.get(baseName + ".background"),
                "background",
                (Polygon) transformed,
                styleService.getBackgroundStyle());
      } else if (event.getGeometry().getGeometryType().equals(Geometry.MULTI_POLYGON)
          && event.getGeometry().getGeometries() != null) {
        for (int i = 0; i < event.getGeometry().getGeometries().length; i++) {
          Geometry polygon = event.getGeometry().getGeometries()[i];

          org.geomajas.gwt.client.spatial.geometry.Geometry transformed =
              mapWidget
                  .getMapModel()
                  .getMapView()
                  .getWorldViewTransformer()
                  .worldToPan(GeometryConverter.toGwt(polygon));
          mapWidget
              .getVectorContext()
              .drawPolygon(
                  groups.get(baseName + ".geometry" + i + ".background"),
                  "background",
                  (Polygon) transformed,
                  styleService.getBackgroundStyle());
        }
      }
    }

    // Next, redraw the list:
    for (GeometryIndex index : indicesToUpdate.keySet()) {
      update(event.getGeometry(), index, indicesToUpdate.get(index));
    }
  }