public Canvas getSearchCanvas() {
    final VLayout mainLayout = new VLayout(20);
    mainLayout.setWidth100();
    mainLayout.setHeight100();
    mainLayout.setPadding(5);

    Label titleBar = new Label(MESSAGES.geometricSearchWidgetFreeDrawingSearchTitle());
    titleBar.setBackgroundColor("#E0E9FF");
    titleBar.setWidth100();
    titleBar.setHeight(20);
    titleBar.setPadding(5);

    HLayout geomsButtonBar = new HLayout();
    geomsButtonBar.setWidth100();
    geomsButtonBar.setAutoHeight();
    geomsButtonBar.setMembersMargin(10);
    HLayout actionsButtonBar = new HLayout();
    actionsButtonBar.setWidth100();
    actionsButtonBar.setAutoHeight();
    actionsButtonBar.setMembersMargin(10);

    btnPoint = new IButton(MESSAGES.geometricSearchWidgetFreeDrawingPoint());
    btnPoint.setIcon(WidgetLayout.iconPointCreate);
    btnPoint.setWidth(
        btnPoint.getTitle().length() * GsfLayout.buttonFontWidth + GsfLayout.buttonOffset);
    btnPoint.setActionType(SelectionType.RADIO);
    btnPoint.setRadioGroup("drawType");
    btnPoint.addClickHandler(
        new ClickHandler() {
          public void onClick(ClickEvent event) {
            onDrawPoint();
          }
        });

    btnLine = new IButton(MESSAGES.geometricSearchWidgetFreeDrawingLine());
    btnLine.setIcon(WidgetLayout.iconLineCreate);
    btnLine.setWidth(
        btnLine.getTitle().length() * GsfLayout.buttonFontWidth + GsfLayout.buttonOffset);
    btnLine.setActionType(SelectionType.RADIO);
    btnLine.setRadioGroup("drawType");
    btnLine.addClickHandler(
        new ClickHandler() {
          public void onClick(ClickEvent event) {
            onDrawLine();
          }
        });

    btnPolygon = new IButton(MESSAGES.geometricSearchWidgetFreeDrawingPolygon());
    btnPolygon.setIcon(WidgetLayout.iconPolygonCreate);
    btnPolygon.setWidth(
        btnPolygon.getTitle().length() * GsfLayout.buttonFontWidth + GsfLayout.buttonOffset);
    btnPolygon.setActionType(SelectionType.RADIO);
    btnPolygon.setRadioGroup("drawType");
    btnPolygon.addClickHandler(
        new ClickHandler() {
          public void onClick(ClickEvent event) {
            onDrawPolygon();
          }
        });

    btnUndo = new IButton(MESSAGES.geometricSearchWidgetFreeDrawingUndo());
    btnUndo.setIcon(WidgetLayout.iconUndo);
    btnUndo.setWidth(
        btnUndo.getTitle().length() * GsfLayout.buttonFontWidth + GsfLayout.buttonOffset);
    btnUndo.setDisabled(true);
    btnUndo.setShowDisabledIcon(false);
    btnUndo.addClickHandler(
        new ClickHandler() {
          public void onClick(ClickEvent event) {
            onUndo();
          }
        });

    btnRedo = new IButton(MESSAGES.geometricSearchWidgetFreeDrawingRedo());
    btnRedo.setIcon(WidgetLayout.iconRedo);
    btnRedo.setWidth(
        btnRedo.getTitle().length() * GsfLayout.buttonFontWidth + GsfLayout.buttonOffset);
    btnRedo.setDisabled(true);
    btnRedo.setShowDisabledIcon(false);
    btnRedo.addClickHandler(
        new ClickHandler() {
          public void onClick(ClickEvent event) {
            onRedo();
          }
        });

    frmBuffer = new DynamicForm();
    frmBuffer.setWidth100();
    spiBuffer = new SpinnerItem();
    spiBuffer.setTitle(MESSAGES.geometricSearchWidgetBufferLabel());
    spiBuffer.setDefaultValue(5);
    spiBuffer.setMin(0);
    spiBuffer.setWidth(60);
    spiBuffer.addChangedHandler(
        new ChangedHandler() {
          public void onChanged(ChangedEvent event) {
            updateView();
          }
        });
    frmBuffer.setFields(spiBuffer);

    // ----------------------------------------------------------

    geomsButtonBar.addMember(btnPoint);
    geomsButtonBar.addMember(btnLine);
    geomsButtonBar.addMember(btnPolygon);

    actionsButtonBar.addMember(btnUndo);
    actionsButtonBar.addMember(btnRedo);

    mainLayout.addMember(titleBar);
    mainLayout.addMember(geomsButtonBar);
    mainLayout.addMember(actionsButtonBar);
    mainLayout.addMember(frmBuffer);

    return mainLayout;
  }
  private void build() {
    final VLayout layout = new VLayout();
    layout.setMargin(5);

    final VStack infraLayout = new VStack();
    infraLayout.setHeight(26);
    final Label infraLabel = new Label("Updating available Infrastructures and Policies");
    infraLabel.setIcon("loading.gif");
    infraLabel.setHeight(26);
    infraLabel.setAlign(Alignment.CENTER);
    infraLayout.addMember(infraLabel);

    final DynamicForm infraForm = new DynamicForm();
    infraForm.setEncoding(Encoding.MULTIPART);
    infraForm.setMethod(FormMethod.POST);
    infraForm.setAction(GWT.getModuleBaseURL() + "createnodesource");
    infraForm.setTarget("__hiddenFrame");

    infraLayout.addMember(infraForm);

    final Label label =
        new Label(
            "A Node Source is a combination of an Infrastructure, which defines how resources"
                + " will be acquired, and a Policy, that dictates when resources can be acquired.");
    label.setHeight(40);

    final HashMap<String, List<FormItem>> allForms = new HashMap<String, List<FormItem>>();

    controller.fetchSupportedInfrastructuresAndPolicies(
        new Runnable() {
          public void run() {

            infraSelect = new SelectItem("infra", "Infrastructure");
            infraSelect.setRequired(true);
            policySelect = new SelectItem("policy", "Policy");
            policySelect.setRequired(true);

            infraSelect.setWidth(300);
            policySelect.setWidth(300);

            HiddenItem name = new HiddenItem("nsName");
            HiddenItem callback = new HiddenItem("nsCallback");
            HiddenItem session = new HiddenItem("sessionId");

            ArrayList<FormItem> tmpAll = new ArrayList<FormItem>();
            tmpAll.add(name);
            tmpAll.add(callback);
            tmpAll.add(session);
            tmpAll.add(infraSelect);

            LinkedHashMap<String, String> values = new LinkedHashMap<String, String>();
            for (PluginDescriptor inf :
                controller.getModel().getSupportedInfrastructures().values()) {
              String shortName =
                  inf.getPluginName().substring(inf.getPluginName().lastIndexOf('.') + 1);
              values.put(inf.getPluginName(), shortName);

              List<Field> configurableFields = inf.getConfigurableFields();
              ArrayList<FormItem> forms = new ArrayList<FormItem>(configurableFields.size());
              for (Field f : configurableFields) {
                FormItem infra = null;
                if (f.isPassword()) {
                  infra = new PasswordItem(inf.getPluginName() + f.getName(), f.getName());
                } else if (f.isFile() || f.isCredential()) {
                  infra = new UploadItem(inf.getPluginName() + f.getName(), f.getName());
                  if (f.isCredential()) {
                    PickerIcon cred =
                        new PickerIcon(
                            new Picker(Images.instance.key_16().getSafeUri().asString()),
                            new FormItemClickHandler() {
                              @Override
                              public void onFormItemClick(FormItemIconClickEvent event) {
                                CredentialsWindow win = new CredentialsWindow();
                                win.show();
                              }
                            });
                    cred.setPrompt("Create a Credential file");
                    cred.setWidth(16);
                    cred.setHeight(16);
                    cred.setAttribute("hspace", 6);
                    infra.setIcons(cred);
                  }
                } else {
                  infra = new TextItem(inf.getPluginName() + f.getName(), f.getName());
                }
                infra.setValue(f.getValue());
                infra.setWidth(250);
                infra.setHint("<nobr>" + f.getDescription() + "</nobr>");
                forms.add(infra);
                tmpAll.add(infra);
              }
              allForms.put(inf.getPluginName(), forms);
            }
            infraSelect.setValueMap(values);

            tmpAll.add(new SpacerItem());
            values.clear();
            tmpAll.add(policySelect);
            for (PluginDescriptor inf : controller.getModel().getSupportedPolicies().values()) {
              String shortName =
                  inf.getPluginName().substring(inf.getPluginName().lastIndexOf('.') + 1);
              values.put(inf.getPluginName(), shortName);

              List<Field> configurableFields = inf.getConfigurableFields();
              ArrayList<FormItem> forms = new ArrayList<FormItem>(configurableFields.size());
              for (Field f : configurableFields) {
                FormItem pol = null;
                if (f.isPassword()) {
                  pol = new PasswordItem(inf.getPluginName() + f.getName(), f.getName());
                } else if (f.isFile() || f.isCredential()) {
                  pol = new UploadItem(inf.getPluginName() + f.getName(), f.getName());
                  if (f.isCredential()) {
                    PickerIcon cred =
                        new PickerIcon(
                            new Picker(Images.instance.key_16().getSafeUri().asString()),
                            new FormItemClickHandler() {
                              @Override
                              public void onFormItemClick(FormItemIconClickEvent event) {
                                CredentialsWindow win = new CredentialsWindow();
                                win.show();
                              }
                            });
                    cred.setPrompt("Create a Credential file");
                    cred.setWidth(16);
                    cred.setHeight(16);
                    cred.setAttribute("hspace", 6);
                    pol.setIcons(cred);
                  }
                } else {
                  pol = new TextItem(inf.getPluginName() + f.getName(), f.getName());
                }
                pol.setValue(f.getValue());
                pol.setWidth(250);
                pol.setHint("<nobr>" + f.getDescription() + "</nobr>");
                forms.add(pol);
                tmpAll.add(pol);
              }
              allForms.put(inf.getPluginName(), forms);
            }
            policySelect.setValueMap(values);

            infraSelectChanged =
                new Runnable() {
                  @Override
                  public void run() {
                    if (policySelect.getValueAsString() == null) {
                      return;
                    }

                    String nsName = infraSelect.getValueAsString();
                    if (oldInfra != null) {
                      for (FormItem f : allForms.get(oldInfra)) {
                        f.hide();
                      }
                    }
                    for (FormItem f : allForms.get(nsName)) {
                      f.show();
                    }

                    if (oldInfra == null) {
                      oldInfra = nsName;
                      policySelectChanged.run();
                    } else {
                      oldInfra = nsName;
                    }
                  }
                };

            policySelectChanged =
                new Runnable() {
                  @Override
                  public void run() {
                    if (infraSelect.getValueAsString() == null) {
                      return;
                    }

                    String policy = policySelect.getValueAsString();
                    if (oldPolicy != null) {
                      for (FormItem f : allForms.get(oldPolicy)) {
                        f.hide();
                      }
                    }
                    for (FormItem f : allForms.get(policy)) {
                      f.show();
                    }

                    if (oldPolicy == null) {
                      oldPolicy = policy;
                      infraSelectChanged.run();
                    } else {
                      oldPolicy = policy;
                    }
                  }
                };

            infraSelect.addChangedHandler(
                new ChangedHandler() {
                  public void onChanged(ChangedEvent event) {
                    infraSelectChanged.run();
                  }
                });

            policySelect.addChangedHandler(
                new ChangedHandler() {
                  public void onChanged(ChangedEvent event) {
                    policySelectChanged.run();
                  }
                });

            infraForm.setFields(tmpAll.toArray(new FormItem[tmpAll.size()]));
            infraLabel.hide();
            infraForm.show();

            for (List<FormItem> li : allForms.values()) {
              for (FormItem it : li) {
                it.hide();
              }
            }
          }
        },
        new Runnable() {
          @Override
          public void run() {
            window.hide();
          }
        });

    final TextItem nameItem = new TextItem("nsName", "Name");
    DynamicForm nameForm = new DynamicForm();
    nameForm.setFields(nameItem);

    HLayout buttons = new HLayout();

    buttons.setWidth100();
    buttons.setHeight(22);
    buttons.setMargin(5);
    buttons.setAlign(Alignment.RIGHT);
    buttons.setMembersMargin(5);

    final IButton okButton = new IButton("Ok");
    okButton.setIcon(Images.instance.ok_16().getSafeUri().asString());
    okButton.setShowDisabledIcon(false);
    final IButton cancelButton = new IButton("Cancel");
    cancelButton.setIcon(Images.instance.cancel_16().getSafeUri().asString());
    cancelButton.setShowDisabledIcon(false);

    okButton.addClickHandler(
        new ClickHandler() {
          public void onClick(ClickEvent event) {
            infraForm.setValue("infra", infraSelect.getValueAsString());
            infraForm.setValue("nsName", nameItem.getValueAsString());
            infraForm.setValue("policy", policySelect.getValueAsString());
            infraForm.setValue("sessionId", LoginModel.getInstance().getSessionId());
            infraForm.setCanSubmit(true);

            /* this smartGWT form looks nice but cannot do callbacks ;
             * we register a native JS function to the document, send it to
             * the servlet so that it writes it back when returning
             * when the browser reads the return value and interprets it as JS,
             * the callback is called */
            infraForm.setValue(
                "nsCallback",
                JSUtil.register(
                    new JSUtil.JSCallback() {
                      public void execute(JavaScriptObject obj) {
                        JSONObject js = new JSONObject(obj);
                        if (js.containsKey("result")
                            && js.get("result").isBoolean().booleanValue()) {
                          window.hide();
                          LogModel.getInstance()
                              .logMessage(
                                  "Successfully created nodesource: "
                                      + nameItem.getValueAsString());
                        } else {
                          String msg;
                          if (js.get("errorMessage").isString() != null) {
                            msg = js.get("errorMessage").isString().stringValue();
                          } else {
                            msg = js.toString();
                          }
                          label.setContents(
                              "<span style='color:red'>Failed to create Node Source :<br>"
                                  + msg
                                  + "</span>");
                          LogModel.getInstance()
                              .logImportantMessage(
                                  "Failed to create nodesource "
                                      + nameItem.getValueAsString()
                                      + ": "
                                      + msg);
                          layout.scrollToTop();
                        }
                        infraLabel.hide();
                        infraForm.show();
                        okButton.setDisabled(false);
                        cancelButton.setDisabled(false);
                      }
                    }));
            infraForm.submitForm();

            cancelButton.setDisabled(true);
            okButton.setDisabled(true);

            infraLabel.setContents("Node Source creation requested...");
            infraLabel.show();
            infraForm.hide();
          }
        });
    cancelButton.addClickHandler(
        new ClickHandler() {
          public void onClick(ClickEvent event) {
            window.hide();
          }
        });
    buttons.setMembers(okButton, cancelButton);

    VLayout scroll = new VLayout();
    scroll.setHeight100();
    scroll.setWidth100();
    scroll.setMembers(infraLayout);
    scroll.setOverflow(Overflow.AUTO);
    scroll.setBorder("1px solid #ddd");
    scroll.setBackgroundColor("#fafafa");

    layout.addMember(label);
    layout.addMember(nameForm);
    layout.addMember(scroll);
    layout.addMember(buttons);

    int winWidth = com.google.gwt.user.client.Window.getClientWidth() * 80 / 100;
    int winHeight = com.google.gwt.user.client.Window.getClientHeight() * 80 / 100;
    winWidth = Math.min(1000, winWidth);
    winHeight = Math.min(1000, winHeight);

    this.window = new Window();
    this.window.setTitle("Create Node Source");
    this.window.setShowMinimizeButton(false);
    this.window.setIsModal(true);
    this.window.setShowModalMask(true);
    this.window.addItem(layout);
    this.window.setWidth(winWidth);
    this.window.setHeight(winHeight);
    this.window.setCanDragResize(true);
    this.window.setCanDragReposition(true);
    this.window.centerInPage();
  }