package jetbrains.mps.debugger.api.ui.tree; /*Generated by MPS */ import org.apache.log4j.Logger; import org.apache.log4j.LogManager; import org.jetbrains.annotations.NotNull; import jetbrains.mps.debug.api.programState.IWatchable; import jetbrains.mps.debug.api.AbstractUiState; import java.util.concurrent.atomic.AtomicBoolean; import java.util.List; import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes; import jetbrains.mps.internal.collections.runtime.ListSequence; import java.util.ArrayList; import jetbrains.mps.debug.api.programState.Watchable2; import jetbrains.mps.debug.api.programState.IValue; import javax.swing.tree.DefaultTreeModel; import com.intellij.openapi.application.ApplicationManager; import org.apache.log4j.Level; public class WatchableNode extends AbstractWatchableNode { private static final Logger LOG = LogManager.getLogger(WatchableNode.class); private volatile boolean myInitialized; @NotNull private final IWatchable myWatchable; private final AbstractUiState myState; private final AtomicBoolean myInitializationInProgress = new AtomicBoolean(false); private final List<_FunctionTypes._void_P0_E0> myCallbacks = ListSequence.fromList(new ArrayList<_FunctionTypes._void_P0_E0>()); public WatchableNode(@NotNull IWatchable w, AbstractUiState state) { super((w instanceof Watchable2 ? ((Watchable2) w).getSourceNode() : ((w.getNode() == null ? null : w.getNode().getReference())))); myWatchable = w; myState = state; setNodeIdentifier(calculateNodeId(w)); setIcon(w.getPresentationIcon()); } @Override protected void doUpdate() { this.removeAllChildren(); myInitialized = false; } @Override public boolean isInitialized() { return myInitialized; } private static String calculateNodeId(IWatchable watchable) { IValue value = watchable.getValue(); if (value == null) { return watchable.getName() + " = null"; } return watchable.getName() + " = " + value.getValuePresentation(); } @Override public boolean isLeaf() { IValue value = getValue(); return value == null || !(value.isStructure()); } public IValue getValue() { return myWatchable.getValue(); } /*package*/ void nodeChanged() { ((DefaultTreeModel) getTree().getModel()).nodeStructureChanged(this); } @Override protected void doInit() { init(new _FunctionTypes._void_P0_E0() { public void invoke() { } }); } public void init(final _FunctionTypes._void_P0_E0 callback) { if (myInitialized) { callback.invoke(); return; } if (!(isLeaf())) { if (myInitializationInProgress.compareAndSet(false, true)) { myState.invokeEvaluation(new _FunctionTypes._void_P0_E0() { public void invoke() { try { myWatchable.getValue().initSubvalues(); ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { try { removeAllChildren(); for (IWatchable watchable : ListSequence.fromList(getValue().getSubvalues())) { add(new WatchableNode(watchable, myState)); } updatePresentation(); myInitialized = true; callback.invoke(); for (_FunctionTypes._void_P0_E0 callback : ListSequence.fromList(myCallbacks)) { try { callback.invoke(); } catch (Throwable t) { if (LOG.isEnabledFor(Level.ERROR)) { LOG.error("", t); } } } ListSequence.fromList(myCallbacks).clear(); nodeChanged(); } finally { myInitializationInProgress.set(false); } } }); } catch (Throwable t) { myInitializationInProgress.set(false); } } }); } else { // callbacks are accessed from ui thread only ListSequence.fromList(myCallbacks).addElement(callback); } } } }