@Override
  public void draw(float fXCenter, float fYCenter, GL2 gl, GLU glu) {

    HashMap<PartialDisc, PDDrawingStrategySelected> mapSelectedDrawingStrategies =
        new HashMap<PartialDisc, PDDrawingStrategySelected>();
    parentIndicatorType = SelectionType.NORMAL;

    initDrawingStrategies(mapSelectedDrawingStrategies);

    PartialDisc pdCurrentRootElement = radialHierarchy.getCurrentRootElement();

    gl.glLoadIdentity();
    gl.glTranslatef(fXCenter, fYCenter, 0);

    float fHierarchyOuterRadius =
        Math.min(
            fXCenter * RadialHierarchyRenderStyle.USED_SCREEN_PERCENTAGE,
            fYCenter * RadialHierarchyRenderStyle.USED_SCREEN_PERCENTAGE);
    float fDiscWidth = fHierarchyOuterRadius / iDisplayedHierarchyDepth;

    pdCurrentRootElement.drawHierarchyFull(gl, glu, fDiscWidth, iDisplayedHierarchyDepth);

    // The selected elements have to be drawn (again using their own drawing
    // strategy) at last for
    // correct antialiasing

    for (PartialDisc pdSelected : mapSelectedDrawingStrategies.keySet()) {
      PDDrawingStrategySelected dsCurrent = mapSelectedDrawingStrategies.get(pdSelected);
      dsCurrent.drawPartialDisc(gl, glu, pdSelected);
    }

    if (parentIndicatorType != SelectionType.NORMAL) {
      gl.glPushClientAttrib(GL.GL_COLOR_BUFFER_BIT);
      if (parentIndicatorType == SelectionType.SELECTION)
        gl.glColor3fv(SelectionType.SELECTION.getColor().getRGB(), 0);
      else gl.glColor3fv(SelectionType.MOUSE_OVER.getColor().getRGB(), 0);
      GLPrimitives.renderCircle(glu, fDiscWidth / 2.0f, 100);
      GLPrimitives.renderCircleBorder(gl, glu, fDiscWidth / 2.0f, 100, 2);
      gl.glPopAttrib();
    }

    LabelManager.get()
        .drawAllLabels(gl, glu, fXCenter * 2.0f, fYCenter * 2.0f, fHierarchyOuterRadius);
    LabelManager.get().clearLabels();

    radialHierarchy.setNewSelection(false);
  }
  /**
   * Initializes drawing strategies for all selected elements of the radial hierarchy's selection
   * manager.
   *
   * @param mapSelectedDrawingStrategies Map is filled with key-value pairs where the key is a
   *     selected partial disc and its value is the corresponding drawing strategy.
   */
  private void initDrawingStrategies(
      HashMap<PartialDisc, PDDrawingStrategySelected> mapSelectedDrawingStrategies) {

    PartialDisc pdCurrentRootElement = radialHierarchy.getCurrentRootElement();
    int iMaxDisplayedHierarchyDepth = radialHierarchy.getMaxDisplayedHierarchyDepth();
    pdCurrentMouseOverElement = null;

    iDisplayedHierarchyDepth =
        Math.min(iMaxDisplayedHierarchyDepth, pdCurrentRootElement.getDepth());

    DrawingStrategyManager drawingStrategyManager = radialHierarchy.getDrawingStrategyManager();

    APDDrawingStrategy dsDefault = drawingStrategyManager.getDefaultDrawingStrategy();

    SelectionManager selectionManager = radialHierarchy.getSelectionManager();
    Set<Integer> setSelection = selectionManager.getElements(SelectionType.SELECTION);
    Set<Integer> setMouseOver = selectionManager.getElements(SelectionType.MOUSE_OVER);

    pdCurrentRootElement.setPDDrawingStrategyChildren(dsDefault, iDisplayedHierarchyDepth);

    HashMap<PartialDisc, SelectionType> mapSelectedElements =
        new HashMap<PartialDisc, SelectionType>();
    HashMap<PartialDisc, SelectionType> mapChildIndictatorElements =
        new HashMap<PartialDisc, SelectionType>();

    boolean bIsNewSelection = radialHierarchy.isNewSelection();

    // Take the mouse over element from the selected elements, if any and if
    // displayed.
    for (Integer elementID : setSelection) {
      PartialDisc pdSelected = radialHierarchy.getPartialDisc(elementID);
      if (pdSelected != null) {
        if (pdSelected.isCurrentlyDisplayed(pdCurrentRootElement, iDisplayedHierarchyDepth)) {
          pdCurrentMouseOverElement = pdSelected;
          break;
        }
      }
    }

    for (Integer elementID : setSelection) {
      PartialDisc pdSelected = radialHierarchy.getPartialDisc(elementID);
      if (pdSelected != null) {

        if (pdCurrentMouseOverElement == null && bIsNewSelection) {

          PartialDisc pdParent = pdSelected.getParent();
          if (pdParent == null) {
            pdCurrentRootElement = pdSelected;
          } else {
            pdCurrentRootElement = pdParent;
          }
          iDisplayedHierarchyDepth =
              Math.min(iMaxDisplayedHierarchyDepth, pdCurrentRootElement.getDepth());

          radialHierarchy.setCurrentRootElement(pdCurrentRootElement);
          radialHierarchy.setCurrentSelectedElement(pdCurrentRootElement);
          navigationHistory.addNewHistoryEntry(
              this, pdCurrentRootElement, pdCurrentRootElement, iMaxDisplayedHierarchyDepth);
          mapSelectedElements.put(pdSelected, SelectionType.SELECTION);
          pdCurrentMouseOverElement = pdSelected;
          continue;
        }

        PartialDisc pdIndicated =
            pdSelected.getFirstVisibleElementOnParentPathToRoot(
                pdCurrentRootElement, iDisplayedHierarchyDepth);

        if (pdIndicated == pdSelected) {
          mapSelectedElements.put(pdSelected, SelectionType.SELECTION);
        } else if (pdIndicated == null) {
          parentIndicatorType = SelectionType.SELECTION;
        } else {
          mapChildIndictatorElements.put(pdIndicated, SelectionType.SELECTION);
        }
      }
    }

    for (Integer elementID : setMouseOver) {
      PartialDisc pdMouseOver = radialHierarchy.getPartialDisc(elementID);
      if (pdMouseOver != null) {

        if (pdCurrentMouseOverElement == null) {
          if (pdMouseOver.isCurrentlyDisplayed(pdCurrentRootElement, iDisplayedHierarchyDepth)) {
            mapSelectedElements.put(pdMouseOver, SelectionType.MOUSE_OVER);
            pdCurrentMouseOverElement = pdMouseOver;
            continue;
          }
        }

        PartialDisc pdIndicated =
            pdMouseOver.getFirstVisibleElementOnParentPathToRoot(
                pdCurrentRootElement, iDisplayedHierarchyDepth);

        if (pdIndicated == pdMouseOver) {
          if (!mapSelectedElements.containsKey(pdMouseOver))
            mapSelectedElements.put(pdMouseOver, SelectionType.MOUSE_OVER);
        } else if (pdIndicated == null) {
          if (parentIndicatorType != SelectionType.SELECTION)
            parentIndicatorType = SelectionType.MOUSE_OVER;
        } else {
          if (!mapChildIndictatorElements.containsKey(pdIndicated))
            mapChildIndictatorElements.put(pdIndicated, SelectionType.MOUSE_OVER);
        }
      }
    }

    for (PartialDisc pdSelected : mapSelectedElements.keySet()) {
      PDDrawingStrategySelected dsCurrent =
          (PDDrawingStrategySelected)
              drawingStrategyManager.createDrawingStrategy(EPDDrawingStrategyType.SELECTED);

      if (mapSelectedElements.get(pdSelected) == SelectionType.SELECTION) {
        dsCurrent.setBorderColor(SelectionType.SELECTION.getColor().getRGBA());
      }
      if (mapChildIndictatorElements.containsKey(pdSelected)) {
        if (mapChildIndictatorElements.get(pdSelected) == SelectionType.SELECTION) {
          dsCurrent.setChildIndicatorColor(SelectionType.SELECTION.getColor().getRGBA());
        } else {
          dsCurrent.setChildIndicatorColor(SelectionType.MOUSE_OVER.getColor().getRGBA());
        }
        mapChildIndictatorElements.remove(pdSelected);
      }

      mapSelectedDrawingStrategies.put(pdSelected, dsCurrent);
      pdSelected.setPDDrawingStrategy(dsCurrent);
    }

    for (PartialDisc pdIndicated : mapChildIndictatorElements.keySet()) {
      APDDrawingStrategyChildIndicator dsCurrent =
          (APDDrawingStrategyChildIndicator)
              drawingStrategyManager.createDrawingStrategy(
                  drawingStrategyManager.getDefaultDrawingStrategy().getDrawingStrategyType());

      if (mapChildIndictatorElements.get(pdIndicated) == SelectionType.SELECTION) {
        dsCurrent.setChildIndicatorColor(SelectionType.SELECTION.getColor().getRGBA());
      } else {
        dsCurrent.setChildIndicatorColor(SelectionType.MOUSE_OVER.getColor().getRGBA());
      }

      pdIndicated.setPDDrawingStrategy(dsCurrent);
    }

    if (pdCurrentMouseOverElement != null) {
      APDDrawingStrategyDecorator dsLabelDecorator =
          new PDDrawingStrategyLabelDecorator(
              radialHierarchy.getDataDomain().getTable().getColorMapper());
      pdCurrentMouseOverElement.decoratePDDrawingStrategyChildren(
          dsLabelDecorator,
          Math.min(RadialHierarchyRenderStyle.MAX_LABELING_DEPTH, iDisplayedHierarchyDepth));
    }
  }