/** Private method, fiducial has been updated */
  private void updated() {
    AbstractShape component = FiducialRegistry.getInstance().getFiducialComponent(EventID);

    if (component != null) {
      component.setPositionGlobal(event.getPosition());
      float oldAngle = (Float) component.getUserData("angle"); // retrieve the "old" angle
      float newAngle = event.getAngle();
      if (oldAngle != newAngle) {
        float diff = newAngle + oldAngle;
        component.setUserData("angle", newAngle);
        diff = MTApplication.degrees(diff); // our rotation expects degrees (not radians)
        component.rotateZ(component.getCenterPointRelativeToParent(), diff);
      }
    }
  }
  public FiducialHandler_Search(MTApplication mtApp, MTCanvas mtc, MTInputEvent inEvt) {
    app = mtApp;
    canvas = mtc;

    event = (MTFiducialInputEvt) inEvt;
    EventID = event.getFiducialId();

    switch (event.getId()) {
      case MTFiducialInputEvt.INPUT_STARTED:
        started();
        break;
      case MTFiducialInputEvt.INPUT_ENDED:
        ended();
        break;
      case MTFiducialInputEvt.INPUT_UPDATED:
        updated();
        break;
    }
  }
  // Global input processor listener implementation (IMTInputEventListener)
  public boolean processInputEvent(MTInputEvent inEvt) {
    if (inEvt instanceof MTFiducialInputEvt) {
      MTFiducialInputEvt fEvt = (MTFiducialInputEvt) inEvt;
      int fID = fEvt.getFiducialId();
      Vector3D position = fEvt.getPosition();

      AbstractShape comp;
      switch (fEvt.getId()) {
        case MTFiducialInputEvt.INPUT_STARTED:
          // Create a new component for the fiducial
          AbstractShape newComp = createComponent(fID, position);
          fiducialIDToComp.put(fID, newComp); // Map id to component
          // Move component to fiducial position
          newComp.setPositionGlobal(position);
          // Save the absolute rotation angle in the component for late
          newComp.setUserData("angle", fEvt.getAngle());
          // Rotate the component
          newComp.rotateZ(
              newComp.getCenterPointRelativeToParent(),
              AbstractMTApplication.degrees(fEvt.getAngle()));
          // Add the component to the canvas to draw it
          getCanvas().addChild(newComp);
          break;
        case MTFiducialInputEvt.INPUT_UPDATED:
          // Retrieve the corresponding component for the fiducial ID from the map
          comp = fiducialIDToComp.get(fID);
          if (comp != null) {
            // Set the new position
            comp.setPositionGlobal(position);
            // Set the rotation (we have to do a little more here because
            // mt4j does incremental rotations instead of specifying an absolute angle)
            float oldAngle = (Float) comp.getUserData("angle"); // retrieve the "old" angle
            float newAngle = fEvt.getAngle();
            if (oldAngle != newAngle) {
              float diff = newAngle - oldAngle;
              comp.setUserData("angle", newAngle);
              diff =
                  AbstractMTApplication.degrees(diff); // our rotation expects degrees (not radians)
              comp.rotateZ(comp.getCenterPointRelativeToParent(), diff);
            }
          }
          break;
        case MTFiducialInputEvt.INPUT_ENDED:
          comp = fiducialIDToComp.get(fID);
          if (comp != null) {
            comp.destroy();
            fiducialIDToComp.remove(fID);
          }
          break;
        default:
          break;
      }
    }
    return false;
  }
  /** Private method, handle a new fiducial */
  private void started() {
    AbstractShape roundingcircle =
        new MTEllipse(app, new Vector3D(event.getPosition()), 180, 180, 100);
    roundingcircle.setNoFill(false);
    float r = ToolsMath.getRandom(20, 255);
    float g = ToolsMath.getRandom(20, 255);
    float b = ToolsMath.getRandom(20, 255);
    roundingcircle.setFillColor(new MTColor(r, g, b, 200));
    roundingcircle.setNoStroke(false);
    roundingcircle.setStrokeWeight(1);
    roundingcircle.setStrokeColor(new MTColor(r, g, b, 200));
    roundingcircle.unregisterAllInputProcessors();

    AbstractShape component = new MTEllipse(app, new Vector3D(event.getPosition()), 20, 20, 20);
    component.setNoFill(false);
    float r1 = ToolsMath.getRandom(20, 255);
    float g1 = ToolsMath.getRandom(20, 255);
    float b1 = ToolsMath.getRandom(20, 255);
    component.setFillColor(new MTColor(r1, g1, b1, 200));
    component.setNoStroke(false);
    component.setStrokeWeight(1);
    component.setStrokeColor(new MTColor(r1, g1, b1, 200));
    component.unregisterAllInputProcessors(); // Dont process input/gestures on this component

    roundingcircle.addChild(component);

    MTColor white = new MTColor(255, 255, 255);

    IFont fontArial = FontManager.getInstance().createFont(app, "arial.ttf", 50, white);

    MTTextArea text = new MTTextArea(app, fontArial);
    text.setFillColor(new MTColor(0, 0, 0, 0));
    text.setStrokeColor(new MTColor(0, 0, 0, 0));
    text.unregisterAllInputProcessors();
    roundingcircle.addChild(text);
    text.setPositionRelativeToParent(
        new Vector3D(event.getPosition().x, event.getPosition().y - 120));

    roundingcircle.setUserData("angle", event.getAngle());

    MTKeyboard keys = KeyboardPool.getInstance(app).getKeyboard();
    roundingcircle.addChild(keys);
    keys.setPositionRelativeToParent(
        new Vector3D(event.getPosition().x, event.getPosition().y + 150));
    keys.setUserData("fiducialID", EventID);

    text.setExpandDirection(ExpandDirection.UP);
    text.unregisterAllInputProcessors();
    /*
     * Need to find a way to keep the text centred at all times.
     */
    // text.setEnableCaret(true);

    keys.addTextInputListener(text);
    keys.addInputListener(text);

    FiducialRegistry.getInstance().putFiducialCompoent(EventID, roundingcircle);

    String searchTerm = "Doctor Who";
    TwitterSearch twsearch = new TwitterSearch();
    twsearch.search(searchTerm);

    canvas.addChild(roundingcircle);
  }