| /*=============================================================================# |
| # Copyright (c) 2005, 2020 Stephan Wahlbrink and others. |
| # |
| # This program and the accompanying materials are made available under the |
| # terms of the Eclipse Public License 2.0 which is available at |
| # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 |
| # which is available at https://www.apache.org/licenses/LICENSE-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| # |
| # Contributors: |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.internal.nico.ui; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.concurrent.atomic.AtomicInteger; |
| |
| import org.eclipse.core.runtime.jobs.IJobChangeEvent; |
| import org.eclipse.core.runtime.jobs.IJobChangeListener; |
| import org.eclipse.core.runtime.jobs.Job; |
| import org.eclipse.debug.core.DebugPlugin; |
| import org.eclipse.debug.core.ILaunch; |
| import org.eclipse.debug.core.ILaunchesListener; |
| import org.eclipse.debug.core.model.IProcess; |
| import org.eclipse.ui.IPageListener; |
| import org.eclipse.ui.IWorkbenchPage; |
| import org.eclipse.ui.IWorkbenchWindow; |
| import org.eclipse.ui.console.ConsolePlugin; |
| import org.eclipse.ui.console.IConsole; |
| import org.eclipse.ui.console.IConsoleManager; |
| import org.eclipse.ui.console.IConsoleView; |
| |
| import org.eclipse.statet.jcommons.ts.core.Tool; |
| |
| import org.eclipse.statet.ecommons.collections.FastList; |
| import org.eclipse.statet.ecommons.ts.ui.workbench.WorkbenchToolRegistry; |
| import org.eclipse.statet.ecommons.ts.ui.workbench.WorkbenchToolRegistryListener; |
| import org.eclipse.statet.ecommons.ts.ui.workbench.WorkbenchToolSessionData; |
| import org.eclipse.statet.ecommons.ui.util.UIAccess; |
| |
| import org.eclipse.statet.nico.core.runtime.ToolProcess; |
| import org.eclipse.statet.nico.ui.console.NIConsole; |
| |
| |
| public class ToolRegistry implements WorkbenchToolRegistry, IPageListener { |
| |
| |
| static boolean DEBUG = false; |
| |
| |
| /** |
| * Prevents to run system "Show Console View" jobs when own jobs are scheduled |
| */ |
| private static class JobListener implements IJobChangeListener { |
| |
| private static final String OWN_SHOWCONSOLE_NAME = PageRegistry.SHOW_CONSOLE_JOB_NAME; |
| private static final String OTHER_SHOWCONSOLE_NAME = "Show Console View"; //$NON-NLS-1$ |
| |
| private final AtomicInteger fOwnJobs = new AtomicInteger(0); |
| |
| @Override |
| public void scheduled(final IJobChangeEvent event) { |
| if (event.getJob().getName() == OWN_SHOWCONSOLE_NAME) { |
| fOwnJobs.incrementAndGet(); |
| } |
| else { |
| checkJob(event.getJob()); |
| } |
| } |
| @Override |
| public void aboutToRun(final IJobChangeEvent event) { |
| checkJob(event.getJob()); |
| } |
| @Override |
| public void done(final IJobChangeEvent event) { |
| if (event.getJob().getName() == OWN_SHOWCONSOLE_NAME) { |
| fOwnJobs.decrementAndGet(); |
| } |
| } |
| private void checkJob(final Job eventJob) { |
| if (fOwnJobs.get() > 0 |
| && eventJob.getName() == OTHER_SHOWCONSOLE_NAME) { |
| eventJob.cancel(); |
| if (DEBUG) { |
| System.out.println("[tool registry] show job canceled"); //$NON-NLS-1$ |
| } |
| } |
| } |
| |
| @Override |
| public void sleeping(final IJobChangeEvent event) { |
| } |
| @Override |
| public void awake(final IJobChangeEvent event) { |
| } |
| @Override |
| public void running(final IJobChangeEvent event) { |
| } |
| |
| } |
| |
| |
| private class LaunchesListener implements ILaunchesListener { |
| |
| @Override |
| public void launchesAdded(final ILaunch[] launches) { |
| } |
| @Override |
| public void launchesChanged(final ILaunch[] launches) { |
| } |
| |
| @Override |
| public void launchesRemoved(final ILaunch[] launches) { |
| final List<ToolProcess> list= new ArrayList<>(); |
| for (final ILaunch launch : launches) { |
| final IProcess[] processes = launch.getProcesses(); |
| for (final IProcess process : processes) { |
| if (process instanceof ToolProcess) { |
| list.add((ToolProcess) process); |
| } |
| } |
| } |
| |
| if (list.isEmpty()) { |
| return; |
| } |
| |
| final PageRegistry[] registries = getPageRegistries(); |
| for (final PageRegistry reg : registries) { |
| reg.handleConsolesRemoved(list); |
| } |
| |
| // Because debug plugin removes only ProcessConsoles, we have to do... |
| removeConsoles(list); |
| } |
| |
| private void removeConsoles(final List<ToolProcess> processes) { |
| final List<IConsole> toRemove= new ArrayList<>(); |
| final IConsoleManager manager = ConsolePlugin.getDefault().getConsoleManager(); |
| final IConsole[] consoles = manager.getConsoles(); |
| for (final IConsole console : consoles) { |
| if ((console instanceof NIConsole) && |
| processes.contains(((NIConsole) console).getProcess()) ) { |
| toRemove.add(console); |
| } |
| } |
| manager.removeConsoles(toRemove.toArray(new IConsole[toRemove.size()])); |
| } |
| |
| } |
| |
| |
| private final Map<IWorkbenchPage, PageRegistry> fPageRegistries= new HashMap<>(); |
| private boolean isDisposed = false; |
| |
| private LaunchesListener fLaunchesListener; |
| private JobListener fJobListener; |
| |
| private final FastList<WorkbenchToolRegistryListener> fListenersWorkbench= new FastList<>(WorkbenchToolRegistryListener.class, FastList.IDENTITY); |
| |
| |
| public ToolRegistry() { |
| fLaunchesListener = new LaunchesListener(); |
| fJobListener = new JobListener(); |
| DebugPlugin.getDefault().getLaunchManager().addLaunchListener(fLaunchesListener); |
| |
| Job.getJobManager().addJobChangeListener(fJobListener); |
| } |
| |
| public void dispose() { |
| DebugPlugin.getDefault().getLaunchManager().removeLaunchListener(fLaunchesListener); |
| synchronized (fPageRegistries) { |
| fLaunchesListener = null; |
| |
| for (final IWorkbenchPage page : fPageRegistries.keySet()) { |
| page.getWorkbenchWindow().removePageListener(this); |
| final PageRegistry reg = fPageRegistries.get(page); |
| reg.dispose(); |
| } |
| fPageRegistries.clear(); |
| isDisposed = true; |
| } |
| |
| Job.getJobManager().addJobChangeListener(fJobListener); |
| fJobListener = null; |
| if (DEBUG) { |
| System.out.println("[tool registry] registry closed."); //$NON-NLS-1$ |
| } |
| } |
| |
| |
| @Override |
| public void pageOpened(final IWorkbenchPage page) { |
| } |
| @Override |
| public void pageActivated(final IWorkbenchPage page) { |
| } |
| |
| @Override |
| public void pageClosed(final IWorkbenchPage page) { |
| PageRegistry reg; |
| synchronized (fPageRegistries) { |
| page.getWorkbenchWindow().removePageListener(this); |
| reg = fPageRegistries.remove(page); |
| } |
| reg.dispose(); |
| } |
| |
| |
| private PageRegistry getPageRegistry(final IWorkbenchPage page) { |
| if (page == null) { |
| return null; |
| } |
| synchronized (fPageRegistries) { |
| PageRegistry reg = fPageRegistries.get(page); |
| if (reg == null) { |
| if (this.isDisposed) { |
| return null; |
| } |
| final IWorkbenchWindow window= page.getWorkbenchWindow(); |
| if (window == null) { |
| return null; |
| } |
| window.addPageListener(this); |
| final WorkbenchToolRegistryListener[] listeners = fListenersWorkbench.toArray(); |
| reg = new PageRegistry(page, listeners); |
| fPageRegistries.put(page, reg); |
| } |
| return reg; |
| } |
| } |
| |
| private PageRegistry[] getPageRegistries() { |
| synchronized (fPageRegistries) { |
| final Collection<PageRegistry> collection = fPageRegistries.values(); |
| return collection.toArray(new PageRegistry[collection.size()]); |
| } |
| } |
| |
| |
| @Override |
| public void addListener(final WorkbenchToolRegistryListener listener, final IWorkbenchPage page) { |
| if (page == null) { |
| fListenersWorkbench.add(listener); |
| } |
| final PageRegistry reg = getPageRegistry(page); |
| if (reg != null) { |
| reg.fListeners.add(listener); |
| } |
| } |
| |
| @Override |
| public void removeListener(final WorkbenchToolRegistryListener listener) { |
| fListenersWorkbench.remove(listener); |
| synchronized (fPageRegistries) { |
| for (final PageRegistry reg : fPageRegistries.values()) { |
| reg.fListeners.remove(listener); |
| } |
| } |
| } |
| |
| |
| public void consoleActivated(final IConsoleView consoleView, final NIConsole console) { |
| final IWorkbenchPage page = consoleView.getViewSite().getPage(); |
| final PageRegistry reg = getPageRegistry(page); |
| if (reg != null) { |
| reg.handleActiveConsoleChanged(console, consoleView); |
| } |
| } |
| |
| @Override |
| public WorkbenchToolSessionData getActiveToolSession(final IWorkbenchPage page) { |
| if (page == null) { |
| return null; |
| } |
| |
| final PageRegistry reg = getPageRegistry(page); |
| if (reg != null) { |
| return reg.createSessionInfo(null); |
| } |
| return null; |
| } |
| |
| @Override |
| public IWorkbenchPage findWorkbenchPage(final Tool process) { |
| final IWorkbenchPage activePage = UIAccess.getActiveWorkbenchPage(false); |
| IWorkbenchPage page = null; |
| synchronized (fPageRegistries) { |
| for (final PageRegistry reg : fPageRegistries.values()) { |
| if (reg.getActiveProcess() == process) { |
| page = reg.getPage(); |
| if (page == activePage) { |
| return page; |
| } |
| } |
| } |
| } |
| if (page != null) { |
| return page; |
| } |
| return activePage; |
| } |
| |
| public IConsoleView getConsoleView(final NIConsole console, final IWorkbenchPage page) { |
| final PageRegistry reg = getPageRegistry(page); |
| if (reg != null) { |
| return reg.getConsoleView(console); |
| } |
| return null; |
| } |
| |
| public void showConsole(final NIConsole console, final IWorkbenchPage page, |
| final boolean activate) { |
| final PageRegistry reg = getPageRegistry(page); |
| if (reg != null) { |
| reg.showConsole(console, activate); |
| } |
| } |
| |
| public void showConsoleExplicitly(final NIConsole console, final IWorkbenchPage page, |
| final boolean pin) { |
| final PageRegistry reg = getPageRegistry(page); |
| if (reg != null) { |
| reg.showConsoleExplicitly(console, pin); |
| } |
| } |
| |
| } |