package org.nightlabs.jfire.issuetracking.ui.overview; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Set; import javax.jdo.FetchPlan; import javax.jdo.JDOHelper; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.nightlabs.base.ui.composite.XComboComposite; import org.nightlabs.base.ui.composite.XComposite; import org.nightlabs.base.ui.exceptionhandler.ExceptionHandlerRegistry; import org.nightlabs.base.ui.job.Job; import org.nightlabs.jdo.NLJDOHelper; import org.nightlabs.jdo.query.QueryEvent; import org.nightlabs.jdo.query.QueryProvider; import org.nightlabs.jdo.query.AbstractSearchQuery.FieldChangeCarrier; import org.nightlabs.jfire.base.ui.search.AbstractQueryFilterComposite; import org.nightlabs.jfire.issue.IssueLinkType; import org.nightlabs.jfire.issue.dao.IssueLinkTypeDAO; import org.nightlabs.jfire.issue.id.IssueLinkTypeID; import org.nightlabs.jfire.issue.query.IssueQuery; import org.nightlabs.jfire.issuetracking.ui.resource.Messages; import org.nightlabs.jfire.organisation.Organisation; import org.nightlabs.progress.NullProgressMonitor; import org.nightlabs.progress.ProgressMonitor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Chairat Kongarayawetchakun <!-- chairat [AT] nightlabs [DOT] de --> * */ public class IssueFilterCompositeIssueLinkRelated extends AbstractQueryFilterComposite<IssueQuery> { private static final Logger logger = LoggerFactory.getLogger(IssueFilterCompositeIssueLinkRelated.class); private XComboComposite<IssueLinkType> issueLinkTypeCombo; private Object mutex = new Object(); /** * Used to defer the selection of an element until the loading job is finished. */ private volatile IssueLinkType selectedIssueLinkType; /** * @param parent * The parent to instantiate this filter into. * @param style * The style to apply. * @param layoutMode * The layout mode to use. See {@link XComposite.LayoutMode}. * @param layoutDataMode * The layout data mode to use. See {@link XComposite.LayoutDataMode}. * @param queryProvider * The queryProvider to use. It may be <code>null</code>, but the caller has to * ensure, that it is set before {@link #getQuery()} is called! */ public IssueFilterCompositeIssueLinkRelated(Composite parent, int style, LayoutMode layoutMode, LayoutDataMode layoutDataMode, QueryProvider<? super IssueQuery> queryProvider) { super(parent, style, layoutMode, layoutDataMode, queryProvider); prepareProperties(); createComposite(); } /** * @param parent * The parent to instantiate this filter into. * @param style * The style to apply. * @param queryProvider * The queryProvider to use. It may be <code>null</code>, but the caller has to * ensure, that it is set before {@link #getQuery()} is called! */ public IssueFilterCompositeIssueLinkRelated(Composite parent, int style, QueryProvider<? super IssueQuery> queryProvider) { super(parent, style, queryProvider); prepareProperties(); createComposite(); } @Override public Class<IssueQuery> getQueryClass() { return IssueQuery.class; } @Override protected void createComposite() { GridLayout gridLayout = new GridLayout(2, false); gridLayout.verticalSpacing = 10; this.setLayout(gridLayout); this.setLayoutData(new GridData(GridData.FILL_BOTH)); new Label(this, SWT.NONE).setText(Messages.getString("org.nightlabs.jfire.issuetracking.ui.overview.IssueFilterCompositeIssueLinkRelated.label.linkType.text")); //$NON-NLS-1$ issueLinkTypeCombo = new XComboComposite<IssueLinkType>(this, getBorderStyle() | SWT.READ_ONLY); issueLinkTypeCombo.setLabelProvider(labelProvider); issueLinkTypeCombo.addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent e) { final IssueLinkType selectedIssueLinkType = issueLinkTypeCombo.getSelectedElement(); if (selectedIssueLinkType.equals(ISSUE_LINK_TYPE_ALL)) { getQuery().setIssueLinkTypeID(null); getQuery().setFieldEnabled(IssueQuery.FieldName.issueLinkTypeID, false); } else { getQuery().setIssueLinkTypeID((IssueLinkTypeID) JDOHelper.getObjectId(selectedIssueLinkType)); getQuery().setFieldEnabled(IssueQuery.FieldName.issueLinkTypeID, true); } } }); loadProperties(); } private LabelProvider labelProvider = new LabelProvider() { @Override public String getText(Object element) { if (element instanceof IssueLinkType) { IssueLinkType issueLinkType = (IssueLinkType) element; return issueLinkType.getName().getText(); } return ""; //$NON-NLS-1$ }; }; @Override protected void updateUI(QueryEvent event, List<FieldChangeCarrier> changedFields) { if (Display.getCurrent() == null) throw new IllegalStateException("Thread mismatch! Must be called on UI thread!"); for (FieldChangeCarrier changedField : event.getChangedFields()) { if (IssueQuery.FieldName.issueLinkTypeID.equals(changedField.getPropertyName())) { IssueLinkTypeID newIssueLinkTypeID = (IssueLinkTypeID) changedField.getNewValue(); if (newIssueLinkTypeID == null) { issueLinkTypeCombo.setSelection(ISSUE_LINK_TYPE_ALL); selectedIssueLinkType = null; logger.info("updateUI:1: selectedIssueLinkType == NULL"); } else { final IssueLinkType newIssueLinkType = IssueLinkTypeDAO.sharedInstance().getIssueLinkType( newIssueLinkTypeID, new String[] { IssueLinkType.FETCH_GROUP_NAME, FetchPlan.DEFAULT }, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT, new NullProgressMonitor() ); issueLinkTypeCombo.setSelection(newIssueLinkType); selectedIssueLinkType = newIssueLinkType; logger.info("updateUI:2: selectedIssueLinkType == " + selectedIssueLinkType); } } else if (getEnableFieldName(IssueQuery.FieldName.issueLinkTypeID).equals(changedField.getPropertyName())) { boolean isActive = (Boolean) changedField.getNewValue(); setSearchSectionActive(isActive/*getQuery().isFieldEnabled(IssueQuery.FieldName.issueLinkTypeID)*/); if (!isActive) { getQuery().setIssueLinkTypeID(null); issueLinkTypeCombo.setSelection(ISSUE_LINK_TYPE_ALL); selectedIssueLinkType = null; } logger.info("updateUI:3: selectedIssueLinkType == " + isActive); } } // for (FieldChangeCarrier changedField : event.getChangedFields()) } private static final String[] FETCH_GROUPS_ISSUE_LINK_TYPE = { IssueLinkType.FETCH_GROUP_NAME, FetchPlan.DEFAULT }; private static IssueLinkType ISSUE_LINK_TYPE_ALL = new IssueLinkType(Organisation.DEV_ORGANISATION_ID, "Issue_Link_Type_All"); //$NON-NLS-1$ private void prepareProperties(){ ISSUE_LINK_TYPE_ALL.getName().setText(Locale.ENGLISH.getLanguage(), Messages.getString("org.nightlabs.jfire.issuetracking.ui.overview.IssueFilterCompositeIssueLinkRelated.issueLinkType.all.text")); //$NON-NLS-1$ } private void loadProperties(){ Job loadJob = new Job(Messages.getString("org.nightlabs.jfire.issuetracking.ui.overview.IssueFilterCompositeIssueLinkRelated.job.loadingIssueLinkProperties.text")) { //$NON-NLS-1$ @Override protected IStatus run(final ProgressMonitor monitor) { synchronized (mutex) { logger.debug("Load Job running...."); //$NON-NLS-1$ } try { try { final List<IssueLinkType> issueLinkTypeList = new ArrayList<IssueLinkType>(IssueLinkTypeDAO.sharedInstance(). getIssueLinkTypes(FETCH_GROUPS_ISSUE_LINK_TYPE, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT, monitor)); Display.getDefault().asyncExec(new Runnable() { public void run() { issueLinkTypeCombo.removeAll(); issueLinkTypeCombo.addElement(ISSUE_LINK_TYPE_ALL); for (IssueLinkType issueLinkType : issueLinkTypeList) { issueLinkTypeCombo.addElement(issueLinkType); } if (selectedIssueLinkType == null) issueLinkTypeCombo.setSelection(ISSUE_LINK_TYPE_ALL); else { issueLinkTypeCombo.setSelection(selectedIssueLinkType); } logger.info("Display.getDefault().asyncExec: " + issueLinkTypeList); } }); }catch (Exception e1) { ExceptionHandlerRegistry.asyncHandleException(e1); throw new RuntimeException(e1); } return Status.OK_STATUS; } finally { synchronized (mutex) { logger.debug("Load Job finished."); //$NON-NLS-1$ } } } }; loadJob.schedule(); } private static final Set<String> fieldNames = Collections.singleton(IssueQuery.FieldName.issueLinkTypeID); @Override protected Set<String> getFieldNames() { return fieldNames; } /** * Group ID for storing active states in the query. */ public static final String FILTER_GROUP_ID = "IssueFilterCompositeIssueLinkRelated"; //$NON-NLS-1$ @Override protected String getGroupID() { return FILTER_GROUP_ID; } }