/******************************************************************************* * Copyright (c) 2011 Red Hat 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: * David Green <david.green@tasktop.com> - initial contribution * Christian Trutz <christian.trutz@gmail.com> - initial contribution * Chris Aniszczyk <caniszczyk@gmail.com> - initial contribution *******************************************************************************/ package org.eclipse.mylyn.internal.github.ui.issue; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.LinkedList; import java.util.List; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.egit.github.core.Milestone; import org.eclipse.egit.github.core.service.IssueService; import org.eclipse.egit.github.core.util.LabelComparator; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.operation.IRunnableContext; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.CheckboxTableViewer; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.mylyn.commons.core.ICoreRunnable; import org.eclipse.mylyn.commons.net.Policy; import org.eclipse.mylyn.commons.ui.CommonUiUtil; import org.eclipse.mylyn.internal.github.core.QueryUtils; import org.eclipse.mylyn.internal.github.core.issue.IssueConnector; import org.eclipse.mylyn.internal.github.ui.GitHubImages; import org.eclipse.mylyn.internal.github.ui.GitHubRepositoryQueryPage; import org.eclipse.mylyn.tasks.core.IRepositoryQuery; import org.eclipse.mylyn.tasks.core.TaskRepository; import org.eclipse.mylyn.tasks.ui.TasksUiImages; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; 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.events.SelectionListener; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import org.eclipse.swt.widgets.ToolBar; import org.eclipse.swt.widgets.ToolItem; import org.eclipse.ui.PlatformUI; /** * GitHub issue repository query page class. */ public class IssueRepositoryQueryPage extends GitHubRepositoryQueryPage { private Button openButton; private Button closedButton; private Text titleText; private Text assigneeText; private Text mentionText; private Combo milestoneCombo; private CheckboxTableViewer labelsViewer; private List<Milestone> milestones; private SelectionListener completeListener = new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { setPageComplete(isPageComplete()); } }; /** * @param pageName * @param taskRepository * @param query */ public IssueRepositoryQueryPage(String pageName, TaskRepository taskRepository, IRepositoryQuery query) { super(pageName, taskRepository, query); setDescription(Messages.IssueRepositoryQueryPage_Description); setPageComplete(false); } /** * @param taskRepository * @param query */ public IssueRepositoryQueryPage(TaskRepository taskRepository, IRepositoryQuery query) { this("issueQueryPage", taskRepository, query); //$NON-NLS-1$ } private void createLabelsArea(Composite parent) { Group labelsArea = new Group(parent, SWT.NONE); labelsArea.setText(Messages.IssueRepositoryQueryPage_LabelsLabel); GridDataFactory.fillDefaults().grab(true, true).applyTo(labelsArea); GridLayoutFactory.swtDefaults().applyTo(labelsArea); labelsViewer = CheckboxTableViewer.newCheckList(labelsArea, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL); GridDataFactory.fillDefaults().grab(true, true).hint(100, 80) .applyTo(labelsViewer.getControl()); labelsViewer.setContentProvider(ArrayContentProvider.getInstance()); labelsViewer.setLabelProvider(new LabelProvider() { public Image getImage(Object element) { return GitHubImages.get(GitHubImages.GITHUB_ISSUE_LABEL_OBJ); } }); labelsViewer .addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { setPageComplete(isPageComplete()); } }); } private void createOptionsArea(Composite parent) { Composite optionsArea = new Composite(parent, SWT.NONE); GridLayoutFactory.fillDefaults().numColumns(2).applyTo(optionsArea); GridDataFactory.fillDefaults().grab(true, true).applyTo(optionsArea); Composite statusArea = new Composite(optionsArea, SWT.NONE); GridLayoutFactory.fillDefaults().numColumns(4).equalWidth(false) .applyTo(statusArea); GridDataFactory.fillDefaults().grab(true, false).span(2, 1) .applyTo(statusArea); new Label(statusArea, SWT.NONE) .setText(Messages.IssueRepositoryQueryPage_StatusLabel); openButton = new Button(statusArea, SWT.CHECK); openButton.setSelection(true); openButton.setText(Messages.IssueRepositoryQueryPage_StatusOpen); openButton.addSelectionListener(completeListener); closedButton = new Button(statusArea, SWT.CHECK); closedButton.setSelection(true); closedButton.setText(Messages.IssueRepositoryQueryPage_StatusClosed); closedButton.addSelectionListener(completeListener); ToolBar toolbar = new ToolBar(statusArea, SWT.FLAT); ToolItem updateItem = new ToolItem(toolbar, SWT.PUSH); final Image updateImage = TasksUiImages.REPOSITORY_UPDATE_CONFIGURATION .createImage(); toolbar.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { updateImage.dispose(); } }); updateItem.setImage(updateImage); updateItem .setToolTipText(Messages.IssueRepositoryQueryPage_TooltipUpdateRepository); GridDataFactory.fillDefaults().align(SWT.END, SWT.FILL) .grab(true, false).applyTo(toolbar); updateItem.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { refreshRepository(); } }); Label milestonesLabel = new Label(optionsArea, SWT.NONE); milestonesLabel .setText(Messages.IssueRepositoryQueryPage_MilestoneLabel); milestoneCombo = new Combo(optionsArea, SWT.DROP_DOWN | SWT.READ_ONLY); GridDataFactory.fillDefaults().grab(true, false) .applyTo(milestoneCombo); Label assigneeLabel = new Label(optionsArea, SWT.NONE); assigneeLabel.setText(Messages.IssueRepositoryQueryPage_AssigneeLabel); assigneeText = new Text(optionsArea, SWT.BORDER | SWT.SINGLE); GridDataFactory.fillDefaults().grab(true, false).applyTo(assigneeText); Label mentionLabel = new Label(optionsArea, SWT.NONE); mentionLabel.setText(Messages.IssueRepositoryQueryPage_MentionsLabel); mentionText = new Text(optionsArea, SWT.BORDER | SWT.SINGLE); GridDataFactory.fillDefaults().grab(true, false).applyTo(mentionText); } /** * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite) */ public void createControl(Composite parent) { Composite displayArea = new Composite(parent, SWT.NONE); GridLayoutFactory.fillDefaults().numColumns(2).equalWidth(true) .applyTo(displayArea); GridDataFactory.fillDefaults().grab(true, true).applyTo(displayArea); if (!inSearchContainer()) { Composite titleArea = new Composite(displayArea, SWT.NONE); GridLayoutFactory.fillDefaults().numColumns(2).applyTo(titleArea); GridDataFactory.fillDefaults().grab(true, false).span(2, 1) .applyTo(titleArea); new Label(titleArea, SWT.NONE) .setText(Messages.IssueRepositoryQueryPage_TitleLabel); titleText = new Text(titleArea, SWT.SINGLE | SWT.BORDER); GridDataFactory.fillDefaults().grab(true, false).applyTo(titleText); titleText.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { setPageComplete(isPageComplete()); } }); } createOptionsArea(displayArea); createLabelsArea(displayArea); loadRepository(); initialize(); setControl(displayArea); } private void initialize() { IRepositoryQuery query = getQuery(); if (query == null) return; String milestoneNumber = query .getAttribute(IssueService.FILTER_MILESTONE); if (milestoneNumber != null && milestones != null) { int index = 0; for (Milestone milestone : milestones) { index++; if (milestoneNumber.equals(Integer.toString(milestone .getNumber()))) { milestoneCombo.select(index); break; } } } titleText.setText(query.getSummary()); labelsViewer.setCheckedElements(QueryUtils.getAttributes( IssueService.FILTER_LABELS, query).toArray()); List<String> status = QueryUtils.getAttributes( IssueService.FILTER_STATE, query); closedButton.setSelection(status.contains(IssueService.STATE_CLOSED)); openButton.setSelection(status.contains(IssueService.STATE_OPEN)); String assignee = query.getAttribute(IssueService.FILTER_ASSIGNEE); if (assignee != null) assigneeText.setText(assignee); String mentioning = query.getAttribute(IssueService.FILTER_MENTIONED); if (mentioning != null) mentionText.setText(mentioning); } private boolean updateLabels() { if (labelsViewer.getControl().isDisposed()) return false; IssueConnector connector = IssueConnectorUi.getCoreConnector(); TaskRepository repository = getTaskRepository(); boolean hasLabels = connector.hasCachedLabels(repository); if (hasLabels) { List<org.eclipse.egit.github.core.Label> labels = connector .getLabels(repository); Collections.sort(labels, new LabelComparator()); List<String> labelNames = new ArrayList<String>(labels.size()); for (org.eclipse.egit.github.core.Label label : labels) labelNames.add(label.getName()); labelsViewer.setInput(labelNames); } return hasLabels; } private boolean updateMilestones() { if (milestoneCombo.isDisposed()) return false; IssueConnector connector = IssueConnectorUi.getCoreConnector(); TaskRepository repository = getTaskRepository(); boolean hasMilestones = connector.hasCachedMilestones(repository); if (hasMilestones) { milestones = connector.getMilestones(repository); milestoneCombo.removeAll(); milestoneCombo.add(Messages.IssueRepositoryQueryPage_MilestoneNone); Collections.sort(milestones, new Comparator<Milestone>() { public int compare(Milestone m1, Milestone m2) { return m1.getTitle().compareToIgnoreCase(m2.getTitle()); } }); for (Milestone milestone : milestones) milestoneCombo.add(milestone.getTitle()); milestoneCombo.select(0); } return hasMilestones; } private void refreshRepository() { try { ICoreRunnable runnable = new ICoreRunnable() { public void run(IProgressMonitor monitor) throws CoreException { Policy.monitorFor(monitor); monitor.beginTask("", 2); //$NON-NLS-1$ IssueConnector connector = IssueConnectorUi .getCoreConnector(); TaskRepository repository = getTaskRepository(); monitor.setTaskName(Messages.IssueRepositoryQueryPage_TaskLoadingLabels); connector.refreshLabels(repository); monitor.worked(1); monitor.setTaskName(Messages.IssueRepositoryQueryPage_TaskLoadingMilestones); connector.refreshMilestones(repository); monitor.done(); PlatformUI.getWorkbench().getDisplay() .asyncExec(new Runnable() { public void run() { updateLabels(); updateMilestones(); initialize(); } }); } }; IRunnableContext context = getContainer(); if (context == null) if (inSearchContainer()) context = getSearchContainer().getRunnableContext(); else context = PlatformUI.getWorkbench().getProgressService(); CommonUiUtil.run(context, runnable); } catch (CoreException e) { IStatus status = e.getStatus(); ErrorDialog.openError(getShell(), Messages.IssueRepositoryQueryPage_ErrorLoading, e.getLocalizedMessage(), status); } } private void loadRepository() { boolean labelsLoaded = updateLabels(); boolean milestonesLoaded = updateMilestones(); if (!labelsLoaded || !milestonesLoaded) refreshRepository(); } /** * @see org.eclipse.mylyn.tasks.ui.wizards.AbstractRepositoryQueryPage#isPageComplete() */ public boolean isPageComplete() { boolean complete = inSearchContainer() ? true : super.isPageComplete(); if (complete) { String message = null; if (!openButton.getSelection() && !closedButton.getSelection()) message = Messages.IssueRepositoryQueryPage_ErrorStatus; setErrorMessage(message); complete = message == null; } return complete; } /** * @see org.eclipse.mylyn.tasks.ui.wizards.AbstractRepositoryQueryPage#getQueryTitle() */ public String getQueryTitle() { return titleText != null ? titleText.getText() : null; } /** * @see org.eclipse.mylyn.tasks.ui.wizards.AbstractRepositoryQueryPage#applyTo(org.eclipse.mylyn.tasks.core.IRepositoryQuery) */ public void applyTo(IRepositoryQuery query) { query.setSummary(getQueryTitle()); List<String> statuses = new LinkedList<String>(); if (openButton.getSelection()) statuses.add(IssueService.STATE_OPEN); if (closedButton.getSelection()) statuses.add(IssueService.STATE_CLOSED); QueryUtils.setAttribute(IssueService.FILTER_STATE, statuses, query); String assignee = assigneeText.getText().trim(); if (assignee.length() > 0) query.setAttribute(IssueService.FILTER_ASSIGNEE, assignee); else query.setAttribute(IssueService.FILTER_ASSIGNEE, null); String mentions = mentionText.getText().trim(); if (mentions.length() > 0) query.setAttribute(IssueService.FILTER_MENTIONED, mentions); else query.setAttribute(IssueService.FILTER_MENTIONED, null); int milestoneSelected = milestoneCombo.getSelectionIndex() - 1; if (milestoneSelected >= 0) query.setAttribute(IssueService.FILTER_MILESTONE, Integer .toString(milestones.get(milestoneSelected).getNumber())); else query.setAttribute(IssueService.FILTER_MILESTONE, null); List<String> labels = new LinkedList<String>(); for (Object label : labelsViewer.getCheckedElements()) labels.add(label.toString()); QueryUtils.setAttribute(IssueService.FILTER_LABELS, labels, query); } }