package bndtools.editor.project; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import org.eclipse.jface.util.LocalSelectionTransfer; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.DND; import org.eclipse.swt.dnd.DragSourceEvent; import org.eclipse.swt.dnd.Transfer; 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.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.Text; import org.eclipse.swt.widgets.Tree; import org.eclipse.ui.forms.IManagedForm; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.forms.widgets.Section; import aQute.bnd.build.Workspace; import aQute.bnd.build.WorkspaceRepository; import aQute.bnd.build.model.BndEditModel; import aQute.bnd.service.RepositoryPlugin; import aQute.bnd.service.ResolutionPhase; import bndtools.BndConstants; import bndtools.Plugin; import bndtools.central.Central; import bndtools.central.RepositoriesViewRefresher; import bndtools.central.RepositoryUtils; import bndtools.editor.common.BndEditorPart; import bndtools.model.repo.RepositoryBundle; import bndtools.model.repo.RepositoryTreeContentProvider; import bndtools.model.repo.RepositoryTreeLabelProvider; import bndtools.utils.SelectionDragAdapter; public class AvailableBundlesPart extends BndEditorPart implements RepositoriesViewRefresher.RefreshModel { // Number of millis to wait for the user to stop typing in the filter box private static final long SEARCH_DELAY = 1000; private String searchStr = ""; private ScheduledFuture< ? > scheduledFilterUpdate = null; private final RepositoryTreeContentProvider contentProvider = new RepositoryTreeContentProvider(ResolutionPhase.runtime); private Text txtSearch; private TreeViewer viewer; private Set<String> includedRepos; private final ViewerFilter includedRepoFilter = new ViewerFilter() { @Override public boolean select(Viewer viewer, Object parentElement, Object element) { boolean select = false; if (element instanceof RepositoryBundle) { RepositoryBundle repoBundle = (RepositoryBundle) element; RepositoryPlugin repo = repoBundle.getRepo(); if (includedRepos == null) { select = true; } else if (repo instanceof WorkspaceRepository) { select = includedRepos.contains("Workspace"); } else { select = includedRepos.contains(repoBundle.getRepo().getName()); } } else { select = true; } return select; } }; private final Runnable updateFilterTask = new Runnable() { @Override public void run() { Display display = viewer.getControl().getDisplay(); Runnable update = new Runnable() { @Override public void run() { updatedFilter(searchStr); } }; if (display.getThread() == Thread.currentThread()) update.run(); else display.asyncExec(update); } }; public AvailableBundlesPart(Composite parent, FormToolkit toolkit, int style) { super(parent, toolkit, style); Section section = getSection(); createClient(section, toolkit); } @Override public void initialize(IManagedForm form) { super.initialize(form); Central.addRepositoriesViewer(viewer, this); } private void createClient(Section section, FormToolkit toolkit) { section.setText("Browse Repos"); // Create contents Composite container = toolkit.createComposite(section); section.setClient(container); GridLayout layout = new GridLayout(1, false); layout.marginWidth = 0; layout.marginHeight = 0; container.setLayout(layout); txtSearch = toolkit.createText(container, "", SWT.SEARCH | SWT.ICON_SEARCH | SWT.ICON_CANCEL | SWT.BORDER); txtSearch.setMessage("Enter search string"); txtSearch.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); Tree tree = toolkit.createTree(container, SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI | SWT.V_SCROLL); tree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1)); viewer = new TreeViewer(tree); contentProvider.setShowRepos(false); viewer.setContentProvider(contentProvider); viewer.setLabelProvider(new RepositoryTreeLabelProvider(true)); viewer.setFilters(new ViewerFilter[] { includedRepoFilter }); txtSearch.addModifyListener(new ModifyListener() { @Override public void modifyText(ModifyEvent e) { if (scheduledFilterUpdate != null) scheduledFilterUpdate.cancel(true); searchStr = txtSearch.getText(); scheduledFilterUpdate = Plugin.getDefault().getScheduler().schedule(updateFilterTask, SEARCH_DELAY, TimeUnit.MILLISECONDS); } }); txtSearch.addSelectionListener(new SelectionAdapter() { @Override public void widgetDefaultSelected(SelectionEvent e) { if (scheduledFilterUpdate != null) scheduledFilterUpdate.cancel(true); scheduledFilterUpdate = null; searchStr = txtSearch.getText(); updateFilterTask.run(); } }); viewer.addDragSupport(DND.DROP_COPY | DND.DROP_MOVE, new Transfer[] { LocalSelectionTransfer.getTransfer() }, new SelectionDragAdapter(viewer) { @Override public void dragStart(DragSourceEvent event) { IStructuredSelection selection = (IStructuredSelection) viewer.getSelection(); if (!selection.isEmpty()) { LocalSelectionTransfer.getTransfer().setSelection(selection); LocalSelectionTransfer.getTransfer().setSelectionSetTime(event.time & 0xFFFFFFFFL); } else { event.doit = false; } } }); } private void updatedFilter(String filterString) { contentProvider.setFilter(filterString); viewer.refresh(true); } @Override protected String[] getProperties() { return new String[] { BndConstants.RUNREPOS, BndEditModel.PROP_WORKSPACE }; } @Override protected void refreshFromModel() { viewer.setInput(getRepositories()); } @Override public List<RepositoryPlugin> getRepositories() { List<String> tmp = model.getRunRepos(); includedRepos = (tmp == null) ? null : new HashSet<String>(tmp); Workspace workspace = model.getWorkspace(); List<RepositoryPlugin> repos; try { repos = RepositoryUtils.listRepositories(workspace, true); } catch (Exception e) { repos = Collections.emptyList(); } return repos; } @Override protected void commitToModel(boolean onSave) { // Nothing to do } @Override public void dispose() { Central.removeRepositoriesViewer(viewer); super.dispose(); } }