| /******************************************************************************* |
| * Copyright (c) 2012, 2013 Oracle. All rights reserved. |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License 2.0, which accompanies this distribution |
| * and is available at https://www.eclipse.org/legal/epl-2.0/. |
| * |
| * Contributors: |
| * Oracle - initial API and implementation |
| ******************************************************************************/ |
| package org.eclipse.jpt.jpa.ui.internal.selection; |
| |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.core.runtime.jobs.Job; |
| import org.eclipse.jpt.common.ui.internal.swt.widgets.DisplayTools; |
| import org.eclipse.jpt.common.utility.internal.ObjectTools; |
| import org.eclipse.jpt.jpa.core.JpaStructureNode; |
| import org.eclipse.jpt.jpa.ui.JptJpaUiMessages; |
| |
| /** |
| * This job will not run until any currently outstanding Dali <em>updates</em> etc. |
| * are complete. As a result, the runnable dispatched (by this job) to the |
| * UI thread will not run until the previously scheduled UI runnables are |
| * complete also (e.g. events triggered by the aforementioned <em>updates</em> |
| * etc.). |
| * <p> |
| * Typically, client code will set the JPA selection when some sort of user |
| * action is complete (e.g. when a menu action is complete). The action will |
| * have modified the model (e.g. setting an attribute's mapping) and, if the |
| * action was performed on a single element, will want to select that modified |
| * element once the action is complete (via the appropriate JPA selection |
| * manager). Unless the action is performing its action sychronously |
| * (via a call to |
| * {@link org.eclipse.jpt.jpa.core.JpaProjectManager#execute(org.eclipse.jpt.common.utility.command.Command) |
| * JpaProjectManager.execute(...)}), |
| * the modification(s) will have triggered a background <em>update</em> that |
| * executes in a job that locks the corresponding project. This <em>update</em> will |
| * modify other parts of the model, resulting in events that will modify the UI. |
| * These UI modifications must be dispatched to the UI thread (via something like |
| * {@link org.eclipse.jpt.common.ui.internal.swt.listeners.SWTPropertyChangeListenerWrapper |
| * SWTPropertyChangeListenerWrapper}). |
| * <p> |
| * As a result, the setting of the JPA selection (which, itself, also modifies |
| * the UI via events) is performed via a job that, like the <em>update</em> job, |
| * locks on the corresponding project. As a result this job will not execute |
| * until any outstanding <em>update</em> jobs are complete. Once this job is |
| * executing, it dispatches the actual setting of the JPA selection to the UI |
| * thread; meaning, again, it will not execute until any outstanding UI-targeted |
| * events triggered by the <em>updates</em> have executed. |
| */ |
| class SetJpaSelectionJob |
| extends Job |
| { |
| private final Runnable setJpaSelectionRunnable; |
| |
| |
| SetJpaSelectionJob(Manager manager, JpaStructureNode selection) { |
| super(JptJpaUiMessages.SET_JPA_SELECTION_JOB_NAME); |
| this.setJpaSelectionRunnable = new SetJpaSelectionRunnable(manager, selection); |
| // if the selection is null we don't need a scheduling rule - |
| // the JPA selection can be set to null at any time |
| if (selection != null) { |
| this.setRule(selection.getJpaProject().getProject()); |
| } |
| } |
| |
| @Override |
| protected IStatus run(IProgressMonitor monitor) { |
| DisplayTools.asyncExec(this.setJpaSelectionRunnable); |
| return Status.OK_STATUS; |
| } |
| |
| /** |
| * UI runnable. |
| * @see SetJpaSelectionJob#run(IProgressMonitor) |
| */ |
| private static class SetJpaSelectionRunnable |
| implements Runnable |
| { |
| private final Manager jpaSelectionManager; |
| private final JpaStructureNode selection; |
| |
| SetJpaSelectionRunnable(Manager manager, JpaStructureNode selection) { |
| super(); |
| this.jpaSelectionManager = manager; |
| this.selection = selection; |
| } |
| |
| public void run() { |
| this.jpaSelectionManager.setSelection_(this.selection); |
| } |
| |
| @Override |
| public String toString() { |
| return ObjectTools.toString(this, this.selection); |
| } |
| } |
| |
| /** |
| * Internal interface used to set the JPA selection while executing on |
| * the UI thread. |
| * @see SetJpaSelectionRunnable#run() |
| */ |
| interface Manager { |
| /** |
| * @see SetJpaSelectionRunnable#run() |
| */ |
| void setSelection_(JpaStructureNode selection); |
| } |
| } |