mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-22 22:22:11 +02:00
New Project Location area: full rework.
This commit is contained in:
parent
efe180944f
commit
733f00d3a8
4 changed files with 391 additions and 25 deletions
|
@ -19,5 +19,6 @@ Require-Bundle: org.eclipse.ui.ide;bundle-version="[3.2.0,4.0.0)",
|
|||
org.eclipse.core.variables;bundle-version="[3.1.100,4.0.0)",
|
||||
org.eclipse.ui.navigator;bundle-version="[3.2.0,4.0.0)";resolution:=optional,
|
||||
org.eclipse.cdt.make.core,
|
||||
org.eclipse.cdt.make.ui
|
||||
org.eclipse.cdt.make.ui,
|
||||
org.eclipse.core.filesystem
|
||||
Eclipse-LazyStart: true
|
||||
|
|
|
@ -90,12 +90,15 @@ CConfigWizardPage.12=Use "Advanced settings" button to edit project's properties
|
|||
CConfigWizardPage.13=Advanced settings...
|
||||
CMainWizardPage.0=Project types:
|
||||
CMainWizardPage.1=Show project types and toolchains only if they are supported on the platform
|
||||
CMainWizardPage.10=A project with that name already exists in the workspace.
|
||||
CMainWizardPage.2=Edit properties after project creation
|
||||
CMainWizardPage.3=No project types available. Project cannot be created
|
||||
CMainWizardPage.4=At least one toolchain should be selected \!
|
||||
CMainWizardPage.5=Cannot create ICProjectTypeHandler :
|
||||
CMainWizardPage.6=File with specified name already exists \!
|
||||
CMainWizardPage.7=Directory with specified name already exists \!
|
||||
CMainWizardPage.8=Project name:
|
||||
CMainWizardPage.9=Project name is empty
|
||||
WizardNewProjectCreationPage_nameLabel=
|
||||
WizardNewProjectCreationPage_projectNameEmpty=
|
||||
WizardNewProjectCreationPage_projectExistsMessage=
|
||||
|
@ -114,3 +117,14 @@ NewModelProjectWizard.3=Create C++ project of selected type
|
|||
NewModelProjectWizard.4=C project
|
||||
NewModelProjectWizard.5=Create C project of selected type
|
||||
StdBuildWizard.0=Makefile project
|
||||
ProjectContentsArea.0=Browse...
|
||||
ProjectContentsArea.1=Use default location
|
||||
ProjectContentsArea.2=Location:
|
||||
ProjectContentsArea.3=Choose file system:
|
||||
ProjectContentsArea.3=Invalid location path
|
||||
ProjectContentsArea.4=Project contents directory must be specified
|
||||
ProjectContentsArea.5=Select directory:
|
||||
ProjectContentsArea.6=Project path should be absolute
|
||||
ProjectContentsArea.7=Project path is not valid
|
||||
ProjectContentsArea.8=Cannot create given path
|
||||
ProjectContentsArea.9=File with given name already exists
|
||||
|
|
|
@ -16,6 +16,7 @@ import java.util.TreeSet;
|
|||
import org.eclipse.cdt.managedbuilder.core.IToolChain;
|
||||
import org.eclipse.cdt.managedbuilder.ui.properties.Messages;
|
||||
import org.eclipse.cdt.managedbuilder.ui.properties.PageLayout;
|
||||
import org.eclipse.cdt.managedbuilder.ui.wizards.ProjectContentsArea.IErrorMessageReporter;
|
||||
import org.eclipse.cdt.ui.newui.CDTPrefUtil;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.resources.IResource;
|
||||
|
@ -45,11 +46,6 @@ import org.eclipse.swt.widgets.Text;
|
|||
import org.eclipse.swt.widgets.Tree;
|
||||
import org.eclipse.swt.widgets.TreeItem;
|
||||
import org.eclipse.ui.PlatformUI;
|
||||
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
|
||||
import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
|
||||
import org.eclipse.ui.internal.ide.IIDEHelpContextIds;
|
||||
import org.eclipse.ui.internal.ide.dialogs.ProjectContentsLocationArea;
|
||||
import org.eclipse.ui.internal.ide.dialogs.ProjectContentsLocationArea.IErrorMessageReporter;
|
||||
|
||||
public class CMainWizardPage extends WizardPage implements IToolChainListListener {
|
||||
|
||||
|
@ -58,7 +54,7 @@ import org.eclipse.ui.internal.ide.dialogs.ProjectContentsLocationArea.IErrorMes
|
|||
public static final String CLASS_NAME = "class"; //$NON-NLS-1$
|
||||
|
||||
public static final String PAGE_ID = "org.eclipse.cdt.managedbuilder.ui.wizard.NewModelProjectWizardPage"; //$NON-NLS-1$
|
||||
|
||||
private static final String HELP_CTX = "org.eclipse.ui.ide.new_project_wizard_page_context"; //$NON-NLS-1$
|
||||
// initial value stores
|
||||
private String initialProjectFieldValue;
|
||||
|
||||
|
@ -79,7 +75,7 @@ import org.eclipse.ui.internal.ide.dialogs.ProjectContentsLocationArea.IErrorMes
|
|||
}
|
||||
};
|
||||
|
||||
private ProjectContentsLocationArea locationArea;
|
||||
private ProjectContentsArea locationArea;
|
||||
|
||||
// constants
|
||||
private static final int SIZING_TEXT_FIELD_WIDTH = 250;
|
||||
|
@ -103,15 +99,13 @@ import org.eclipse.ui.internal.ide.dialogs.ProjectContentsLocationArea.IErrorMes
|
|||
composite.setFont(parent.getFont());
|
||||
|
||||
initializeDialogUnits(parent);
|
||||
|
||||
PlatformUI.getWorkbench().getHelpSystem().setHelp(composite,
|
||||
IIDEHelpContextIds.NEW_PROJECT_WIZARD_PAGE);
|
||||
PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, HELP_CTX);
|
||||
|
||||
composite.setLayout(new GridLayout());
|
||||
composite.setLayoutData(new GridData(GridData.FILL_BOTH));
|
||||
|
||||
createProjectNameGroup(composite);
|
||||
locationArea = new ProjectContentsLocationArea(getErrorReporter(), composite);
|
||||
locationArea = new ProjectContentsArea(getErrorReporter(), composite);
|
||||
if(initialProjectFieldValue != null) {
|
||||
locationArea.updateProjectName(initialProjectFieldValue);
|
||||
}
|
||||
|
@ -180,25 +174,18 @@ import org.eclipse.ui.internal.ide.dialogs.ProjectContentsLocationArea.IErrorMes
|
|||
*/
|
||||
private IErrorMessageReporter getErrorReporter() {
|
||||
return new IErrorMessageReporter(){
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.ui.internal.ide.dialogs.ProjectContentsLocationArea.IErrorMessageReporter#reportError(java.lang.String)
|
||||
*/
|
||||
public void reportError(String errorMessage) {
|
||||
setErrorMessage(errorMessage);
|
||||
boolean valid = errorMessage == null;
|
||||
if(valid) {
|
||||
valid = validatePage();
|
||||
}
|
||||
|
||||
if(valid) valid = validatePage();
|
||||
setPageComplete(valid);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public IWizardPage getNextPage() {
|
||||
if (h_selected == null || h_selected.isDummy()) // cannot continue
|
||||
return null;
|
||||
// MBSCustomPageManager.setPageHideStatus(next.pageID, false);
|
||||
return next;
|
||||
}
|
||||
/**
|
||||
|
@ -216,7 +203,7 @@ import org.eclipse.ui.internal.ide.dialogs.ProjectContentsLocationArea.IErrorMes
|
|||
|
||||
// new project label
|
||||
Label projectLabel = new Label(projectGroup, SWT.NONE);
|
||||
projectLabel.setText(IDEWorkbenchMessages.WizardNewProjectCreationPage_nameLabel);
|
||||
projectLabel.setText(Messages.getString("CMainWizardPage.8")); //$NON-NLS-1$
|
||||
projectLabel.setFont(parent.getFont());
|
||||
|
||||
// new project name entry field
|
||||
|
@ -323,12 +310,12 @@ import org.eclipse.ui.internal.ide.dialogs.ProjectContentsLocationArea.IErrorMes
|
|||
* <code>false</code> if at least one is invalid
|
||||
*/
|
||||
protected boolean validatePage() {
|
||||
IWorkspace workspace = IDEWorkbenchPlugin.getPluginWorkspace();
|
||||
IWorkspace workspace = ResourcesPlugin.getWorkspace();
|
||||
setMessage(null);
|
||||
|
||||
String projectFieldContents = getProjectNameFieldValue();
|
||||
if (projectFieldContents.length() == 0) {
|
||||
setErrorMessage(IDEWorkbenchMessages.WizardNewProjectCreationPage_projectNameEmpty);
|
||||
setErrorMessage(Messages.getString("CMainWizardPage.9")); //$NON-NLS-1$
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -349,7 +336,7 @@ import org.eclipse.ui.internal.ide.dialogs.ProjectContentsLocationArea.IErrorMes
|
|||
bad = false;
|
||||
}
|
||||
if (bad) {
|
||||
setErrorMessage(IDEWorkbenchMessages.WizardNewProjectCreationPage_projectExistsMessage);
|
||||
setErrorMessage(Messages.getString("CMainWizardPage.10")); //$NON-NLS-1$
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,364 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2005, 2007 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
* Intel corporation - cloned to CDT UI, to avoid discouraged access
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.managedbuilder.ui.wizards;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import org.eclipse.cdt.managedbuilder.ui.properties.Messages;
|
||||
import org.eclipse.cdt.ui.newui.AbstractPage;
|
||||
import org.eclipse.core.filesystem.URIUtil;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.resources.ResourcesPlugin;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Path;
|
||||
import org.eclipse.core.runtime.Platform;
|
||||
import org.eclipse.osgi.util.TextProcessor;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.events.ModifyEvent;
|
||||
import org.eclipse.swt.events.ModifyListener;
|
||||
import org.eclipse.swt.events.SelectionAdapter;
|
||||
import org.eclipse.swt.events.SelectionEvent;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.layout.GridLayout;
|
||||
import org.eclipse.swt.widgets.Button;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.DirectoryDialog;
|
||||
import org.eclipse.swt.widgets.Label;
|
||||
import org.eclipse.swt.widgets.Text;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class ProjectContentsArea {
|
||||
private static final String ERROR_INVALID_PATH = Messages.getString("ProjectContentsArea.3"); //$NON-NLS-1$
|
||||
private static final String ERROR_PATH_EMPTY = Messages.getString("ProjectContentsArea.4"); //$NON-NLS-1$
|
||||
private static final String ERROR_NOT_ABSOLUTE = Messages.getString("ProjectContentsArea.6"); //$NON-NLS-1$
|
||||
private static final String ERROR_NOT_VALID = Messages.getString("ProjectContentsArea.7"); //$NON-NLS-1$
|
||||
private static final String ERROR_CANNOT_CREATE = Messages.getString("ProjectContentsArea.8"); //$NON-NLS-1$
|
||||
private static final String ERROR_FILE_EXISTS = Messages.getString("ProjectContentsArea.9"); //$NON-NLS-1$
|
||||
|
||||
private static final String BROWSE_LABEL = Messages.getString("ProjectContentsArea.0"); //$NON-NLS-1$
|
||||
private static final int SIZING_TEXT_FIELD_WIDTH = 250;
|
||||
private static final String FILE_SCHEME = "file"; //$NON-NLS-1$
|
||||
private Label locationLabel;
|
||||
private Text locationPathField;
|
||||
private Button browseButton;
|
||||
private IErrorMessageReporter errorReporter;
|
||||
private String projectName = AbstractPage.EMPTY_STR;
|
||||
private String userPath = AbstractPage.EMPTY_STR;
|
||||
private Button useDefaultsButton;
|
||||
private IProject existingProject;
|
||||
|
||||
/**
|
||||
* Create a new instance of a ProjectContentsLocationArea.
|
||||
*
|
||||
* @param composite
|
||||
*/
|
||||
public ProjectContentsArea(IErrorMessageReporter er, Composite composite) {
|
||||
errorReporter = er;
|
||||
createContents(composite, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the contents of the receiver.
|
||||
*
|
||||
* @param composite
|
||||
* @param defaultEnabled
|
||||
*/
|
||||
private void createContents(Composite composite, boolean defaultEnabled) {
|
||||
// project specification group
|
||||
Composite projectGroup = new Composite(composite, SWT.NONE);
|
||||
GridLayout layout = new GridLayout();
|
||||
layout.numColumns = 4;
|
||||
projectGroup.setLayout(layout);
|
||||
projectGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
|
||||
|
||||
useDefaultsButton = new Button(projectGroup, SWT.CHECK | SWT.RIGHT);
|
||||
useDefaultsButton.setText(Messages.getString("ProjectContentsArea.1")); //$NON-NLS-1$
|
||||
useDefaultsButton.setSelection(defaultEnabled);
|
||||
GridData buttonData = new GridData();
|
||||
buttonData.horizontalSpan = 4;
|
||||
useDefaultsButton.setLayoutData(buttonData);
|
||||
|
||||
createUserEntryArea(projectGroup, defaultEnabled);
|
||||
|
||||
useDefaultsButton.addSelectionListener(new SelectionAdapter() {
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
boolean useDefaults = useDefaultsButton.getSelection();
|
||||
|
||||
if (useDefaults) {
|
||||
userPath = locationPathField.getText();
|
||||
locationPathField.setText(TextProcessor
|
||||
.process(getDefaultPathDisplayString()));
|
||||
} else {
|
||||
locationPathField.setText(TextProcessor.process(userPath));
|
||||
}
|
||||
setUserAreaEnabled(!useDefaults);
|
||||
}
|
||||
});
|
||||
setUserAreaEnabled(!defaultEnabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether or not we are currently showing the default location for
|
||||
* the project.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean isDefault() {
|
||||
return useDefaultsButton.getSelection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the area for user entry.
|
||||
*
|
||||
* @param composite
|
||||
* @param defaultEnabled
|
||||
*/
|
||||
private void createUserEntryArea(Composite composite, boolean defaultEnabled) {
|
||||
// location label
|
||||
locationLabel = new Label(composite, SWT.NONE);
|
||||
locationLabel.setText(Messages.getString("ProjectContentsArea.2")); //$NON-NLS-1$
|
||||
|
||||
// project location entry field
|
||||
locationPathField = new Text(composite, SWT.BORDER);
|
||||
GridData data = new GridData(GridData.FILL_HORIZONTAL);
|
||||
data.widthHint = SIZING_TEXT_FIELD_WIDTH;
|
||||
data.horizontalSpan = 2;
|
||||
locationPathField.setLayoutData(data);
|
||||
|
||||
// browse button
|
||||
browseButton = new Button(composite, SWT.PUSH);
|
||||
browseButton.setText(BROWSE_LABEL);
|
||||
browseButton.addSelectionListener(new SelectionAdapter() {
|
||||
public void widgetSelected(SelectionEvent event) {
|
||||
handleLocationBrowseButtonPressed();
|
||||
}
|
||||
});
|
||||
|
||||
if (defaultEnabled) {
|
||||
locationPathField.setText(TextProcessor
|
||||
.process(getDefaultPathDisplayString()));
|
||||
} else {
|
||||
if (existingProject == null) {
|
||||
locationPathField.setText(AbstractPage.EMPTY_STR);
|
||||
} else {
|
||||
locationPathField.setText(TextProcessor.process(existingProject
|
||||
.getLocation().toString()));
|
||||
}
|
||||
}
|
||||
|
||||
locationPathField.addModifyListener(new ModifyListener() {
|
||||
public void modifyText(ModifyEvent e) {
|
||||
errorReporter.reportError(checkValidLocation());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the path we are going to display. If it is a file URI then remove
|
||||
* the file prefix.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
private String getDefaultPathDisplayString() {
|
||||
|
||||
URI defaultURI = null;
|
||||
if (existingProject != null) {
|
||||
defaultURI = existingProject.getLocationURI();
|
||||
}
|
||||
|
||||
// Handle files specially. Assume a file if there is no project to query
|
||||
if (defaultURI == null || defaultURI.getScheme().equals(FILE_SCHEME)) {
|
||||
return Platform.getLocation().append(projectName).toString();
|
||||
}
|
||||
return defaultURI.toString();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the enablement state of the receiver.
|
||||
*
|
||||
* @param enabled
|
||||
*/
|
||||
private void setUserAreaEnabled(boolean enabled) {
|
||||
locationLabel.setEnabled(enabled);
|
||||
locationPathField.setEnabled(enabled);
|
||||
browseButton.setEnabled(enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the browse button. Usually referenced in order to set the layout
|
||||
* data for a dialog.
|
||||
*
|
||||
* @return Button
|
||||
*/
|
||||
public Button getBrowseButton() {
|
||||
return browseButton;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open an appropriate directory browser
|
||||
*/
|
||||
private void handleLocationBrowseButtonPressed() {
|
||||
|
||||
String selectedDirectory = null;
|
||||
String dirName = getPathFromLocationField();
|
||||
|
||||
if (!dirName.equals(AbstractPage.EMPTY_STR)) {
|
||||
File f = new Path(dirName).toFile();
|
||||
if (!f.exists()) dirName = AbstractPage.EMPTY_STR;
|
||||
}
|
||||
|
||||
DirectoryDialog dialog = new DirectoryDialog(locationPathField.getShell());
|
||||
dialog.setMessage(Messages.getString("ProjectContentsArea.5")); //$NON-NLS-1$
|
||||
dialog.setFilterPath(dirName);
|
||||
selectedDirectory = dialog.open();
|
||||
|
||||
if (selectedDirectory != null)
|
||||
updateLocationField(selectedDirectory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the location field based on the selected path.
|
||||
*
|
||||
* @param selectedPath
|
||||
*/
|
||||
private void updateLocationField(String selectedPath) {
|
||||
locationPathField.setText(TextProcessor.process(selectedPath));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the path on the location field.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
private String getPathFromLocationField() {
|
||||
URI fieldURI;
|
||||
try {
|
||||
fieldURI = new URI(locationPathField.getText());
|
||||
} catch (URISyntaxException e) {
|
||||
return locationPathField.getText();
|
||||
}
|
||||
return fieldURI.getPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the entry in the widget location is valid. If it is valid return
|
||||
* null. Otherwise return a string that indicates the problem.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String checkValidLocation() {
|
||||
|
||||
if (isDefault()) return null;
|
||||
|
||||
String locationFieldContents = locationPathField.getText();
|
||||
|
||||
if (locationFieldContents.length() == 0)
|
||||
return ERROR_PATH_EMPTY;
|
||||
|
||||
URI newPath = getProjectLocationURI();
|
||||
|
||||
if (newPath == null)
|
||||
return ERROR_INVALID_PATH;
|
||||
|
||||
if (!Path.EMPTY.isValidPath(locationFieldContents))
|
||||
return ERROR_NOT_VALID;
|
||||
|
||||
Path p = new Path(locationFieldContents);
|
||||
|
||||
if (!p.isAbsolute())
|
||||
return ERROR_NOT_ABSOLUTE;
|
||||
|
||||
// try to create dummy file
|
||||
File f = p.toFile();
|
||||
if (!f.exists()) {
|
||||
boolean result = false;
|
||||
try {
|
||||
result = f.createNewFile();
|
||||
} catch (IOException e) {}
|
||||
|
||||
if (result)
|
||||
f.delete();
|
||||
else
|
||||
return ERROR_CANNOT_CREATE;
|
||||
} else {
|
||||
if (f.isFile())
|
||||
return ERROR_FILE_EXISTS;
|
||||
}
|
||||
|
||||
//create a dummy project for the purpose of validation if necessary
|
||||
IProject project = existingProject;
|
||||
if (project == null) {
|
||||
String name = new Path(locationFieldContents).lastSegment();
|
||||
if (name != null && Path.EMPTY.isValidSegment(name))
|
||||
project = ResourcesPlugin.getWorkspace().getRoot().getProject(name);
|
||||
else
|
||||
return ERROR_INVALID_PATH;
|
||||
}
|
||||
IStatus locationStatus = project.getWorkspace().validateProjectLocationURI(project, newPath);
|
||||
|
||||
if (!locationStatus.isOK()) {
|
||||
return locationStatus.getMessage();
|
||||
}
|
||||
if (existingProject != null) {
|
||||
URI projectPath = existingProject.getLocationURI();
|
||||
if (projectPath != null && URIUtil.equals(projectPath, newPath))
|
||||
return ERROR_INVALID_PATH;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URI for the location field if possible.
|
||||
* @return URI or <code>null</code> if it is not valid.
|
||||
*/
|
||||
public URI getProjectLocationURI() {
|
||||
return URIUtil.toURI(locationPathField.getText());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the text to the default or clear it if not using the defaults.
|
||||
* @param newName
|
||||
* the name of the project to use. If <code>null</code> use the
|
||||
* existing project name.
|
||||
*/
|
||||
public void updateProjectName(String newName) {
|
||||
projectName = newName;
|
||||
if (isDefault())
|
||||
locationPathField.setText(TextProcessor.process(getDefaultPathDisplayString()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the location for the project. If we are using defaults then return
|
||||
* the workspace root so that core creates it with default values.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String getProjectLocation() {
|
||||
return isDefault() ?
|
||||
Platform.getLocation().toString():
|
||||
locationPathField.getText();
|
||||
}
|
||||
|
||||
/**
|
||||
* IErrorMessageReporter is an interface for type that allow message
|
||||
* reporting. Null means "clear error messages area".
|
||||
*/
|
||||
public interface IErrorMessageReporter {
|
||||
public void reportError(String errorMessage);
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue