know
know

Reputation: 3

How to validate more `org.eclipse.jface.preference.StringFieldEditor` instances at one preference page?

At my FieldEditorPreferencePage I do create two instances of FileFieldEditor, one for ground texture setting, another for background texture setting:

public class PrefPage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage
{
  final int MAX_NR_COLUMNS = 3;
  private List<FieldEditor> fields = null;
  
  public PrefPage() {
    super(GRID);
    setPreferenceStore(Activator.getDefault().getPreferenceStore());
  }

  @Override
  protected void createFieldEditors()
  {
    Composite fieldEditorParent = getFieldEditorParent();
    //types allowed for Ground and Background texture
    String[] pictureTypesAllowed = {"jpg","jpeg","png"};
    String[] pictureTypesAllowedC = new String[]{"*.jpg;*.jpeg;*.png"};
    
    // some settings
    
    // ground settings
    Group envGroup = new Group(fieldEditorParent, SWT.NULL);
    envGroup.setText("Ground");
    envGroup.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, true, false, MAX_NR_COLUMNS, 1));
    ComboFieldEditor envControlFE = new ComboFieldEditor(PrefRayConstants.P_RT_GROUND, "Type") PrefRayConstants.GROUND_TYPES, envGroup);
    addField(envControlFE);
    
    CustomFileFieldEditor txtrControlFE = new CustomFileFieldEditor(PrefRayConstants.P_RT_GROUND_TEXTURE, 
        "Texture", 
        envGroup,
        pictureTypesAllowed); 
    txtrControlFE.setFileExtensions(pictureTypesAllowedC);//allow only those file types
    addField(txtrControlFE);
    
    // background settings
    Group bgGroup = new Group(fieldEditorParent, SWT.NULL);
    bgGroup.setText("Background");
    bgGroup.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, true, false, MAX_NR_COLUMNS, 1));
    FileFieldEditor bgTxtrControlFE = new CustomFileFieldEditor(PrefRayConstants.P_RT_BG_TEXTURE, 
        "Texture", 
        bgGroup,
        pictureTypesAllowed); 
    bgTxtrControlFE.setFileExtensions(pictureTypesAllowedC);//allow only those file types
    addField(bgTxtrControlFE);
  }
  
  @Override
  protected void performApply() {
    super.performApply();
    //Viewer.showReloadRestartMessage(this.getShell());
  }
  
  @Override
  public boolean performOk() {
    boolean bol = super.performOk();
    /*Viewer.showReloadRestartMessage(Activator.getDefault().getWorkbench().getActiveWorkbenchWindow().getShell());
    if (Viewer.getActiveViewer()!=null)
      Viewer.getActiveViewer().setRayLocalSettings();*/
    return bol;
  }

}

My problem is:

  1. if ground texture path is wrong - error message appears > correct
  2. set focus (mouse cursor) to background texture field and and back to ground texture - error message disappears, because only background texture field is validated (fired by focus lost event from StringFieldEditor.getTextControl) > WRONG!!!

Another scenario:

  1. if ground texture path is wrong - error message appears > correct
  2. set wrong value to background texture path - error message appears > correct
  3. delete background texture path - empty string is allowed - error message disappears, but there is no error message for ground path > WRONG!!!

Note: whole page is validated correctly by FieldEditorPreferencePage.checkState.

My question is: is there something built in Eclipse, what did I miss? If not, what would be better approach: customize StringFieldEditor.checkState (add some validation for all fields) or validate somehow at preference page?

My custom FileFieldEditor:

public class CustomFileFieldEditor extends FileFieldEditor
{
  private List<String> allowedExtensions = null;
  private boolean enableValidation = true;

  public CustomFileFieldEditor(String name, String labelText, Composite parent)
  {
    //this(name, labelText, parent, true);
    init(name, labelText);
    setErrorMessage(JFaceResources.getString("FileFieldEditor.errorMessage"));
    setValidateStrategy(VALIDATE_ON_KEY_STROKE);
    createControl(parent);
  }
  
  public CustomFileFieldEditor(String name, String labelText, Composite parent, String[] allowedExtensions)
  {
    // this(name, labelText, parent, true);
    init(name, labelText);
    setErrorMessage(JFaceResources.getString("FileFieldEditor.errorMessage"));
    setValidateStrategy(VALIDATE_ON_KEY_STROKE);
    createControl(parent);
    this.allowedExtensions  = Arrays.asList(allowedExtensions);
  }

  
  public CustomFileFieldEditor(String name, String labelText, Composite parent, boolean enableValidation)
  {
    //super(name, labelText, parent);
    init(name, labelText);
    setErrorMessage(JFaceResources.getString("FileFieldEditor.errorMessage"));
    enableValidation(enableValidation);
    //setEmptyStringAllowed(!enableValidation);
    setValidateStrategy(VALIDATE_ON_KEY_STROKE);
    createControl(parent);
  }
  
  public void enableValidation(boolean enableValidation)
  {
    this.enableValidation = enableValidation;
  }

  @Override
  protected boolean doCheckState() {
    return super.doCheckState();
  }
  
  @Override
  protected boolean checkState()
  {
    return super.checkState();

  }
  
  public void valueChanged() {
    super.valueChanged();
  }
  
  // prepared method
  private boolean isSuffixAllowed(String txt)
  {
    if (allowedExtensions == null)
      return true;

      if (!allowedExtensions.isEmpty())
        for (String suffix : allowedExtensions)
          if (txt.endsWith(suffix))
            return true;

    return false;
  }
  
  @Override
  public boolean isValid()
  {
    return super.isValid();
  }
    
}

Upvotes: 0

Views: 77

Answers (1)

know
know

Reputation: 3

As a hot fix I disabled all error messages fired by FileFieldEditor and only FieldEditorPreferencePage handles those.

In CustomFileFieldEditor:

  @Override
  protected void clearErrorMessage()
  {
    // only FieldEditorPreferencePage should handle error messages
    //if (page != null)
    //  page.setErrorMessage(null);
  }
  
  @Override
  public void setErrorMessage(String message)
  {
    // only FieldEditorPreferencePage should handle error messages
    //errorMessage = message;
  }

In PrefPage:

  @Override
  protected void checkState()
  {
    // super.checkState();
    boolean valid = true;
    invalidFieldEditor = null;
    // The state can only be set to true if all
    // field editors contain a valid value. So we must check them all
    if (fields != null)
    {
      int size = fields.size();
      for (int i = 0; i < size; i++)
      {
        FieldEditor editor = fields.get(i);
        valid = valid && editor.isValid();
        if (!valid)
        {
          if (editor instanceof CustomDirectoryFieldEditor)
          {
            // if should not be validated
            if (!((CustomDirectoryFieldEditor) editor).getEnableValidation())
            {
              valid = true;
              break;
            }
          }
          invalidFieldEditor = editor;
          break;
        }
        // validate extensions for all file fields
        if (editor instanceof CustomFileFieldEditor && !((CustomFileFieldEditor) editor).getStringValue().isEmpty())
        {
          validFileType = false;
          if (((CustomFileFieldEditor) editor).isFileType())
            validFileType = true;

          valid = valid && validFileType;
          if (!valid)
          {
            invalidFieldEditor = editor;
            break;
          }
        }
      }
    }

    setValid(valid);
  }

As @greg-449 mentioned in comment, I will consider to rework whole preference page with SWT controls.

Upvotes: 0

Related Questions