@Override
  public Control createPageContents(Composite parent) {
    XComposite mainComposite = new XComposite(parent, SWT.NONE);
    mainComposite.getGridLayout().numColumns = 1;

    linkHandlerFactoryTreeComposite =
        new SelectIssueLinkHandlerFactoryTreeComposite(
            mainComposite, mainComposite.getBorderStyle(), null);

    for (Object l : selectionChangedListeners.getListeners())
      linkHandlerFactoryTreeComposite.addSelectionChangedListener((ISelectionChangedListener) l);

    linkHandlerFactoryTreeComposite.addDoubleClickListener(
        new IDoubleClickListener() {
          @Override
          public void doubleClick(DoubleClickEvent e) {
            if (e.getSelection() instanceof TreeSelection) {
              Object firstElement = ((TreeSelection) e.getSelection()).getFirstElement();
              if (firstElement instanceof IssueLinkHandlerFactory<?, ?>)
                getContainer().showPage(getNextPage());
              else {
                TreeViewer tv = linkHandlerFactoryTreeComposite.getTreeViewer();
                if (tv.getExpandedState(firstElement)) {
                  tv.collapseToLevel(firstElement, 1);
                } else {
                  tv.expandToLevel(firstElement, 1);
                }
              }
            }
          }
        });
    linkHandlerFactoryTreeComposite.getTreeViewer().expandAll();

    return mainComposite;
  }
  @Override
  protected void createComposite() {
    this.setLayout(new GridLayout(3, false));

    XComposite mainComposite =
        new XComposite(this, SWT.NONE, LayoutMode.TIGHT_WRAPPER, LayoutDataMode.GRID_DATA);
    mainComposite.getGridLayout().numColumns = 2;

    new Label(mainComposite, SWT.NONE)
        .setText(
            Messages.getString(
                "org.nightlabs.jfire.issuetracking.ui.overview.IssueFilterCompositeStateRelated.issueTypeLabel")); //$NON-NLS-1$
    processDefinitionsCombo =
        new XComboComposite<ProcessDefinition>(
            mainComposite, SWT.NONE | SWT.READ_ONLY, stateDefinitionLabelProvider);
    GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
    processDefinitionsCombo.setLayoutData(gridData);
    processDefinitionsCombo.setLabelProvider(processDefinitionLabelProvider);
    processDefinitionsCombo.addSelectionChangedListener(
        new ISelectionChangedListener() {
          @Override
          public void selectionChanged(SelectionChangedEvent e) {
            stateDefinitionsCombo.selectElement(ALL_STATE_DEFINITION);
            stateDefinitionsComboSelected();

            ProcessDefinition selectedProcessDefinition =
                processDefinitionsCombo.getSelectedElement();
            boolean isSelectAll = selectedProcessDefinition.equals(ALL_PROCESS_DEFINITION);
            if (isSelectAll) {
              getQuery().setProcessDefinitionID(null);
              getQuery().setFieldEnabled(IssueQuery.FieldName.processDefinitionID, false);
            } else {
              getQuery()
                  .setProcessDefinitionID(
                      (ProcessDefinitionID) JDOHelper.getObjectId(selectedProcessDefinition));
              getQuery().setFieldEnabled(IssueQuery.FieldName.processDefinitionID, true);
            }

            stateDefinitionsCombo.removeAll();
            stateDefinitionsCombo.addElement(ALL_STATE_DEFINITION);
            stateDefinitionsCombo.selectElementByIndex(0);

            List<StateDefinition> stateDefinitionList =
                processDefinition2StateDefinitions.get(selectedProcessDefinition);
            if (selectedProcessDefinition.equals(ALL_PROCESS_DEFINITION)) {
              for (List<StateDefinition> l : processDefinition2StateDefinitions.values()) {
                stateDefinitionsCombo.addElements(l);
              }
            } else {
              stateDefinitionsCombo.addElements(stateDefinitionList);
            }
          }
        });

    new Label(mainComposite, SWT.NONE)
        .setText(
            Messages.getString(
                "org.nightlabs.jfire.issuetracking.ui.overview.IssueFilterCompositeStateRelated.stateLabel")); //$NON-NLS-1$
    stateDefinitionsCombo =
        new XComboComposite<StateDefinition>(
            mainComposite, SWT.NONE | SWT.READ_ONLY, stateDefinitionLabelProvider);
    gridData = new GridData(GridData.FILL_HORIZONTAL);
    stateDefinitionsCombo.setLayoutData(gridData);
    stateDefinitionsCombo.addSelectionChangedListener(
        new ISelectionChangedListener() {
          @Override
          public void selectionChanged(SelectionChangedEvent e) {
            stateDefinitionsComboSelected();
          }
        });

    loadProperties();
  }
  /**
   * Construct a new {@link GridLayoutConfigComposite}.
   *
   * @param parent The parent Composite.
   * @param style The style to apply to the new Composite.
   */
  public GridLayoutConfigComposite(Composite parent, int style) {
    super(parent, style);
    propertyChangeSupport = new PropertyChangeSupport(this);
    XComposite layoutWrapper =
        new XComposite(
            this, SWT.NONE, LayoutMode.TIGHT_WRAPPER, LayoutDataMode.GRID_DATA_HORIZONTAL);
    layoutWrapper.getGridLayout().numColumns = 2;
    layoutWrapper.getGridLayout().makeColumnsEqualWidth = false;
    Label numColLabel = new Label(layoutWrapper, SWT.NONE);
    numColLabel.setText(
        Messages.getString(
            "org.nightlabs.clientui.ui.layout.GridLayoutConfigComposite.label.numberOfColumns.text")); //$NON-NLS-1$

    Button previewButton = new Button(layoutWrapper, SWT.PUSH);
    GridData previewGD = new GridData();
    previewGD.verticalSpan = 3;
    previewGD.verticalAlignment = SWT.END;
    previewButton.setLayoutData(previewGD);
    previewButton.setText(
        Messages.getString(
            "org.nightlabs.clientui.ui.layout.GridLayoutConfigComposite.button.preview.text")); //$NON-NLS-1$
    previewButton.addSelectionListener(
        new SelectionAdapter() {
          @Override
          public void widgetSelected(SelectionEvent e) {
            if (gridLayoutConfig != null) {
              gridDataEntryConfigComposite.updateGridDataEntry();
              updateGridLayout();
              GridLayoutConfigPreviewDialog dlg =
                  new GridLayoutConfigPreviewDialog(getShell(), null, gridLayoutConfig);
              dlg.open();
            }
          }
        });

    numColText = new Text(layoutWrapper, getBorderStyle());
    GridData gd = new GridData();
    gd.widthHint = 80;
    numColText.setLayoutData(gd);
    numColText.addModifyListener(textListener);

    colsEqualWidthCB = new Button(layoutWrapper, SWT.CHECK);
    colsEqualWidthCB.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
    colsEqualWidthCB.setText(
        Messages.getString(
            "org.nightlabs.clientui.ui.layout.GridLayoutConfigComposite.button.columnsEqualWidth.text")); //$NON-NLS-1$
    colsEqualWidthCB.addSelectionListener(cbListener);

    XComposite bottomWrapper = new XComposite(this, SWT.NONE, LayoutMode.TIGHT_WRAPPER);
    bottomWrapper.getGridLayout().numColumns = 2;
    bottomWrapper.getGridLayout().makeColumnsEqualWidth = false;

    gridDataEntryTable = new GridDataEntryTable(bottomWrapper, SWT.NONE);
    gridDataEntryTable.addSelectionChangedListener(selectionChangeListener);

    XComposite buttonWrapper = new XComposite(bottomWrapper, SWT.NONE);

    addEntryButton = new Button(buttonWrapper, SWT.PUSH);
    addEntryButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
    addEntryButton.setText(
        Messages.getString(
            "org.nightlabs.clientui.ui.layout.GridLayoutConfigComposite.button.add.text")); //$NON-NLS-1$
    addEntryButton.addSelectionListener(
        new SelectionAdapter() {
          @Override
          public void widgetSelected(SelectionEvent e) {
            if (gridLayoutConfig != null) {
              IGridDataEntry entry = gridLayoutConfig.addGridDataEntry();
              if (entry != null) {
                refreshEntryTable();
                gridDataEntryTable.setSelection(new StructuredSelection(entry), true);
                fireGridLayoutConfigChanged();
              }
            }
          }
        });

    removeEntryButton = new Button(buttonWrapper, SWT.PUSH);
    removeEntryButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
    removeEntryButton.setText(
        Messages.getString(
            "org.nightlabs.clientui.ui.layout.GridLayoutConfigComposite.button.remove.text")); //$NON-NLS-1$
    removeEntryButton.addSelectionListener(
        new SelectionAdapter() {
          @Override
          public void widgetSelected(SelectionEvent e) {
            if (gridLayoutConfig != null) {
              int index = gridDataEntryTable.getSelectionIndex();

              Collection<IGridDataEntry> entries = gridDataEntryTable.getSelectedElements();
              for (IGridDataEntry entry : entries) {
                gridLayoutConfig.removeGridDataEntry(entry);
              }
              refreshEntryTable();

              if (!gridDataEntryTable.getElements().isEmpty()) {
                gridDataEntryTable.select(index);
              }
              fireGridLayoutConfigChanged();
            }
          }
        });

    moveEntryUpButton = new Button(buttonWrapper, SWT.PUSH);
    moveEntryUpButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
    moveEntryUpButton.setText(
        Messages.getString(
            "org.nightlabs.clientui.ui.layout.GridLayoutConfigComposite.button.up.text")); //$NON-NLS-1$
    moveEntryUpButton.addSelectionListener(
        new SelectionAdapter() {
          @Override
          public void widgetSelected(SelectionEvent e) {
            if (gridLayoutConfig != null) {
              Collection<IGridDataEntry> entries = gridDataEntryTable.getSelectedElements();
              for (IGridDataEntry entry : entries) {
                if (!gridLayoutConfig.moveEntryUp(entry)) {
                  break;
                }
              }
              refreshEntryTable();
              fireGridLayoutConfigChanged();
            }
          }
        });

    moveEntryDownButton = new Button(buttonWrapper, SWT.PUSH);
    moveEntryDownButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
    moveEntryDownButton.setText(
        Messages.getString(
            "org.nightlabs.clientui.ui.layout.GridLayoutConfigComposite.button.down.text")); //$NON-NLS-1$
    moveEntryDownButton.addSelectionListener(
        new SelectionAdapter() {
          @Override
          public void widgetSelected(SelectionEvent e) {
            if (gridLayoutConfig != null) {
              List<IGridDataEntry> entries =
                  new ArrayList<IGridDataEntry>(gridDataEntryTable.getSelectedElements());
              Collections.reverse(entries);
              for (IGridDataEntry entry : entries) {
                if (!gridLayoutConfig.moveEntryDown(entry)) {
                  break;
                }
              }
              refreshEntryTable();
              fireGridLayoutConfigChanged();
            }
          }
        });

    gridDataEntryConfigComposite =
        new GridDataEntryConfigComposite(buttonWrapper, SWT.NONE, LayoutDataMode.NONE);
    GridData gdEntry = new GridData(GridData.FILL_VERTICAL);
    gdEntry.horizontalAlignment = SWT.FILL;
    gdEntry.widthHint = 50;
    gridDataEntryConfigComposite.setLayoutData(gdEntry);
    gridDataEntryConfigComposite.addPropertyChangeListener(entryListener);
  }