Java tutorial
/******************************************************************************* * Copyright (c) 2004 - 2009 Mylyn project committers 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: * Mylyn project committers, Atlassian, Sven Krzyzak *******************************************************************************/ /******************************************************************************* * Copyright (c) 2009 Markus Knittig * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Contributors: * Markus Knittig - adapted Trac, Redmine & Atlassian implementations for * Review Board *******************************************************************************/ package org.review_board.ereviewboard.ui.wizard; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.eclipse.jface.dialogs.Dialog; 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.ComboViewer; import org.eclipse.mylyn.tasks.core.IRepositoryQuery; import org.eclipse.mylyn.tasks.core.TaskRepository; import org.eclipse.mylyn.tasks.ui.TasksUi; import org.eclipse.mylyn.tasks.ui.wizards.AbstractRepositoryQueryPage; import org.eclipse.mylyn.tasks.ui.wizards.ITaskSearchPageContainer; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Text; import org.review_board.ereviewboard.core.ReviewboardCorePlugin; import org.review_board.ereviewboard.core.ReviewboardRepositoryConnector; import org.review_board.ereviewboard.core.client.ReviewboardClient; import org.review_board.ereviewboard.core.client.ReviewboardClientData; import org.review_board.ereviewboard.core.model.AllReviewRequestQuery; import org.review_board.ereviewboard.core.model.FromUserReviewRequestQuery; import org.review_board.ereviewboard.core.model.GroupReviewRequestQuery; import org.review_board.ereviewboard.core.model.Repository; import org.review_board.ereviewboard.core.model.RepositoryReviewRequestQuery; import org.review_board.ereviewboard.core.model.ReviewRequestQuery; import org.review_board.ereviewboard.core.model.ReviewRequestStatus; import org.review_board.ereviewboard.core.model.StatusReviewRequestQuery; import org.review_board.ereviewboard.core.model.ToUserReviewRequestQuery; import org.review_board.ereviewboard.core.util.ReviewboardUtil; import org.review_board.ereviewboard.ui.ReviewboardUiUtil; import org.review_board.ereviewboard.ui.internal.control.EnhancedAutoCompleteField; import org.review_board.ereviewboard.ui.internal.control.Proposal; import org.review_board.ereviewboard.ui.util.UiUtils; /** * @author Markus Knittig * */ public class ReviewboardQueryPage extends AbstractRepositoryQueryPage { private enum Selection { ALL, GROUP, FROM_USER, TO_USER, REPOSITORY; } private static final String TITLE = "Enter query parameters"; private static final String DESCRIPTION = "Select options to create a query"; private static final String TITLE_QUERY_TITLE = "Query title"; private final UpdateButtonsListener updateButtonsListener = new UpdateButtonsListener(); private ReviewboardClient client; private IRepositoryQuery query; private Text titleText; private String changeNum = ""; private Text groupText; private Text fromUserText; private Text toUserText; private ComboViewer repositoryCombo; private EnhancedAutoCompleteField groupAutoCompleteField; private EnhancedAutoCompleteField fromUserAutoCompleteField; private EnhancedAutoCompleteField toUserComboAutoCompleteField; private List<String> users; private List<String> groups; private ComboViewer statusCombo; private Text changeNumText; private Map<Integer, String> repositories; private List<Repository> repositoryList; private Text maxResultsText; private Map<Button, SelectionRunnable> radioButtons = new HashMap<Button, SelectionRunnable>(); private Selection selection = Selection.ALL; private ReviewRequestQuery reviewRequestQuery; public ReviewboardQueryPage(TaskRepository taskRepository, IRepositoryQuery query) { super(TITLE, taskRepository, query); this.query = query; ReviewboardRepositoryConnector connector = (ReviewboardRepositoryConnector) TasksUi.getRepositoryManager() .getRepositoryConnector(ReviewboardCorePlugin.REPOSITORY_KIND); client = connector.getClientManager().getClient(getTaskRepository()); setTitle(TITLE); setDescription(DESCRIPTION); } public ReviewboardQueryPage(TaskRepository repository) { this(repository, null); } private void updateRepositoryData(final boolean force) { if (force || !client.hasRepositoryData()) ReviewboardUiUtil.refreshRepositoryData(client, force, getRunnableContext()); ReviewboardClientData clientData = client.getClientData(); repositoryCombo.setInput(ReviewboardUtil.toStringList(clientData.getRepositories())); users = ReviewboardUtil.toStringList(clientData.getUsers()); groups = ReviewboardUtil.toStringList(clientData.getGroups()); groupAutoCompleteField.setProposals(UiUtils.adaptGroups(clientData.getGroups())); fromUserAutoCompleteField.setProposals(UiUtils.adaptUsers(clientData.getUsers())); toUserComboAutoCompleteField.setProposals(UiUtils.adaptUsers(clientData.getUsers())); repositories = new HashMap<Integer, String>(); repositoryList = clientData.getRepositories(); for (Repository repository : clientData.getRepositories()) repositories.put(repository.getId(), repository.getName()); } private IRunnableContext getRunnableContext() { if (getContainer() != null) return getContainer(); ITaskSearchPageContainer container = getSearchContainer(); if (container != null) return container.getRunnableContext(); return null; } private void restoreQuery(IRepositoryQuery query) { titleText.setText(query.getSummary()); changeNum = query.getAttribute("changeNum"); ReviewRequestQuery reviewRequestQuery = StatusReviewRequestQuery.fromQueryString(query.getUrl()); selection = Selection.ALL; if (reviewRequestQuery instanceof StatusReviewRequestQuery) { ReviewRequestStatus status = ((StatusReviewRequestQuery) reviewRequestQuery).getStatus(); ReviewboardUiUtil.selectComboItemByValue(statusCombo, status.getDisplayname()); maxResultsText.setText(String.valueOf(((StatusReviewRequestQuery) reviewRequestQuery).getMaxResults())); if (reviewRequestQuery instanceof GroupReviewRequestQuery) { GroupReviewRequestQuery specificQuery = (GroupReviewRequestQuery) reviewRequestQuery; groupText.setText(specificQuery.getGroupname()); selection = Selection.GROUP; } else if (reviewRequestQuery instanceof FromUserReviewRequestQuery) { FromUserReviewRequestQuery specificQuery = (FromUserReviewRequestQuery) reviewRequestQuery; fromUserText.setText(specificQuery.getUsername()); selection = Selection.FROM_USER; } else if (reviewRequestQuery instanceof ToUserReviewRequestQuery) { ToUserReviewRequestQuery specificQuery = (ToUserReviewRequestQuery) reviewRequestQuery; toUserText.setText(specificQuery.getUsername()); selection = Selection.TO_USER; } else if (reviewRequestQuery instanceof RepositoryReviewRequestQuery) { RepositoryReviewRequestQuery specificQuery = (RepositoryReviewRequestQuery) reviewRequestQuery; changeNumText.setText(String.valueOf(specificQuery.getChangeNum())); ReviewboardUiUtil.selectComboItemByValue(repositoryCombo, repositories.get(specificQuery.getRepositoryId())); selection = Selection.REPOSITORY; } } // toggle buttons for (Iterator<Map.Entry<Button, SelectionRunnable>> iterator = radioButtons.entrySet().iterator(); iterator .hasNext();) { Entry<Button, SelectionRunnable> entry = iterator.next(); boolean needsSelection = (entry.getValue().getSelection() == selection); entry.getKey().setSelection(needsSelection); if (needsSelection) entry.getValue().run(); } } @Override public void applyTo(IRepositoryQuery query) { query.setSummary(getQueryTitle()); query.setUrl(reviewRequestQuery.getQuery()); query.setAttribute("maxResults", String.valueOf(((StatusReviewRequestQuery) reviewRequestQuery).getMaxResults())); query.setAttribute("changeNum", changeNum); } @Override public String getQueryTitle() { if (titleText == null) { return "<search>"; } else { return titleText.getText(); } } @Override public boolean canFlipToNextPage() { return false; } @Override public boolean isPageComplete() { return validate(); } private boolean validate() { boolean valid = true; ReviewRequestQuery query; ReviewRequestStatus status = getSelectedStatus(); int maxResults; try { maxResults = Integer.parseInt(maxResultsText.getText()); if (maxResults <= 0) return false; } catch (NumberFormatException e) { return false; } switch (selection) { case ALL: query = new AllReviewRequestQuery(status, maxResults); break; case GROUP: if (!groups.contains(groupText.getText())) return false; query = new GroupReviewRequestQuery(status, maxResults, groupText.getText()); break; case REPOSITORY: String text = changeNumText.getText(); try { int changeNumInt = Integer.parseInt(text); if (changeNumInt <= 0) return false; int repositoryIndex = repositoryCombo.getCombo().getSelectionIndex(); int repositoryId = repositoryList.get(repositoryIndex).getId(); query = new RepositoryReviewRequestQuery(status, maxResults, repositoryId, changeNumInt); } catch (NumberFormatException e) { return false; } break; case TO_USER: if (!users.contains(toUserText.getText())) return false; query = new ToUserReviewRequestQuery(status, maxResults, toUserText.getText()); break; case FROM_USER: if (!users.contains(fromUserText.getText())) return false; query = new FromUserReviewRequestQuery(status, maxResults, fromUserText.getText()); break; default: return false; } // assign at the end to benefit from 'definite assignment' compiler analysis reviewRequestQuery = query; return (titleText != null && titleText.getText().length() > 0) && valid; } public void createControl(Composite parent) { Composite control = new Composite(parent, SWT.NONE); GridLayoutFactory.fillDefaults().numColumns(4).applyTo(control); createTitleGroup(control); Composite parentRadioComposite = new Composite(control, SWT.NONE); GridLayoutFactory.fillDefaults().numColumns(2).applyTo(parentRadioComposite); GridDataFactory.fillDefaults().span(4, 1).applyTo(parentRadioComposite); Composite radioComposite = new Composite(parentRadioComposite, SWT.NONE); GridDataFactory.fillDefaults().span(2, 1).applyTo(radioComposite); GridLayoutFactory.fillDefaults().numColumns(2).applyTo(radioComposite); createAllButton(radioComposite); Composite groupComposite = createRadioCompositeWithCombo(radioComposite, "With group", Selection.GROUP); createGroupText(groupComposite); recursiveEnable(groupComposite, false); Composite fromUserComposite = createRadioCompositeWithCombo(radioComposite, "From the user", Selection.FROM_USER); createFromUserText(fromUserComposite); recursiveEnable(fromUserComposite, false); Composite toUserComposite = createRadioCompositeWithCombo(radioComposite, "To the user", Selection.TO_USER); createToUserText(toUserComposite); recursiveEnable(toUserComposite, false); Composite repositoryComposite = createRadioCompositeWithCombo(radioComposite, "From repository", Selection.REPOSITORY); repositoryCombo = createRepositoryCombo(repositoryComposite); Label changeNumLabel = new Label(repositoryComposite, SWT.FILL); changeNumLabel.setText("with change number:"); changeNumText = new Text(repositoryComposite, SWT.BORDER); changeNumText.addListener(SWT.Modify, new Listener() { public void handleEvent(Event event) { changeNum = ((Text) event.widget).getText(); event.widget = repositoryCombo.getCombo(); repositoryCombo.getCombo().notifyListeners(SWT.Modify, event); getContainer().updateButtons(); } }); recursiveEnable(repositoryComposite, false); Composite statusComposite = new Composite(parentRadioComposite, SWT.NONE); GridLayoutFactory.fillDefaults().numColumns(2).applyTo(statusComposite); Label statusLabel = new Label(statusComposite, SWT.NONE); statusLabel.setText("With Status"); statusCombo = createCombo(statusComposite); for (ReviewRequestStatus status : ReviewRequestStatus.values()) if (status != ReviewRequestStatus.NONE) statusCombo.add(status.getDisplayname()); statusCombo.getCombo().select(0); statusCombo.getCombo().addListener(SWT.Modify, updateButtonsListener); Composite maxResultComposite = new Composite(parentRadioComposite, SWT.NONE); GridLayoutFactory.fillDefaults().numColumns(2).applyTo(maxResultComposite); Label maxResultsLabel = new Label(maxResultComposite, SWT.FILL); maxResultsLabel.setText("Maximum results"); maxResultsText = new Text(maxResultComposite, SWT.BORDER); GridDataFactory.swtDefaults().hint(50, SWT.DEFAULT).applyTo(maxResultsText); maxResultsText.addListener(SWT.Modify, updateButtonsListener); Button button = new Button(control, SWT.NONE); GridDataFactory.swtDefaults().span(4, 1).applyTo(button); button.setText("Refresh repository configuration"); button.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { updateRepositoryData(true); } }); setControl(control); Dialog.applyDialogFont(control); updateRepositoryData(false); ReviewboardUiUtil.selectDefaultComboItem(repositoryCombo); maxResultsText.setText(String.valueOf(ReviewRequestQuery.DEFAULT_MAX_RESULTS)); if (query != null) restoreQuery(query); } private ReviewRequestStatus getSelectedStatus() { return ReviewRequestStatus.valueOf(statusCombo.getCombo().getText().toUpperCase()); } private void createAllButton(Composite radioComposite) { Button button = UiUtils.createRadioButton(radioComposite, "All"); final SelectionRunnable toggleRunnable = new SelectionRunnable(Selection.ALL) { public void run0() { getContainer().updateButtons(); } }; radioButtons.put(button, toggleRunnable); button.setSelection(true); final Composite allComposite = createRadioComposite(radioComposite); new Label(allComposite, SWT.NONE); button.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { toggleRunnable.run(); } }); recursiveEnable(allComposite, false); } private Composite createRadioComposite(Composite parent) { final Composite composite = new Composite(parent, SWT.NONE); GridLayoutFactory.fillDefaults().numColumns(3).applyTo(composite); return composite; } private static void recursiveEnable(Composite composite, boolean enabled) { composite.setEnabled(enabled); for (Control childControl : composite.getChildren()) childControl.setEnabled(enabled); } private Composite createRadioCompositeWithCombo(final Composite parent, String text, final Selection selection) { final Button button = UiUtils.createRadioButton(parent, text); final Composite composite = createRadioComposite(parent); final SelectionRunnable toggleRunnable = new SelectionRunnable(selection) { protected void run0() { recursiveEnable(composite, button.getSelection()); getContainer().updateButtons(); } }; radioButtons.put(button, toggleRunnable); button.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { toggleRunnable.run(); } }); return composite; } private ComboViewer createCombo(Composite parent) { final ComboViewer combo = new ComboViewer(parent, SWT.DROP_DOWN | SWT.BORDER | SWT.READ_ONLY); combo.setContentProvider(new ArrayContentProvider()); parent.addListener(SWT.Modify, new Listener() { public void handleEvent(Event event) { event.widget = combo.getCombo(); combo.getCombo().notifyListeners(SWT.Modify, event); } }); return combo; } private void createGroupText(Composite parent) { groupText = newWideTextField(parent); groupAutoCompleteField = new EnhancedAutoCompleteField(groupText, new Proposal[0]); parent.addListener(SWT.Modify, new Listener() { public void handleEvent(Event event) { groupText.notifyListeners(SWT.Modify, event); } }); groupText.addListener(SWT.Modify, updateButtonsListener); } private Text newWideTextField(Composite parent) { Text text = new Text(parent, SWT.BORDER); GridDataFactory.swtDefaults().hint(175, SWT.DEFAULT).applyTo(text); return text; } private void createFromUserText(Composite fromUserComposite) { fromUserText = newWideTextField(fromUserComposite); fromUserAutoCompleteField = new EnhancedAutoCompleteField(fromUserText, new Proposal[0]); fromUserComposite.addListener(SWT.Modify, new Listener() { public void handleEvent(Event event) { fromUserText.notifyListeners(SWT.Modify, event); } }); fromUserText.addListener(SWT.Modify, updateButtonsListener); } private void createToUserText(Composite toUserComposite) { toUserText = newWideTextField(toUserComposite); toUserComboAutoCompleteField = new EnhancedAutoCompleteField(toUserText, new Proposal[0]); toUserComposite.addListener(SWT.Modify, new Listener() { public void handleEvent(Event event) { toUserText.notifyListeners(SWT.Modify, event); } }); toUserText.addListener(SWT.Modify, updateButtonsListener); } private ComboViewer createRepositoryCombo(Composite parent) { ComboViewer combo = createCombo(parent); combo.getCombo().addListener(SWT.Modify, updateButtonsListener); return combo; } private void createTitleGroup(Composite control) { if (inSearchContainer()) return; Label titleLabel = new Label(control, SWT.NONE); titleLabel.setText(TITLE_QUERY_TITLE); titleText = new Text(control, SWT.BORDER); GridDataFactory.fillDefaults().grab(true, false).span(3, 1).applyTo(titleText); titleText.addListener(SWT.Modify, updateButtonsListener); } private abstract class SelectionRunnable implements Runnable { private final Selection selection; public SelectionRunnable(Selection selection) { this.selection = selection; } public Selection getSelection() { return selection; } public void run() { ReviewboardQueryPage.this.selection = selection; run0(); } protected abstract void run0(); } private final class UpdateButtonsListener implements Listener { public void handleEvent(Event event) { // event might be triggered before the wizard is shown // see task #42 if (getContainer().getCurrentPage() != null) getContainer().updateButtons(); } } }