/**
   * TODO summary sentence for createControl ...
   *
   * @param parent
   * @param klisten
   * @return Generated composite
   */
  public Composite createControl(Composite parent, KeyListener klisten) {
    this.part =
        AbstractSimpleConfigurator.subpart(parent, Messages.SimpleStyleConfigurator_label_label);
    this.klisten = klisten;

    this.on = new Button(part, SWT.CHECK);

    this.field = new Combo(part, SWT.DROP_DOWN | SWT.READ_ONLY);
    this.field.addKeyListener(klisten);
    if (this.schema != null) {
      List<AttributeDescriptor> types = this.schema.getAttributeDescriptors();
      List<String> typeStrings = new ArrayList<String>();
      for (AttributeDescriptor attributeDescriptor : types) {
        typeStrings.add(attributeDescriptor.getLocalName());
      }
      this.field.setItems(typeStrings.toArray(new String[0]));
    }
    this.field.setToolTipText(Messages.LabelViewer_field_tooltip);

    this.fonter = new FontEditor(part);

    // determine which placement to use
    if (schema != null) {
      if (SLD.isLine(schema)) {
        pointPlacement = false;
      } else {
        pointPlacement = true;
      }
      if (pointPlacement) {
        // point placement (3 combos: AnchorPoint (Horiz, Vert) + Rotation)
        initPlacementContentsPoint();
      } else {
        // line placement (1 combo: Perpendicular Offset)
        initPlacementContentsLine();
      }
    }

    listen(true);

    return part;
  }
  /**
   * Start editing the provided symbolizer.
   *
   * @param schema
   * @param sym
   * @param mode
   */
  public void set(SimpleFeatureType schema, TextSymbolizer sym, Mode mode) {
    listen(false);
    try {
      this.schema = schema;
      this.enabled = (mode != Mode.NONE && sym != null);

      this.font = SLDs.textFont(sym);
      if (this.font == null || this.font.length == 0) {
        this.font = new FontData[] {new FontData("Arial", 12, SWT.NORMAL)}; // $NON-NLS-1$
      }
      this.labelType = SLDs.textLabelString(sym);
      this.colour = SLDs.textFontFill(sym);
      if (this.colour == null) {
        this.colour = Color.BLACK;
      }

      this.on.setEnabled(mode != Mode.NONE);
      this.fonter.setColorValue(this.colour);
      this.fonter.setFontList(this.font);

      if (schema != null) {
        AttributeDescriptor[] attrs =
            schema.getAttributeDescriptors().toArray(new AttributeDescriptor[0]);
        List<String> list = new ArrayList<String>();
        for (int i = 0; i < attrs.length; i++) {
          Class cls = attrs[i].getType().getBinding();
          if (String.class.isAssignableFrom(cls)) {
            list.add(attrs[i].getName().getLocalPart());
          } else if (Number.class.isAssignableFrom(cls)) {
            list.add(attrs[i].getName().getLocalPart());
          }
        }
        this.field.removeAll();
        this.field.setItems(list.toArray(new String[0]));
        if (this.labelType == null) {
          this.field.select(0);
        } else {
          this.field.setText(this.labelType);
        }
      }

      this.on.setSelection(this.enabled);
      this.field.setEnabled(this.enabled);
      this.fonter.setEnabled(this.enabled);

      if (schema != null && (SLD.isLine(schema) == pointPlacement || this.place == null)) {
        pointPlacement = !SLD.isLine(schema);
        if (pointPlacement) {
          initPlacementContentsPoint();
        } else {
          initPlacementContentsLine();
        }
      }
      this.place.setEnabled(this.enabled);
      if (pointPlacement) {
        // PointPlacement
        this.place2.setEnabled(this.enabled);
        this.place3.setEnabled(this.enabled);
        if (this.labelPlacement == null || !(this.labelPlacement instanceof PointPlacement)) {
          // defaults
          if (mode == Mode.POINT) {
            // don't cover the point!
            this.place.select(2); // top
            this.place2.select(2); // right
          } else {
            this.place.select(1); // middle
            this.place2.select(1); // center
          }
          this.place3.select(0); // 0 degrees rotation
        } else {
          AnchorPoint anchor = ((PointPlacement) labelPlacement).getAnchorPoint();
          String anchorX = anchor.getAnchorPointX().toString();
          String anchorY = anchor.getAnchorPointY().toString();
          // use labels if 0, 0.5, or 1, otherwise use value for align
          if (anchorX.equals(Double.toString(SLDs.ALIGN_LEFT))) {
            this.place2.select(0);
          } else if (anchorX.equals(Double.toString(SLDs.ALIGN_CENTER))) {
            this.place2.select(1);
          } else if (anchorX.equals(Double.toString(SLDs.ALIGN_RIGHT))) {
            this.place2.select(2);
          } else {
            this.place2.setText(anchorX);
          }
          if (anchorY.equals(Double.toString(SLDs.ALIGN_BOTTOM))) {
            this.place.select(0);
          } else if (anchorY.equals(Double.toString(SLDs.ALIGN_MIDDLE))) {
            this.place.select(1);
          } else if (anchorY.equals(Double.toString(SLDs.ALIGN_TOP))) {
            this.place.select(2);
          } else {
            this.place.setText(anchorY);
          }
          // rotation
          this.place3.setText(((PointPlacement) labelPlacement).getRotation().toString());
        }
      } else {
        // LinePlacement
        if (this.labelPlacement == null || !(this.labelPlacement instanceof LinePlacement)) {
          // defaults
          this.place.setText(
              ProjectPlugin.getPlugin()
                  .getPreferenceStore()
                  .getString(PreferenceConstants.P_STYLE_DEFAULT_PERPENDICULAR_OFFSET));
        } else {
          String offset = ((LinePlacement) labelPlacement).getPerpendicularOffset().toString();
          this.place.setText(offset);
        }
      }
    } finally {
      listen(true);
    }
  }
  /**
   * Constructs a TextSymbolizer from the inputs
   *
   * @param build
   * @return TextSymbolizer defined by this model
   */
  public TextSymbolizer get(StyleBuilder build) {
    if (!this.enabled) {
      return null;
    }
    if (this.font == null || this.font.length == 0) {
      return null;
    }
    if (this.labelType == null || "".equals(this.labelType)) { // $NON-NLS-1$
      return null;
    }

    String fontName = this.font[0].getName();
    boolean fontBold = (this.font[0].getStyle() == SWT.BOLD);
    boolean fontItalic = (this.font[0].getStyle() == SWT.ITALIC);
    double fontSize = this.font[0].getHeight();
    Font gtFont = build.createFont(fontName, fontItalic, fontBold, fontSize);
    Fill fill = build.createFill(this.colour);

    LabelPlacement placement;
    if (pointPlacement) {
      // PointPlacement
      double horiz;
      if (this.place.getSelectionIndex() < 3) {
        switch (this.place.getSelectionIndex()) {
          case 0:
            horiz = SLDs.ALIGN_LEFT;
            break;
          case 1:
            horiz = SLDs.ALIGN_CENTER;
            break;
          case 2:
            horiz = SLDs.ALIGN_RIGHT;
            break;

          default:
            horiz = SLDs.ALIGN_CENTER;
            break;
        }
      } else { // custom value
        horiz = Double.parseDouble(this.place.getText());
      }

      double vert;
      if (this.place2.getSelectionIndex() < 3) {
        switch (this.place2.getSelectionIndex()) {
          case 0:
            vert = SLDs.ALIGN_BOTTOM;
            break;
          case 1:
            vert = SLDs.ALIGN_MIDDLE;
            break;
          case 2:
            vert = SLDs.ALIGN_TOP;
            break;

          default:
            vert = SLDs.ALIGN_MIDDLE;
            break;
        }
      } else { // custom value
        vert = Double.parseDouble(this.place2.getText());
      }

      double rotation = Double.parseDouble(this.place3.getText());

      placement = build.createPointPlacement(vert, horiz, rotation);
    } else {
      // LinePlacement
      double offset = Double.parseDouble(this.place.getText());
      placement = build.createLinePlacement(offset);
    }
    this.labelPlacement = placement;

    Expression exp =
        (Expression)
            CommonFactoryFinder.getFilterFactory(GeoTools.getDefaultHints())
                .property(this.labelType);
    TextSymbolizer text =
        build.createTextSymbolizer(fill, new Font[] {gtFont}, null, exp, placement, null);
    if (SLD.isLine(this.schema)) {
      text.addToOptions("group", "yes"); // $NON-NLS-1$ //$NON-NLS-2$
    }
    text.addToOptions("spaceAround", "2"); // $NON-NLS-1$ //$NON-NLS-2$
    return text;
  }