/*******************************************************************************
 * Copyright (c) 2007, 2012 Intel Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 * Intel Corporation - Initial API and implementation
 * Andrew Gvozdev (Quoin Inc.) - Regular expression error parsers
 *******************************************************************************/
package org.eclipse.cdt.ui.newui;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.ErrorParserManager;
import org.eclipse.cdt.core.IErrorParserNamed;
import org.eclipse.cdt.core.errorparsers.RegexErrorParser;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICMultiConfigDescription;
import org.eclipse.cdt.core.settings.model.ICResourceDescription;
import org.eclipse.cdt.internal.ui.ICHelpContextIds;
import org.eclipse.cdt.internal.ui.dialogs.StatusInfo;
import org.eclipse.cdt.internal.ui.newui.Messages;
import org.eclipse.cdt.ui.CDTSharedImages;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.dialogs.ICOptionPage;
import org.eclipse.cdt.ui.dialogs.IInputStatusValidator;
import org.eclipse.cdt.ui.dialogs.InputStatusDialog;
import org.eclipse.cdt.ui.dialogs.RegexErrorParserOptionPage;
import org.eclipse.cdt.utils.ui.controls.TabFolderLayout;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.PixelConverter;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.IDecoration;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.window.Window;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.PlatformUI;
import org.osgi.service.prefs.BackingStoreException;

import com.ibm.icu.text.MessageFormat;

/**
 * This class represents Error Parser Tab in Project Properties or workspace Preferences
 *
 * @noextend This class is not intended to be subclassed by clients.
 */
public class ErrorParsTab extends AbstractCPropertyTab {
	private static final int DEFAULT_HEIGHT = 130;
	private static final int BUTTON_ADD = 0;
	private static final int BUTTON_EDIT = 1;
	private static final int BUTTON_DELETE = 2;
	// there is a separator instead of button = 3
	private static final int BUTTON_MOVEUP = 4;
	private static final int BUTTON_MOVEDOWN = 5;

	private static final String[] BUTTONS = new String[] { ADD_STR, EDIT_STR, DEL_STR, null, MOVEUP_STR,
			MOVEDOWN_STR, };
	private static final String RESET_STR = Messages.ErrorParsTab_Reset;

	private static final String OOPS = "OOPS"; //$NON-NLS-1$

	private Table fTable;
	private CheckboxTableViewer fTableViewer;
	private ICConfigurationDescription fCfgDesc;

	private static Map<String, IErrorParserNamed> fExtensionErrorParsers = null;

	private final Map<String, IErrorParserNamed> fAvailableErrorParsers = new LinkedHashMap<>();
	private final Map<String, ICOptionPage> fOptionsPageMap = new HashMap<>();
	private ICOptionPage fCurrentOptionsPage = null;

	private Composite fCompositeForOptionsPage;

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.ui.newui.AbstractCPropertyTab#createControls(org.eclipse.swt.widgets.Composite)
	 */
	@Override
	public void createControls(Composite parent) {

		super.createControls(parent);
		PlatformUI.getWorkbench().getHelpSystem().setHelp(usercomp, ICHelpContextIds.ERROR_PARSERS_PAGE);

		usercomp.setLayout(new GridLayout(1, false));

		// SashForm
		SashForm sashForm = new SashForm(usercomp, SWT.NONE);
		sashForm.setBackground(sashForm.getDisplay().getSystemColor(SWT.COLOR_GRAY));
		sashForm.setOrientation(SWT.VERTICAL);
		sashForm.setLayoutData(new GridData(GridData.FILL_BOTH));

		GridLayout layout = new GridLayout(2, false);
		layout.marginHeight = 5;
		sashForm.setLayout(layout);

		// table
		Composite compositeSashForm = new Composite(sashForm, SWT.NONE);
		compositeSashForm.setLayout(new GridLayout(2, false));
		fTable = new Table(compositeSashForm, SWT.BORDER | SWT.CHECK | SWT.SINGLE);
		fTable.setLayoutData(new GridData(GridData.FILL_BOTH));
		fTable.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				displaySelectedOptionPage();
				updateButtons();
			}
		});
		fTableViewer = new CheckboxTableViewer(fTable);
		fTableViewer.setContentProvider(new IStructuredContentProvider() {
			@Override
			public Object[] getElements(Object inputElement) {
				return (Object[]) inputElement;
			}

			@Override
			public void dispose() {
			}

			@Override
			public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
			}
		});
		fTableViewer.setLabelProvider(new LabelProvider() {
			@Override
			public String getText(Object element) {
				if (element instanceof String) {
					String id = (String) element;
					IErrorParserNamed errorParser = fAvailableErrorParsers.get(id);
					if (errorParser != null) {
						String name = errorParser.getName();
						if (name != null && name.length() > 0) {
							return name;
						}
					}
					return NLS.bind(Messages.GeneralMessages_NonAccessibleID, id);
				}
				return OOPS;
			}

			@Override
			public Image getImage(Object element) {
				final String TEST_PLUGIN_ID = "org.eclipse.cdt.core.tests"; //$NON-NLS-1$
				final String DEPRECATED = CCorePlugin.getResourceString("CCorePlugin.Deprecated"); //$NON-NLS-1$
				if (element instanceof String) {
					String id = (String) element;
					String[] extIds = ErrorParserManager.getErrorParserExtensionIds();
					if (Arrays.asList(extIds).contains(id)) {
						String imageKey = CDTSharedImages.IMG_OBJS_EXTENSION;
						if (id.startsWith(TEST_PLUGIN_ID))
							imageKey = CDTSharedImages.IMG_OBJS_CDT_TESTING;

						String[] overlayKeys = new String[5];
						IErrorParserNamed errorParser = fAvailableErrorParsers.get(id);
						IErrorParserNamed errorParserExt = fExtensionErrorParsers.get(id);
						if (!errorParser.equals(errorParserExt)) {
							overlayKeys[IDecoration.TOP_RIGHT] = CDTSharedImages.IMG_OVR_SETTING;
						} else if (errorParser.getName().contains(DEPRECATED)) {
							overlayKeys[IDecoration.TOP_RIGHT] = CDTSharedImages.IMG_OVR_INACTIVE;
						}
						return CDTSharedImages.getImageOverlaid(imageKey, overlayKeys);
					}
					return CDTSharedImages.getImage(CDTSharedImages.IMG_OBJS_USER);
				}
				return null;
			}

		});

		fTableViewer.addCheckStateListener(new ICheckStateListener() {
			@Override
			public void checkStateChanged(CheckStateChangedEvent e) {
				saveChecked();
			}
		});

		// Buttons
		Composite compositeButtons = new Composite(compositeSashForm, SWT.NONE);
		compositeButtons.setLayoutData(new GridData(GridData.END));
		initButtons(compositeButtons, BUTTONS);

		fCompositeForOptionsPage = new Composite(sashForm, SWT.NULL);
		GridData gd = new GridData();
		fCompositeForOptionsPage.setLayout(new TabFolderLayout());

		PixelConverter converter = new PixelConverter(parent);
		gd.heightHint = converter.convertHorizontalDLUsToPixels(DEFAULT_HEIGHT);

		gd.horizontalAlignment = GridData.FILL;
		gd.grabExcessHorizontalSpace = true;
		gd.grabExcessVerticalSpace = true;
		gd.horizontalSpan = 2;
		fCompositeForOptionsPage.setLayoutData(gd);

		sashForm.setWeights(new int[] { 50, 50 });

		// init data
		ICResourceDescription resDecs = getResDesc();
		fCfgDesc = resDecs != null ? resDecs.getConfiguration() : null;
		initMapParsers();
		updateData(getResDesc());
	}

	private void initMapParsers() {
		if (fExtensionErrorParsers == null) {
			fExtensionErrorParsers = new LinkedHashMap<>();
			String[] idsExt = ErrorParserManager.getErrorParserExtensionIds();
			for (String idExt : idsExt) {
				IErrorParserNamed errorParserExt = ErrorParserManager.getErrorParserExtensionCopy(idExt);
				fExtensionErrorParsers.put(idExt, errorParserExt);
			}
		}
		fAvailableErrorParsers.clear();
		fOptionsPageMap.clear();
		for (String id : ErrorParserManager.getErrorParserAvailableIdsInContext(ErrorParserManager.BUILD_CONTEXT)) {
			IErrorParserNamed errorParser = ErrorParserManager.getErrorParserCopy(id);
			fAvailableErrorParsers.put(id, errorParser);
			initializeOptionsPage(id);
		}

		String ids[];
		if (fCfgDesc != null) {
			ICConfigurationDescription srcCfgDesc = fCfgDesc.getConfiguration();
			if (srcCfgDesc instanceof ICMultiConfigDescription) {
				String[][] ss = ((ICMultiConfigDescription) srcCfgDesc).getErrorParserIDs();
				ids = CDTPrefUtil.getStrListForDisplay(ss);
			} else {
				ids = srcCfgDesc.getBuildSetting().getErrorParserIDs();
			}
			Set<String> setIds = new LinkedHashSet<>(Arrays.asList(ids));
			setIds.addAll(fAvailableErrorParsers.keySet());
			fTableViewer.setInput(setIds.toArray(new String[0]));
		} else {
			fTableViewer.setInput(fAvailableErrorParsers.keySet().toArray(new String[0]));
			ids = ErrorParserManager.getDefaultErrorParserIds();
		}
		fTableViewer.setCheckedElements(ids);

		displaySelectedOptionPage();
	}

	private void initializeOptionsPage(final String id) {
		IErrorParserNamed errorParser = fAvailableErrorParsers.get(id);
		if (errorParser != null) {
			String name = errorParser.getName();
			if (name != null && name.length() > 0) {
				// RegexErrorParser has an Options page
				if (errorParser instanceof RegexErrorParser) {
					// allow to edit only for Build Settings Preference Page (where cfgd==null)
					RegexErrorParserOptionPage optionsPage = new RegexErrorParserOptionPage(
							(RegexErrorParser) errorParser, isErrorParsersEditable());
					optionsPage.addListener(new Listener() {
						@Override
						public void handleEvent(Event event) {
							fTableViewer.refresh(id);
							updateButtons();
						}
					});
					fOptionsPageMap.put(id, optionsPage);
					optionsPage.setContainer(page);
					optionsPage.createControl(fCompositeForOptionsPage);
					optionsPage.setVisible(false);
					fCompositeForOptionsPage.layout(true);
				}
			}
		}
	}

	private void displaySelectedOptionPage() {
		if (fCurrentOptionsPage != null)
			fCurrentOptionsPage.setVisible(false);

		int pos = fTable.getSelectionIndex();
		if (pos < 0)
			return;

		String parserId = (String) fTable.getItem(pos).getData();
		ICOptionPage optionsPage = fOptionsPageMap.get(parserId);
		if (optionsPage != null) {
			optionsPage.setVisible(true);
		}
		fCurrentOptionsPage = optionsPage;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.ui.newui.AbstractCPropertyTab#buttonPressed(int)
	 */
	@Override
	public void buttonPressed(int n) {
		switch (n) {
		case BUTTON_ADD:
			addErrorParser();
			break;
		case BUTTON_EDIT:
			editErrorParser();
			break;
		case BUTTON_DELETE:
			deleteErrorParser();
			break;
		case BUTTON_MOVEUP:
			moveItem(true);
			break;
		case BUTTON_MOVEDOWN:
			moveItem(false);
			break;
		default:
			break;
		}
		updateButtons();
	}

	// Move item up / down
	private void moveItem(boolean up) {
		int n = fTable.getSelectionIndex();
		if (n < 0 || (up && n == 0) || (!up && n + 1 == fTable.getItemCount()))
			return;

		String id = (String) fTableViewer.getElementAt(n);
		boolean checked = fTableViewer.getChecked(id);
		fTableViewer.remove(id);
		n = up ? n - 1 : n + 1;
		fTableViewer.insert(id, n);
		fTableViewer.setChecked(id, checked);
		fTable.setSelection(n);

		saveChecked();
	}

	private String makeId(String name) {
		return CUIPlugin.PLUGIN_ID + '.' + name;
	}

	private void addErrorParser() {
		IInputStatusValidator inputValidator = new IInputStatusValidator() {
			@Override
			public IStatus isValid(String newText) {
				StatusInfo status = new StatusInfo();
				if (newText.trim().length() == 0) {
					status.setError(Messages.ErrorParsTab_error_NonEmptyName);
				} else if (newText.indexOf(ErrorParserManager.ERROR_PARSER_DELIMITER) >= 0) {
					String message = MessageFormat.format(Messages.ErrorParsTab_error_IllegalCharacter,
							new Object[] { ErrorParserManager.ERROR_PARSER_DELIMITER });
					status.setError(message);
				} else if (fAvailableErrorParsers.containsKey(makeId(newText))) {
					status.setError(Messages.ErrorParsTab_error_NonUniqueID);
				}
				return status;
			}

		};
		InputStatusDialog addDialog = new InputStatusDialog(usercomp.getShell(), Messages.ErrorParsTab_title_Add,
				Messages.ErrorParsTab_label_EnterName, Messages.ErrorParsTab_label_DefaultRegexErrorParserName,
				inputValidator);
		addDialog.setHelpAvailable(false);

		if (addDialog.open() == Window.OK) {
			String newName = addDialog.getValue();
			String newId = makeId(newName);
			IErrorParserNamed errorParser = new RegexErrorParser(newId, newName);
			fAvailableErrorParsers.put(newId, errorParser);

			fTableViewer.add(newId);
			fTableViewer.setChecked(newId, true);
			fTable.setSelection(fTable.getItemCount() - 1);

			initializeOptionsPage(newId);
			displaySelectedOptionPage();
			updateButtons();
		}
	}

	private void editErrorParser() {
		int n = fTable.getSelectionIndex();
		Assert.isTrue(n >= 0);

		String id = (String) fTableViewer.getElementAt(n);
		IErrorParserNamed errorParser = fAvailableErrorParsers.get(id);

		IInputStatusValidator inputValidator = new IInputStatusValidator() {
			@Override
			public IStatus isValid(String newText) {
				StatusInfo status = new StatusInfo();
				if (newText.trim().length() == 0) {
					status.setError(Messages.ErrorParsTab_error_NonEmptyName);
				} else if (newText.indexOf(ErrorParserManager.ERROR_PARSER_DELIMITER) >= 0) {
					String message = MessageFormat.format(Messages.ErrorParsTab_error_IllegalCharacter,
							new Object[] { ErrorParserManager.ERROR_PARSER_DELIMITER });
					status.setError(message);
				}
				return status;
			}

		};
		InputStatusDialog addDialog = new InputStatusDialog(usercomp.getShell(), Messages.ErrorParsTab_title_Edit,
				Messages.ErrorParsTab_label_EnterName, errorParser.getName(), inputValidator);
		addDialog.setHelpAvailable(false);

		if (addDialog.open() == Window.OK) {
			errorParser.setName(addDialog.getValue());
			fTableViewer.refresh(id);
		}
	}

	private void deleteErrorParser() {
		int n = fTable.getSelectionIndex();
		if (n < 0)
			return;

		String id = (String) fTableViewer.getElementAt(n);
		if (fExtensionErrorParsers.containsKey(id)) {
			// Reset
			fAvailableErrorParsers.put(id, ErrorParserManager.getErrorParserExtensionCopy(id));
			fTableViewer.refresh(id);
			initializeOptionsPage(id);
			displaySelectedOptionPage();
		} else {
			// Delete
			fTableViewer.remove(id);

			int last = fTable.getItemCount() - 1;
			if (n > last)
				n = last;
			if (n >= 0)
				fTable.setSelection(n);

			saveChecked();
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.ui.newui.AbstractCPropertyTab#updateData(org.eclipse.cdt.core.settings.model.ICResourceDescription)
	 */
	@Override
	public void updateData(ICResourceDescription resDecs) {
		ICConfigurationDescription oldCfgDesc = fCfgDesc;
		fCfgDesc = resDecs != null ? resDecs.getConfiguration() : null;
		if (oldCfgDesc != fCfgDesc) {
			initMapParsers();
		}
		displaySelectedOptionPage();
		updateButtons();
	}

	private static boolean isExtensionId(String id) {
		for (String extId : ErrorParserManager.getErrorParserExtensionIds()) {
			if (extId.equals(id)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Check if error parser with this id shown to user differs from error parser defined as extension.
	 */
	private boolean isModified(String id) {
		IErrorParserNamed errorParser = fAvailableErrorParsers.get(id);
		IErrorParserNamed errorParserExt = fExtensionErrorParsers.get(id);
		return !errorParser.equals(errorParserExt);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.ui.newui.AbstractCPropertyTab#updateButtons()
	 */
	@Override
	public void updateButtons() {
		int pos = fTable.getSelectionIndex();
		int count = fTable.getItemCount();
		int last = count - 1;
		boolean selected = pos >= 0 && pos <= last;
		String id = (String) fTableViewer.getElementAt(pos);

		boolean isExtensionId = isExtensionId(id);
		boolean canDelete = !isExtensionId && isErrorParsersEditable();
		boolean canReset = isExtensionId && isErrorParsersEditable() && isModified(id);

		buttonSetText(BUTTON_DELETE, isExtensionId ? RESET_STR : DEL_STR);

		buttonSetEnabled(BUTTON_ADD, isErrorParsersEditable());
		buttonSetEnabled(BUTTON_EDIT, isErrorParsersEditable() && selected);
		buttonSetEnabled(BUTTON_DELETE, (canDelete || canReset) && selected);
		buttonSetEnabled(BUTTON_MOVEUP, selected && pos != 0);
		buttonSetEnabled(BUTTON_MOVEDOWN, selected && pos != last);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.ui.newui.AbstractCPropertyTab#performApply(org.eclipse.cdt.core.settings.model.ICResourceDescription, org.eclipse.cdt.core.settings.model.ICResourceDescription)
	 */
	@Override
	protected void performApply(ICResourceDescription src, ICResourceDescription dst) {
		performOK();

		if (!page.isForPrefs()) {
			ICConfigurationDescription sd = src.getConfiguration();
			ICConfigurationDescription dd = dst.getConfiguration();
			String[] s = null;
			if (sd instanceof ICMultiConfigDescription) {
				String[][] ss = ((ICMultiConfigDescription) sd).getErrorParserIDs();
				s = CDTPrefUtil.getStrListForDisplay(ss);
			} else {
				s = sd.getBuildSetting().getErrorParserIDs();
			}
			if (dd instanceof ICMultiConfigDescription)
				((ICMultiConfigDescription) dd).setErrorParserIDs(s);
			else
				dd.getBuildSetting().setErrorParserIDs(s);
			initMapParsers();
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.ui.newui.AbstractCPropertyTab#performOK()
	 */
	@Override
	protected void performOK() {
		informPages(true);

		if (page.isForPrefs()) {
			if (fCfgDesc == null) {
				// Build Settings page
				try {
					List<IErrorParserNamed> errorParsersList = new ArrayList<>(fTable.getItemCount());
					for (TableItem item : fTable.getItems()) {
						if (item.getData() instanceof String) {
							String id = (String) item.getData();
							if (isModified(id)) {
								errorParsersList.add(fAvailableErrorParsers.get(id));
							}
						}
					}

					Object[] checkedElements = fTableViewer.getCheckedElements();
					String[] checkedErrorParserIds = new String[checkedElements.length];
					System.arraycopy(checkedElements, 0, checkedErrorParserIds, 0, checkedElements.length);

					ErrorParserManager.setDefaultErrorParserIds(checkedErrorParserIds);
					ErrorParserManager.setUserDefinedErrorParsers(
							errorParsersList.toArray(new IErrorParserNamed[errorParsersList.size()]));
				} catch (BackingStoreException e) {
					CUIPlugin.log(Messages.ErrorParsTab_error_OnApplyingSettings, e);
				} catch (CoreException e) {
					CUIPlugin.log(Messages.ErrorParsTab_error_OnApplyingSettings, e);
				}
			}
			initMapParsers();
		}
	}

	private void saveChecked() {
		if (fCfgDesc != null) {
			Object[] objs = fTableViewer.getCheckedElements();
			String[] ids = new String[objs.length];
			System.arraycopy(objs, 0, ids, 0, objs.length);

			if (fCfgDesc instanceof ICMultiConfigDescription)
				((ICMultiConfigDescription) fCfgDesc).setErrorParserIDs(ids);
			else
				fCfgDesc.getBuildSetting().setErrorParserIDs(ids);
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.ui.newui.AbstractCPropertyTab#canBeVisible()
	 */
	@Override
	public boolean canBeVisible() {
		return page.isForProject() || page.isForPrefs();
	}

	/**
	 * @return {@code true} if the error parsers are allowed to be editable,
	 *     i.e. Add/Edit/Delete buttons are enabled and Options page edits enabled.
	 *     This will evaluate to {@code true} for Preference Build Settings page but
	 *     not for Preference New CDT Project Wizard/Makefile Project.
	 */
	private boolean isErrorParsersEditable() {
		return fCfgDesc == null;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.ui.newui.AbstractCPropertyTab#performDefaults()
	 */
	@Override
	protected void performDefaults() {
		if (isErrorParsersEditable()) {
			// Must be Build Settings Preference Page
			if (MessageDialog.openQuestion(usercomp.getShell(), Messages.ErrorParsTab_title_ConfirmReset,
					Messages.ErrorParsTab_message_ConfirmReset)) {

				try {
					ErrorParserManager.setUserDefinedErrorParsers(null);
					ErrorParserManager.setDefaultErrorParserIds(null);
				} catch (BackingStoreException e) {
					CUIPlugin.log(Messages.ErrorParsTab_error_OnRestoring, e);
				} catch (CoreException e) {
					CUIPlugin.log(Messages.ErrorParsTab_error_OnRestoring, e);
				}
			}
		} else {
			if (fCfgDesc instanceof ICMultiConfigDescription)
				((ICMultiConfigDescription) fCfgDesc).setErrorParserIDs(null);
			else
				fCfgDesc.getBuildSetting().setErrorParserIDs(null);
		}
		initMapParsers();
		updateButtons();
	}

	private void informPages(boolean apply) {
		Collection<ICOptionPage> pages = fOptionsPageMap.values();
		for (ICOptionPage dynamicPage : pages) {
			if (dynamicPage != null && dynamicPage.isValid() && dynamicPage.getControl() != null) {
				try {
					if (apply)
						dynamicPage.performApply(new NullProgressMonitor());
					else
						dynamicPage.performDefaults();
				} catch (CoreException e) {
					CUIPlugin.log(Messages.ErrorParsTab_error_OnApplyingSettings, e);
				}
			}
		}
	}
}
