protected void createSpacer(Composite parent) {
   Label spacer = new Label(parent, SWT.NONE);
   GridData data = new GridData();
   data.horizontalAlignment = GridData.FILL;
   data.verticalAlignment = GridData.BEGINNING;
   data.heightHint = 4;
   spacer.setLayoutData(data);
 }
  private void createButtonPanel(Composite pageContent) {
    Composite buttonPanel = new Composite(pageContent, SWT.NONE);
    GridLayout layout = new GridLayout();
    layout.numColumns = 1;
    buttonPanel.setLayout(layout);

    GridData gridData = new GridData();
    gridData.grabExcessHorizontalSpace = false;
    gridData.grabExcessVerticalSpace = true;
    gridData.verticalAlignment = GridData.CENTER;
    gridData.horizontalAlignment = GridData.CENTER;
    buttonPanel.setLayoutData(gridData);

    addButton = new Button(buttonPanel, SWT.PUSH);
    addButton.setText(Messages._UI_ADD_BUTTON);
    gridData = new GridData();
    gridData.horizontalAlignment = GridData.FILL;
    gridData.verticalAlignment = GridData.CENTER;
    addButton.setLayoutData(gridData);
    addButton.addSelectionListener(new ButtonSelectListener());
    addButton.setToolTipText(Messages._UI_ADD_BUTTON_TOOL_TIP);
    addButton.setEnabled(false);

    removeButton = new Button(buttonPanel, SWT.PUSH);
    removeButton.setText(Messages._UI_REMOVE_BUTTON);
    gridData = new GridData();
    gridData.horizontalAlignment = GridData.FILL;
    gridData.verticalAlignment = GridData.CENTER;
    removeButton.setLayoutData(gridData);
    removeButton.addSelectionListener(new ButtonSelectListener());
    removeButton.setToolTipText(Messages._UI_REMOVE_BUTTON_TOOL_TIP);
    removeButton.setEnabled(false);

    removeAllButton = new Button(buttonPanel, SWT.PUSH);
    removeAllButton.setText(Messages._UI_REMOVE_ALL_BUTTON);
    gridData = new GridData();
    gridData.horizontalAlignment = GridData.FILL;
    gridData.verticalAlignment = GridData.CENTER;
    removeAllButton.setLayoutData(gridData);
    removeAllButton.addSelectionListener(new ButtonSelectListener());
    removeAllButton.setToolTipText(Messages._UI_REMOVE_ALL_BUTTON_TOOL_TIP);
    removeAllButton.setEnabled(false);
  }
  private void createLanguagesGroup(Composite parent) {
    final Group langGroup =
        NSISWizardDialogUtil.createGroup(
            parent, 1, "language.support.group.label", null, false); // $NON-NLS-1$
    GridData data = (GridData) langGroup.getLayoutData();
    data.verticalAlignment = SWT.FILL;
    data.grabExcessVerticalSpace = true;
    data.horizontalAlignment = SWT.FILL;
    data.grabExcessHorizontalSpace = true;

    NSISWizardSettings settings = mWizard.getSettings();

    final Button enableLangSupport =
        NSISWizardDialogUtil.createCheckBox(
            langGroup,
            "enable.language.support.label",
            settings.isEnableLanguageSupport(),
            true,
            null,
            false); //$NON-NLS-1$
    enableLangSupport.addSelectionListener(
        new SelectionAdapter() {
          @Override
          public void widgetSelected(SelectionEvent e) {
            boolean selection = enableLangSupport.getSelection();
            mWizard.getSettings().setEnableLanguageSupport(selection);
            validateField(LANG_CHECK);
          }
        });

    final MasterSlaveController m = new MasterSlaveController(enableLangSupport);

    final Composite listsComposite = new Composite(langGroup, SWT.NONE);
    data = new GridData(SWT.FILL, SWT.FILL, true, true);
    listsComposite.setLayoutData(data);

    GridLayout layout = new GridLayout(2, true);
    layout.marginHeight = 0;
    layout.marginWidth = 0;
    listsComposite.setLayout(layout);

    java.util.List<NSISLanguage> selectedLanguages = settings.getLanguages();
    if (selectedLanguages.isEmpty()) {
      NSISLanguage defaultLanguage = NSISLanguageManager.getInstance().getDefaultLanguage();
      if (defaultLanguage != null) {
        selectedLanguages.add(defaultLanguage);
      }
    }
    java.util.List<NSISLanguage> availableLanguages =
        NSISLanguageManager.getInstance().getLanguages();
    availableLanguages.removeAll(selectedLanguages);

    Composite leftComposite = new Composite(listsComposite, SWT.NONE);
    leftComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
    layout = new GridLayout(2, false);
    layout.marginHeight = 0;
    layout.marginWidth = 0;
    leftComposite.setLayout(layout);

    ((GridData)
                NSISWizardDialogUtil.createLabel(
                        leftComposite,
                        "available.languages.label", //$NON-NLS-1$
                        true,
                        m,
                        false)
                    .getLayoutData())
            .horizontalSpan =
        2;

    final List availableLangList =
        new List(leftComposite, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI);
    data = new GridData(SWT.FILL, SWT.FILL, true, true);
    Dialog.applyDialogFont(availableLangList);
    data.heightHint = Common.calculateControlSize(availableLangList, 0, 12).y;
    availableLangList.setLayoutData(data);
    m.addSlave(availableLangList);

    final ListViewer availableLangViewer = new ListViewer(availableLangList);
    CollectionContentProvider collectionContentProvider = new CollectionContentProvider();
    availableLangViewer.setContentProvider(collectionContentProvider);
    availableLangViewer.setInput(availableLanguages);
    availableLangViewer.setSorter(new ViewerSorter(cLanguageCollator));

    final Composite buttonsComposite1 = new Composite(leftComposite, SWT.NONE);
    layout = new GridLayout(1, false);
    layout.marginHeight = 0;
    layout.marginWidth = 0;
    buttonsComposite1.setLayout(layout);
    data = new GridData(SWT.FILL, SWT.CENTER, false, false);
    buttonsComposite1.setLayoutData(data);

    final Button allRightButton = new Button(buttonsComposite1, SWT.PUSH);
    data = new GridData(SWT.FILL, SWT.CENTER, true, false);
    allRightButton.setLayoutData(data);
    allRightButton.setImage(
        EclipseNSISPlugin.getImageManager()
            .getImage(EclipseNSISPlugin.getResourceString("all.right.icon"))); // $NON-NLS-1$
    allRightButton.setToolTipText(
        EclipseNSISPlugin.getResourceString("all.right.tooltip")); // $NON-NLS-1$

    final Button rightButton = new Button(buttonsComposite1, SWT.PUSH);
    data = new GridData(SWT.FILL, SWT.CENTER, true, false);
    rightButton.setLayoutData(data);
    rightButton.setImage(
        EclipseNSISPlugin.getImageManager()
            .getImage(EclipseNSISPlugin.getResourceString("right.icon"))); // $NON-NLS-1$
    rightButton.setToolTipText(EclipseNSISPlugin.getResourceString("right.tooltip")); // $NON-NLS-1$

    final Button leftButton = new Button(buttonsComposite1, SWT.PUSH);
    data = new GridData(SWT.FILL, SWT.CENTER, true, false);
    leftButton.setLayoutData(data);
    leftButton.setImage(
        EclipseNSISPlugin.getImageManager()
            .getImage(EclipseNSISPlugin.getResourceString("left.icon"))); // $NON-NLS-1$
    leftButton.setToolTipText(EclipseNSISPlugin.getResourceString("left.tooltip")); // $NON-NLS-1$

    final Button allLeftButton = new Button(buttonsComposite1, SWT.PUSH);
    data = new GridData(SWT.FILL, SWT.CENTER, true, false);
    allLeftButton.setLayoutData(data);
    allLeftButton.setImage(
        EclipseNSISPlugin.getImageManager()
            .getImage(EclipseNSISPlugin.getResourceString("all.left.icon"))); // $NON-NLS-1$
    allLeftButton.setToolTipText(
        EclipseNSISPlugin.getResourceString("all.left.tooltip")); // $NON-NLS-1$

    Composite rightComposite = new Composite(listsComposite, SWT.NONE);
    rightComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
    layout = new GridLayout(2, false);
    layout.marginHeight = 0;
    layout.marginWidth = 0;
    rightComposite.setLayout(layout);

    ((GridData)
                NSISWizardDialogUtil.createLabel(
                        rightComposite,
                        "selected.languages.label", //$NON-NLS-1$
                        true,
                        m,
                        isScriptWizard())
                    .getLayoutData())
            .horizontalSpan =
        2;

    final List selectedLangList =
        new List(rightComposite, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI);
    data = new GridData(SWT.FILL, SWT.FILL, true, true);
    Dialog.applyDialogFont(selectedLangList);
    data.heightHint = Common.calculateControlSize(selectedLangList, 0, 12).y;
    selectedLangList.setLayoutData(data);
    m.addSlave(selectedLangList);

    final ListViewer selectedLangViewer = new ListViewer(selectedLangList);
    selectedLangViewer.setContentProvider(collectionContentProvider);
    selectedLangViewer.setInput(selectedLanguages);

    final ListViewerUpDownMover<java.util.List<NSISLanguage>, NSISLanguage> mover =
        new ListViewerUpDownMover<java.util.List<NSISLanguage>, NSISLanguage>() {
          @Override
          @SuppressWarnings("unchecked")
          protected java.util.List<NSISLanguage> getAllElements() {
            return (java.util.List<NSISLanguage>) ((ListViewer) getViewer()).getInput();
          }

          @Override
          protected void updateStructuredViewerInput(
              java.util.List<NSISLanguage> input,
              java.util.List<NSISLanguage> elements,
              java.util.List<NSISLanguage> move,
              boolean isDown) {
            (input).clear();
            (input).addAll(elements);
          }
        };

    mover.setViewer(selectedLangViewer);

    final Composite buttonsComposite2 = new Composite(rightComposite, SWT.NONE);
    layout = new GridLayout(1, false);
    layout.marginHeight = 0;
    layout.marginWidth = 0;
    buttonsComposite2.setLayout(layout);
    data = new GridData(SWT.FILL, SWT.CENTER, false, false);
    buttonsComposite2.setLayoutData(data);

    final Button upButton = new Button(buttonsComposite2, SWT.PUSH);
    data = new GridData(SWT.FILL, SWT.CENTER, true, false);
    upButton.setLayoutData(data);
    upButton.setImage(
        EclipseNSISPlugin.getImageManager()
            .getImage(EclipseNSISPlugin.getResourceString("up.icon"))); // $NON-NLS-1$
    upButton.setToolTipText(EclipseNSISPlugin.getResourceString("up.tooltip")); // $NON-NLS-1$
    m.addSlave(upButton);

    final Button downButton = new Button(buttonsComposite2, SWT.PUSH);
    data = new GridData(SWT.FILL, SWT.CENTER, true, false);
    downButton.setLayoutData(data);
    downButton.setImage(
        EclipseNSISPlugin.getImageManager()
            .getImage(EclipseNSISPlugin.getResourceString("down.icon"))); // $NON-NLS-1$
    downButton.setToolTipText(EclipseNSISPlugin.getResourceString("down.tooltip")); // $NON-NLS-1$
    m.addSlave(downButton);

    Composite langOptions = langGroup;
    boolean showSupportedLangOption =
        NSISPreferences.getInstance().getNSISVersion().compareTo(INSISVersions.VERSION_2_26) >= 0;
    if (showSupportedLangOption) {
      langOptions = new Composite(langGroup, SWT.None);
      layout = new GridLayout(2, false);
      layout.marginHeight = 0;
      layout.marginWidth = 0;
      langOptions.setLayout(layout);
      data = new GridData(SWT.FILL, SWT.FILL, true, false);
      langOptions.setLayoutData(data);
    }

    final Button selectLang =
        NSISWizardDialogUtil.createCheckBox(
            langOptions,
            "select.language.label",
            settings.isSelectLanguage(),
            true,
            m,
            false); //$NON-NLS-1$

    final Button displaySupported;
    if (showSupportedLangOption) {
      ((GridData) selectLang.getLayoutData()).horizontalSpan = 1;
      displaySupported =
          NSISWizardDialogUtil.createCheckBox(
              langOptions,
              "display.supported.languages.label",
              settings.isDisplaySupportedLanguages(), // $NON-NLS-1$
              true,
              m,
              false);
      ((GridData) displaySupported.getLayoutData()).horizontalSpan = 1;
      displaySupported.addSelectionListener(
          new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
              mWizard.getSettings().setDisplaySupportedLanguages(displaySupported.getSelection());
            }
          });
    } else {
      displaySupported = null;
    }

    final MasterSlaveEnabler mse =
        new MasterSlaveEnabler() {
          public void enabled(Control control, boolean flag) {}

          @SuppressWarnings("unchecked")
          public boolean canEnable(Control control) {
            NSISWizardSettings settings = mWizard.getSettings();

            if (control == allRightButton) {
              return settings.isEnableLanguageSupport()
                  && availableLangViewer.getList().getItemCount() > 0;
            } else if (control == rightButton) {
              return settings.isEnableLanguageSupport()
                  && !availableLangViewer.getSelection().isEmpty();
            } else if (control == allLeftButton) {
              return settings.isEnableLanguageSupport()
                  && selectedLangViewer.getList().getItemCount() > 0;
            } else if (control == leftButton) {
              return settings.isEnableLanguageSupport()
                  && !selectedLangViewer.getSelection().isEmpty();
            } else if (control == upButton) {
              return settings.isEnableLanguageSupport() && mover.canMoveUp();
            } else if (control == downButton) {
              return settings.isEnableLanguageSupport() && mover.canMoveDown();
            } else if (control == selectLang) {
              java.util.List<NSISLanguage> selectedLanguages =
                  (java.util.List<NSISLanguage>) selectedLangViewer.getInput();
              return settings.getInstallerType() != INSTALLER_TYPE_SILENT
                  && settings.isEnableLanguageSupport()
                  && selectedLanguages.size() > 1;
            } else if (control == displaySupported && displaySupported != null) {
              java.util.List<NSISLanguage> selectedLanguages =
                  (java.util.List<NSISLanguage>) selectedLangViewer.getInput();
              return settings.getInstallerType() != INSTALLER_TYPE_SILENT
                  && settings.isEnableLanguageSupport()
                  && selectedLanguages.size() > 1
                  && selectLang.getSelection();
            } else {
              return true;
            }
          }
        };
    m.addSlave(rightButton, mse);
    m.addSlave(allRightButton, mse);
    m.addSlave(leftButton, mse);
    m.addSlave(allLeftButton, mse);
    m.setEnabler(upButton, mse);
    m.setEnabler(downButton, mse);
    m.setEnabler(selectLang, mse);
    if (displaySupported != null) {
      m.setEnabler(displaySupported, mse);
    }

    selectLang.addSelectionListener(
        new SelectionAdapter() {
          @Override
          public void widgetSelected(SelectionEvent e) {
            mWizard.getSettings().setSelectLanguage(selectLang.getSelection());
            if (displaySupported != null) {
              displaySupported.setEnabled(mse.canEnable(displaySupported));
            }
          }
        });

    final Runnable langRunnable =
        new Runnable() {
          public void run() {
            availableLangViewer.refresh(false);
            selectedLangViewer.refresh(false);
            allRightButton.setEnabled(mse.canEnable(allRightButton));
            allLeftButton.setEnabled(mse.canEnable(allLeftButton));
            rightButton.setEnabled(mse.canEnable(rightButton));
            leftButton.setEnabled(mse.canEnable(leftButton));
            upButton.setEnabled(mse.canEnable(upButton));
            downButton.setEnabled(mse.canEnable(downButton));
            selectLang.setEnabled(mse.canEnable(selectLang));
            if (displaySupported != null) {
              displaySupported.setEnabled(mse.canEnable(displaySupported));
            }
            setPageComplete(validateField(LANG_CHECK));
          }
        };

    rightButton.addSelectionListener(
        new SelectionAdapter() {
          @Override
          public void widgetSelected(SelectionEvent se) {
            moveAcross(
                availableLangViewer,
                selectedLangViewer,
                Common.makeGenericList(
                    NSISLanguage.class,
                    ((IStructuredSelection) availableLangViewer.getSelection()).toList()));
            langRunnable.run();
          }
        });
    allRightButton.addSelectionListener(
        new SelectionAdapter() {
          @Override
          @SuppressWarnings("unchecked")
          public void widgetSelected(SelectionEvent se) {
            moveAcross(
                availableLangViewer,
                selectedLangViewer,
                (java.util.List<NSISLanguage>) availableLangViewer.getInput());
            langRunnable.run();
          }
        });
    leftButton.addSelectionListener(
        new SelectionAdapter() {
          @Override
          public void widgetSelected(SelectionEvent se) {
            moveAcross(
                selectedLangViewer,
                availableLangViewer,
                Common.makeGenericList(
                    NSISLanguage.class,
                    ((IStructuredSelection) selectedLangViewer.getSelection()).toList()));
            langRunnable.run();
          }
        });
    allLeftButton.addSelectionListener(
        new SelectionAdapter() {
          @Override
          @SuppressWarnings("unchecked")
          public void widgetSelected(SelectionEvent se) {
            moveAcross(
                selectedLangViewer,
                availableLangViewer,
                (java.util.List<NSISLanguage>) selectedLangViewer.getInput());
            langRunnable.run();
          }
        });
    upButton.addSelectionListener(
        new SelectionAdapter() {
          @Override
          public void widgetSelected(SelectionEvent se) {
            mover.moveUp();
            langRunnable.run();
          }
        });
    downButton.addSelectionListener(
        new SelectionAdapter() {
          @Override
          public void widgetSelected(SelectionEvent se) {
            mover.moveDown();
            langRunnable.run();
          }
        });

    availableLangViewer.addSelectionChangedListener(
        new ISelectionChangedListener() {
          public void selectionChanged(SelectionChangedEvent event) {
            rightButton.setEnabled(mse.canEnable(rightButton));
            allRightButton.setEnabled(mse.canEnable(allRightButton));
          }
        });
    availableLangViewer
        .getList()
        .addSelectionListener(
            new SelectionAdapter() {
              @Override
              public void widgetDefaultSelected(SelectionEvent event) {
                IStructuredSelection sel =
                    (IStructuredSelection) availableLangViewer.getSelection();
                if (!sel.isEmpty()) {
                  moveAcross(
                      availableLangViewer,
                      selectedLangViewer,
                      Common.makeGenericList(NSISLanguage.class, sel.toList()));
                  selectedLangViewer.reveal(sel.getFirstElement());
                  langRunnable.run();
                }
              }
            });
    selectedLangViewer.addSelectionChangedListener(
        new ISelectionChangedListener() {
          public void selectionChanged(SelectionChangedEvent event) {
            leftButton.setEnabled(mse.canEnable(leftButton));
            allLeftButton.setEnabled(mse.canEnable(allLeftButton));
            upButton.setEnabled(mse.canEnable(upButton));
            downButton.setEnabled(mse.canEnable(downButton));
            selectLang.setEnabled(mse.canEnable(selectLang));
            if (displaySupported != null) {
              displaySupported.setEnabled(mse.canEnable(displaySupported));
            }
          }
        });
    selectedLangViewer
        .getList()
        .addSelectionListener(
            new SelectionAdapter() {
              @Override
              public void widgetDefaultSelected(SelectionEvent event) {
                IStructuredSelection sel = (IStructuredSelection) selectedLangViewer.getSelection();
                if (!sel.isEmpty()) {
                  moveAcross(
                      selectedLangViewer,
                      availableLangViewer,
                      Common.makeGenericList(NSISLanguage.class, sel.toList()));
                  availableLangViewer.reveal(sel.getFirstElement());
                  langRunnable.run();
                }
              }
            });

    m.updateSlaves();

    listsComposite.addListener(
        SWT.Resize,
        new Listener() {
          boolean init = false;

          public void handleEvent(Event e) {
            if (!init) {
              // Stupid hack so that the height hint doesn't get changed
              // on the first resize,
              // i.e., when the page is drawn for the first time.
              init = true;
            } else {
              Point size = listsComposite.getSize();
              GridLayout layout = (GridLayout) listsComposite.getLayout();
              int heightHint = size.y - 2 * layout.marginHeight;
              ((GridData) availableLangList.getLayoutData()).heightHint = heightHint;
              ((GridData) selectedLangList.getLayoutData()).heightHint = heightHint;
              int totalWidth = size.x - 2 * layout.marginWidth - 3 * layout.horizontalSpacing;
              int listWidth = (int) (totalWidth * 0.4);
              int buttonWidth = (int) (0.5 * (totalWidth - 2 * listWidth));
              size = availableLangList.computeSize(listWidth, SWT.DEFAULT);
              int delta = 0;
              if (size.x > listWidth) {
                delta = size.x - listWidth;
                listWidth = listWidth - delta;
              }
              ((GridData) availableLangList.getLayoutData()).widthHint = listWidth;
              ((GridData) buttonsComposite1.getLayoutData()).widthHint =
                  totalWidth - 2 * (listWidth + delta) - buttonWidth;
              ((GridData) selectedLangList.getLayoutData()).widthHint = listWidth;
              ((GridData) buttonsComposite2.getLayoutData()).widthHint = buttonWidth;
              listsComposite.layout();
            }
          }
        });

    addPageChangedRunnable(
        new Runnable() {
          public void run() {
            if (isCurrentPage()) {
              selectLang.setEnabled(mse.canEnable(selectLang));
              if (displaySupported != null) {
                displaySupported.setEnabled(mse.canEnable(displaySupported));
              }
            }
          }
        });

    mWizard.addSettingsListener(
        new INSISWizardSettingsListener() {
          public void settingsChanged(
              NSISWizardSettings oldSettings, NSISWizardSettings newSettings) {
            enableLangSupport.setSelection(newSettings.isEnableLanguageSupport());
            m.updateSlaves();
            selectLang.setSelection(newSettings.isSelectLanguage());
            if (displaySupported != null) {
              displaySupported.setSelection(newSettings.isDisplaySupportedLanguages());
            }
            java.util.List<NSISLanguage> selectedLanguages = newSettings.getLanguages();
            java.util.List<NSISLanguage> availableLanguages =
                NSISLanguageManager.getInstance().getLanguages();
            if (selectedLanguages.isEmpty()) {
              NSISWizardWelcomePage welcomePage =
                  (NSISWizardWelcomePage) mWizard.getPage(NSISWizardWelcomePage.NAME);
              if (welcomePage != null) {
                if (!welcomePage.isCreateFromTemplate()) {
                  NSISLanguage defaultLanguage =
                      NSISLanguageManager.getInstance().getDefaultLanguage();
                  if (defaultLanguage != null && availableLanguages.contains(defaultLanguage)) {
                    selectedLanguages.add(defaultLanguage);
                  }
                }
              }
            }
            selectedLangViewer.setInput(selectedLanguages);
            availableLanguages.removeAll(selectedLanguages);
            availableLangViewer.setInput(availableLanguages);
          }
        });
  }
  private void createMultiUserGroup(Composite parent) {
    final Group multiUserGroup =
        NSISWizardDialogUtil.createGroup(
            parent, 2, "MultiUser Installation", null, false); // $NON-NLS-1$
    GridData data = (GridData) multiUserGroup.getLayoutData();
    data.verticalAlignment = SWT.FILL;
    data.horizontalAlignment = SWT.FILL;
    data.grabExcessHorizontalSpace = true;

    NSISWizardSettings settings = mWizard.getSettings();

    Composite composite = new Composite(multiUserGroup, SWT.NONE);
    data = new GridData(SWT.FILL, SWT.FILL, true, true);
    composite.setLayoutData(data);

    GridLayout layout = new GridLayout(2, false);
    layout.marginHeight = 0;
    layout.marginWidth = 0;
    composite.setLayout(layout);

    final Button multiUser =
        NSISWizardDialogUtil.createCheckBox(
            composite,
            EclipseNSISPlugin.getResourceString("enable.multiuser.label"), // $NON-NLS-1$
            settings.isMultiUserInstallation(),
            settings.getInstallerType() == INSTALLER_TYPE_MUI2,
            null,
            false);
    multiUser.addSelectionListener(
        new SelectionAdapter() {
          @Override
          public void widgetSelected(SelectionEvent e) {
            boolean selection = multiUser.getSelection();
            mWizard.getSettings().setMultiUserInstallation(selection);
            validateField(MULTIUSER_CHECK);
          }
        });

    final MasterSlaveController m = new MasterSlaveController(multiUser);

    boolean enabled = multiUser.isEnabled() && multiUser.getSelection();

    final Combo execLevel =
        NSISWizardDialogUtil.createCombo(
            composite,
            NSISWizardDisplayValues.MULTIUSER_EXEC_LEVELS,
            settings.getMultiUserExecLevel(),
            true,
            EclipseNSISPlugin.getResourceString("multiuser.exec.level.label"), // $NON-NLS-1$
            enabled,
            m,
            false);
    ((GridData) execLevel.getLayoutData()).horizontalAlignment = SWT.FILL;
    ((GridData) execLevel.getLayoutData()).grabExcessHorizontalSpace = true;

    final Group instModeGroup =
        NSISWizardDialogUtil.createGroup(
            multiUserGroup, 1, "Installation Mode", m, false); // $NON-NLS-1$
    data = (GridData) instModeGroup.getLayoutData();
    data.verticalAlignment = SWT.FILL;
    data.horizontalAlignment = SWT.FILL;
    data.grabExcessHorizontalSpace = true;
    data.horizontalSpan = 1;

    MasterSlaveEnabler mse =
        new MasterSlaveEnabler() {
          public void enabled(Control control, boolean flag) {}

          public boolean canEnable(Control c) {
            return isMultiUser();
          }
        };
    m.addSlave(execLevel, mse);

    enabled = enabled && execLevel.getSelectionIndex() != MULTIUSER_EXEC_LEVEL_STANDARD;

    mse =
        new MasterSlaveEnabler() {
          public void enabled(Control control, boolean flag) {}

          public boolean canEnable(Control c) {
            return isMultiUser()
                && mWizard.getSettings().getMultiUserExecLevel() != MULTIUSER_EXEC_LEVEL_STANDARD;
          }
        };

    execLevel.addSelectionListener(
        new SelectionAdapter() {
          @Override
          public void widgetSelected(SelectionEvent e) {
            mWizard.getSettings().setMultiUserExecLevel(execLevel.getSelectionIndex());
            m.updateSlaves();
            validateField(MULTIUSER_CHECK);
          }
        });

    final Combo instMode =
        NSISWizardDialogUtil.createCombo(
            instModeGroup,
            NSISWizardDisplayValues.MULTIUSER_INSTALL_MODES,
            settings.getMultiUserInstallMode(),
            true,
            EclipseNSISPlugin.getResourceString("multiuser.install.mode.label"),
            enabled,
            m,
            false); //$NON-NLS-1$
    ((GridData) instMode.getLayoutData()).grabExcessHorizontalSpace = true;
    ((GridData) instMode.getLayoutData()).horizontalAlignment = SWT.FILL;
    instMode.addSelectionListener(
        new SelectionAdapter() {
          @Override
          public void widgetSelected(SelectionEvent e) {
            mWizard.getSettings().setMultiUserInstallMode(instMode.getSelectionIndex());
            validateField(MULTIUSER_CHECK);
          }
        });
    m.addSlave(instMode, mse);

    composite = new Composite(instModeGroup, SWT.NONE);
    data = new GridData(SWT.FILL, SWT.FILL, true, true);
    composite.setLayoutData(data);

    layout = new GridLayout(2, true);
    layout.marginHeight = 0;
    layout.marginWidth = 0;
    composite.setLayout(layout);

    final Button instModeRemember =
        NSISWizardDialogUtil.createCheckBox(
            composite,
            EclipseNSISPlugin.getResourceString("multiuser.install.mode.remember.label"),
            settings.isMultiUserInstallModeRemember(), // $NON-NLS-1$
            enabled,
            m,
            false);
    ((GridData) instModeRemember.getLayoutData()).horizontalSpan = 1;
    instModeRemember.addSelectionListener(
        new SelectionAdapter() {
          @Override
          public void widgetSelected(SelectionEvent e) {
            mWizard.getSettings().setMultiUserInstallModeRemember(instModeRemember.getSelection());
            validateField(MULTIUSER_CHECK);
          }
        });
    m.addSlave(instModeRemember, mse);

    final Button instModeAsk =
        NSISWizardDialogUtil.createCheckBox(
            composite,
            EclipseNSISPlugin.getResourceString("multiuser.install.mode.ask.label"),
            settings.isMultiUserInstallModeAsk(), // $NON-NLS-1$
            enabled,
            m,
            false);
    ((GridData) instModeAsk.getLayoutData()).horizontalSpan = 1;
    instModeAsk.addSelectionListener(
        new SelectionAdapter() {
          @Override
          public void widgetSelected(SelectionEvent e) {
            mWizard.getSettings().setMultiUserInstallModeAsk(instModeAsk.getSelection());
            validateField(MULTIUSER_CHECK);
          }
        });
    m.addSlave(instModeAsk, mse);

    m.updateSlaves();
    addPageChangedRunnable(
        new Runnable() {
          public void run() {
            if (isCurrentPage()) {
              NSISWizardDialogUtil.setEnabled(
                  multiUser, mWizard.getSettings().getInstallerType() == INSTALLER_TYPE_MUI2);
              m.updateSlaves();
            }
          }
        });

    mWizard.addSettingsListener(
        new INSISWizardSettingsListener() {
          public void settingsChanged(
              NSISWizardSettings oldSettings, NSISWizardSettings newSettings) {
            NSISWizardSettings settings = mWizard.getSettings();

            multiUser.setSelection(settings.isMultiUserInstallation());
            execLevel.select(settings.getMultiUserExecLevel());
            instMode.select(settings.getMultiUserInstallMode());
            instModeRemember.setSelection(settings.isMultiUserInstallModeRemember());
            instModeAsk.setSelection(settings.isMultiUserInstallModeAsk());
            NSISWizardDialogUtil.setEnabled(
                multiUser, settings.getInstallerType() == INSTALLER_TYPE_MUI2);
            m.updateSlaves();
          }
        });
  }
  /** @see PreferencePage#createContents(Composite) */
  protected Control createContents(Composite ancestor) {
    Composite parent = new Composite(ancestor, SWT.NULL);
    GridLayout layout = new GridLayout();
    layout.numColumns = 2;
    layout.marginHeight = 0;
    layout.marginWidth = 0;
    parent.setLayout(layout);

    // layout the top table & its buttons
    Label label = new Label(parent, SWT.LEFT);
    label.setText(XMLCompareMessages.XMLComparePreference_topTableLabel);
    GridData data = new GridData();
    data.horizontalAlignment = GridData.FILL;
    data.horizontalSpan = 2;
    label.setLayoutData(data);

    fIdMapsTable = new Table(parent, SWT.SINGLE | SWT.BORDER | SWT.FULL_SELECTION);
    fIdMapsTable.setHeaderVisible(true);
    data = new GridData(GridData.FILL_BOTH);
    data.heightHint = fIdMapsTable.getItemHeight() * 4;
    fIdMapsTable.setLayoutData(data);
    fIdMapsTable.addSelectionListener(
        new SelectionAdapter() {
          public void widgetSelected(SelectionEvent e) {
            selectionChanged();
          }
        });

    String column2Text = XMLCompareMessages.XMLComparePreference_topTableColumn2;
    String column3Text = XMLCompareMessages.XMLComparePreference_topTableColumn3;
    ColumnLayoutData columnLayouts[] = {
      new ColumnWeightData(1),
      new ColumnPixelData(convertWidthInCharsToPixels(column2Text.length() + 2), true),
      new ColumnPixelData(convertWidthInCharsToPixels(column3Text.length() + 5), true)
    };
    TableLayout tablelayout = new TableLayout();
    fIdMapsTable.setLayout(tablelayout);
    for (int i = 0; i < 3; i++) tablelayout.addColumnData(columnLayouts[i]);
    TableColumn column = new TableColumn(fIdMapsTable, SWT.NONE);
    column.setText(XMLCompareMessages.XMLComparePreference_topTableColumn1);
    column = new TableColumn(fIdMapsTable, SWT.NONE);
    column.setText(column2Text);
    column = new TableColumn(fIdMapsTable, SWT.NONE);
    column.setText(column3Text);

    fillIdMapsTable();

    Composite buttons = new Composite(parent, SWT.NULL);
    buttons.setLayout(new GridLayout());
    data = new GridData();
    data.verticalAlignment = GridData.FILL;
    data.horizontalAlignment = GridData.FILL;
    buttons.setLayoutData(data);

    fAddIdMapButton = new Button(buttons, SWT.PUSH);
    fAddIdMapButton.setText(XMLCompareMessages.XMLComparePreference_topAdd);
    fAddIdMapButton.addSelectionListener(
        new SelectionAdapter() {
          public void widgetSelected(SelectionEvent e) {
            addIdMap(fAddIdMapButton.getShell());
          }
        });
    data = new GridData();
    data.horizontalAlignment = GridData.FILL;
    // data.heightHint = convertVerticalDLUsToPixels(IDialogConstants.BUTTON_HEIGHT);
    int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
    data.widthHint =
        Math.max(widthHint, fAddIdMapButton.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x);
    fAddIdMapButton.setLayoutData(data);

    fRenameIdMapButton = new Button(buttons, SWT.PUSH);
    fRenameIdMapButton.setText(XMLCompareMessages.XMLComparePreference_topRename);
    fRenameIdMapButton.addSelectionListener(
        new SelectionAdapter() {
          public void widgetSelected(SelectionEvent e) {
            renameIdMap(fRenameIdMapButton.getShell());
          }
        });
    data = new GridData();
    data.horizontalAlignment = GridData.FILL;
    // data.heightHint = convertVerticalDLUsToPixels(IDialogConstants.BUTTON_HEIGHT);
    widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
    data.widthHint =
        Math.max(widthHint, fAddIdMapButton.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x);
    fRenameIdMapButton.setLayoutData(data);

    fRemoveIdMapButton = new Button(buttons, SWT.PUSH);
    fRemoveIdMapButton.setText(XMLCompareMessages.XMLComparePreference_topRemove);
    fRemoveIdMapButton.addSelectionListener(
        new SelectionAdapter() {
          public void widgetSelected(SelectionEvent e) {
            removeIdMap(fRemoveIdMapButton.getShell());
          }
        });
    data = new GridData();
    data.horizontalAlignment = GridData.FILL;
    // data.heightHint = convertVerticalDLUsToPixels(IDialogConstants.BUTTON_HEIGHT);
    widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
    data.widthHint =
        Math.max(widthHint, fRemoveIdMapButton.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x);
    fRemoveIdMapButton.setLayoutData(data);

    createSpacer(buttons);

    fEditIdMapButton = new Button(buttons, SWT.PUSH);
    fEditIdMapButton.setText(XMLCompareMessages.XMLComparePreference_topEdit);
    fEditIdMapButton.addSelectionListener(
        new SelectionAdapter() {
          public void widgetSelected(SelectionEvent e) {
            editIdMap(fEditIdMapButton.getShell());
          }
        });
    data = new GridData();
    data.horizontalAlignment = GridData.FILL;
    // data.heightHint = convertVerticalDLUsToPixels(IDialogConstants.BUTTON_HEIGHT);
    widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
    data.widthHint =
        Math.max(widthHint, fEditIdMapButton.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x);
    fEditIdMapButton.setLayoutData(data);

    // Spacer
    label = new Label(parent, SWT.LEFT);
    data = new GridData();
    data.horizontalAlignment = GridData.FILL;
    data.horizontalSpan = 2;
    label.setLayoutData(data);

    // layout the middle table & its buttons
    label = new Label(parent, SWT.LEFT);
    label.setText(XMLCompareMessages.XMLComparePreference_middleTableLabel);
    data = new GridData();
    data.horizontalAlignment = GridData.FILL;
    data.horizontalSpan = 2;
    label.setLayoutData(data);

    fMappingsTable = new Table(parent, SWT.SINGLE | SWT.BORDER | SWT.FULL_SELECTION);
    fMappingsTable.setHeaderVisible(true);
    data = new GridData(GridData.FILL_BOTH);
    data.heightHint = fMappingsTable.getItemHeight() * 4;
    data.widthHint = convertWidthInCharsToPixels(70);
    fMappingsTable.setLayoutData(data);

    column3Text = XMLCompareMessages.XMLComparePreference_middleTableColumn3;
    String column4Text = XMLCompareMessages.XMLComparePreference_middleTableColumn4;
    columnLayouts =
        new ColumnLayoutData[] {
          new ColumnWeightData(10),
          new ColumnWeightData(18),
          new ColumnPixelData(convertWidthInCharsToPixels(column3Text.length() + 1), true),
          new ColumnPixelData(convertWidthInCharsToPixels(column4Text.length() + 3), true)
        };
    tablelayout = new TableLayout();
    fMappingsTable.setLayout(tablelayout);
    for (int i = 0; i < 4; i++) tablelayout.addColumnData(columnLayouts[i]);
    column = new TableColumn(fMappingsTable, SWT.NONE);
    column.setText(XMLCompareMessages.XMLComparePreference_middleTableColumn1);
    column = new TableColumn(fMappingsTable, SWT.NONE);
    column.setText(XMLCompareMessages.XMLComparePreference_middleTableColumn2);
    column = new TableColumn(fMappingsTable, SWT.NONE);
    column.setText(column3Text);
    column = new TableColumn(fMappingsTable, SWT.NONE);
    column.setText(column4Text);

    buttons = new Composite(parent, SWT.NULL);
    buttons.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING));
    layout = new GridLayout();
    layout.marginHeight = 0;
    layout.marginWidth = 0;
    buttons.setLayout(layout);

    fNewMappingsButton = new Button(buttons, SWT.PUSH);
    fNewMappingsButton.setLayoutData(getButtonGridData(fNewMappingsButton));
    fNewMappingsButton.setText(XMLCompareMessages.XMLComparePreference_middleNew);
    fNewMappingsButton.addSelectionListener(
        new SelectionAdapter() {
          public void widgetSelected(SelectionEvent e) {
            addMapping(fAddIdMapButton.getShell());
          }
        });

    fEditMappingsButton = new Button(buttons, SWT.PUSH);
    fEditMappingsButton.setLayoutData(getButtonGridData(fEditMappingsButton));
    fEditMappingsButton.setText(XMLCompareMessages.XMLComparePreference_middleEdit);
    fEditMappingsButton.addSelectionListener(
        new SelectionAdapter() {
          public void widgetSelected(SelectionEvent e) {
            editMapping(fEditMappingsButton.getShell());
          }
        });

    fRemoveMappingsButton = new Button(buttons, SWT.PUSH);
    fRemoveMappingsButton.setLayoutData(getButtonGridData(fRemoveMappingsButton));
    fRemoveMappingsButton.setText(XMLCompareMessages.XMLComparePreference_middleRemove);
    fRemoveMappingsButton.addSelectionListener(
        new SelectionAdapter() {
          public void widgetSelected(SelectionEvent e) {
            removeMapping(fRemoveMappingsButton.getShell());
          }
        });

    createSpacer(buttons);

    // layout the botton table & its buttons
    label = new Label(parent, SWT.LEFT);
    label.setText(XMLCompareMessages.XMLComparePreference_bottomTableLabel);
    data = new GridData();
    data.horizontalAlignment = GridData.FILL;
    data.horizontalSpan = 2;
    label.setLayoutData(data);

    fOrderedTable = new Table(parent, SWT.SINGLE | SWT.BORDER | SWT.FULL_SELECTION);
    fOrderedTable.setHeaderVisible(true);
    data = new GridData(GridData.FILL_BOTH);
    data.heightHint = fOrderedTable.getItemHeight() * 2;
    data.widthHint = convertWidthInCharsToPixels(70);
    fOrderedTable.setLayoutData(data);

    columnLayouts = new ColumnLayoutData[] {new ColumnWeightData(1), new ColumnWeightData(1)};
    tablelayout = new TableLayout();
    fOrderedTable.setLayout(tablelayout);
    for (int i = 0; i < 2; i++) tablelayout.addColumnData(columnLayouts[i]);
    column = new TableColumn(fOrderedTable, SWT.NONE);
    column.setText(XMLCompareMessages.XMLComparePreference_bottomTableColumn1);
    column = new TableColumn(fOrderedTable, SWT.NONE);
    column.setText(XMLCompareMessages.XMLComparePreference_bottomTableColumn2);

    buttons = new Composite(parent, SWT.NULL);
    buttons.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING));
    layout = new GridLayout();
    layout.marginHeight = 0;
    layout.marginWidth = 0;
    buttons.setLayout(layout);

    fNewOrderedButton = new Button(buttons, SWT.PUSH);
    fNewOrderedButton.setLayoutData(getButtonGridData(fNewOrderedButton));
    fNewOrderedButton.setText(XMLCompareMessages.XMLComparePreference_bottomNew);
    fNewOrderedButton.addSelectionListener(
        new SelectionAdapter() {
          public void widgetSelected(SelectionEvent e) {
            addOrdered(fNewOrderedButton.getShell());
          }
        });

    fEditOrderedButton = new Button(buttons, SWT.PUSH);
    fEditOrderedButton.setLayoutData(getButtonGridData(fEditOrderedButton));
    fEditOrderedButton.setText(XMLCompareMessages.XMLComparePreference_bottomEdit);
    fEditOrderedButton.addSelectionListener(
        new SelectionAdapter() {
          public void widgetSelected(SelectionEvent e) {
            editOrdered(fEditOrderedButton.getShell());
          }
        });

    fRemoveOrderedButton = new Button(buttons, SWT.PUSH);
    fRemoveOrderedButton.setLayoutData(getButtonGridData(fRemoveOrderedButton));
    fRemoveOrderedButton.setText(XMLCompareMessages.XMLComparePreference_bottomRemove);
    fRemoveOrderedButton.addSelectionListener(
        new SelectionAdapter() {
          public void widgetSelected(SelectionEvent e) {
            removeOrdered(fRemoveOrderedButton.getShell());
          }
        });

    createSpacer(buttons);

    fIdMapsTable.setSelection(0);
    fIdMapsTable.setFocus();
    selectionChanged();

    return parent;
  }