Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.jsoar.debugger.JSoarDebugger Maven / Gradle / Ivy
/*
* Copyright (c) 2008 Dave Ray
*
* Created on Sep 21, 2008
*/
package org.jsoar.debugger;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.concurrent.Callable;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;
import javax.swing.AbstractAction;
import javax.swing.AbstractButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import org.jdesktop.swingx.JXFrame;
import org.jsoar.debugger.actions.AboutAction;
import org.jsoar.debugger.actions.ActionManager;
import org.jsoar.debugger.actions.EditProductionAction;
import org.jsoar.debugger.actions.ExciseProductionAction;
import org.jsoar.debugger.actions.ExitAction;
import org.jsoar.debugger.actions.GarbageCollectorAction;
import org.jsoar.debugger.actions.InitSoarAction;
import org.jsoar.debugger.actions.MatchesProductionAction;
import org.jsoar.debugger.actions.RestoreLayoutAction;
import org.jsoar.debugger.actions.RunAction;
import org.jsoar.debugger.actions.SetBreakpointAction;
import org.jsoar.debugger.actions.SourceFileAction;
import org.jsoar.debugger.actions.StepAction;
import org.jsoar.debugger.actions.StopAction;
import org.jsoar.debugger.actions.UrlAction;
import org.jsoar.debugger.selection.SelectionManager;
import org.jsoar.debugger.selection.SelectionProvider;
import org.jsoar.debugger.stopcommand.StopCommandAction;
import org.jsoar.debugger.stopcommand.StopCommandView;
import org.jsoar.debugger.stopcommand.StopCommandViewFactory;
import org.jsoar.debugger.util.Prefs;
import org.jsoar.debugger.util.PrefsFactory;
import org.jsoar.debugger.util.SwingTools;
import org.jsoar.kernel.Agent;
import org.jsoar.kernel.DebuggerProvider;
import org.jsoar.kernel.DebuggerProvider.CloseAction;
import org.jsoar.kernel.RunType;
import org.jsoar.kernel.SoarException;
import org.jsoar.kernel.SoarProperties;
import org.jsoar.kernel.events.AfterInitSoarEvent;
import org.jsoar.kernel.events.StopEvent;
import org.jsoar.runtime.CompletionHandler;
import org.jsoar.runtime.ThreadedAgent;
import org.jsoar.runtime.ThreadedAgentDetachedEvent;
import org.jsoar.util.adaptables.Adaptable;
import org.jsoar.util.adaptables.Adaptables;
import org.jsoar.util.commands.SoarCommand;
import org.jsoar.util.commands.SoarCommandInterpreter;
import org.jsoar.util.commands.SoarCommands;
import org.jsoar.util.events.SoarEvent;
import org.jsoar.util.events.SoarEventListener;
import org.jsoar.util.properties.PropertyChangeEvent;
import org.jsoar.util.properties.PropertyKey;
import org.jsoar.util.properties.PropertyListener;
import org.jsoar.util.properties.PropertyListenerHandle;
import org.jsoar.util.properties.PropertyProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.MultipleCDockable;
import bibliothek.gui.dock.common.event.CFocusListener;
import bibliothek.gui.dock.common.intern.CDockable;
import bibliothek.gui.dock.common.menu.CLayoutChoiceMenuPiece;
import bibliothek.gui.dock.common.menu.CThemeMenuPiece;
import bibliothek.gui.dock.common.theme.ThemeMap;
import bibliothek.gui.dock.facile.menu.RootMenuPiece;
import bibliothek.gui.dock.facile.menu.SubmenuPiece;
import bibliothek.gui.dock.support.menu.SeparatingMenuPiece;
import bibliothek.util.xml.XElement;
import bibliothek.util.xml.XIO;
/**
* @author ray
*/
public class JSoarDebugger extends JPanel implements Adaptable
{
private static final long serialVersionUID = 7997119112479665988L;
private static final Logger logger = LoggerFactory.getLogger(JSoarDebugger.class);
private static final ResourceBundle resources = ResourceBundle.getBundle("jsoar");
private static Preferences PREFERENCES;
private static final PropertyKey CREATED_BY = PropertyKey.builder("JSoarDebugger.createdBy", JSoarDebugger.class).readonly(true).build();
private static final Map debuggers = Collections.synchronizedMap(new HashMap());
private final SelectionManager selectionManager = new SelectionManager();
private final ActionManager actionManager = new ActionManager(this);
private final RunControlModel runControlModel = new RunControlModel();
private Map providerProperties = new HashMap();
private boolean resetPreferencesAtExit = false;
private ThreadedAgent agent;
private final LoadPluginCommand loadPluginCommand = new LoadPluginCommand(this);
private final List plugins = new CopyOnWriteArrayList();
public JFrame frame;
private CControl docking;
private StatusBar status;
private final List views = new ArrayList<>();
private final List soarEventListeners = new ArrayList();
private final List> propertyListeners = new ArrayList>();
private static float fontScale = 1.0f;
private StopCommandViewFactory factory;
/**
* Construct a new debugger. Add to a JFrame and call initialize().
*/
private JSoarDebugger(Map properties)
{
super(new BorderLayout());
this.providerProperties.putAll(properties);
}
public static float getFontScale() {
return fontScale;
}
/**
* Initialize the debugger
*
* @param parentFrame The parent frame of the debugger
* @param proxy A non-null, initialized agent proxy
*/
private void initialize(final JXFrame parentFrame, ThreadedAgent proxy)
{
logger.info("Initializing debugger for agent '" + proxy + "'");
final float scaleUpFactor = 4.0f / 3.0f;
final float scaleDownFactor = .75f;
parentFrame.addMouseWheelListener(e ->
{
if (e.isControlDown()){
float scaleFactor = 1.0f;
if (e.getWheelRotation() < 0) {
scaleFactor = scaleUpFactor;
} else if (e.getWheelRotation() > 0) {
scaleFactor = scaleDownFactor;
}
fontScale = fontScale * scaleFactor;
setFontScale(scaleFactor, parentFrame.getComponents());
SwingTools.setFontScale(scaleFactor);
parentFrame.repaint();
}
});
parentFrame.addKeyListener(new KeyAdapter()
{
@Override
public void keyPressed(KeyEvent e)
{
if (e.isControlDown()) {
float scaleFactor = 1.0f;
if (e.getKeyCode() == KeyEvent.VK_PLUS || e.getKeyCode() == KeyEvent.VK_EQUALS){
scaleFactor = scaleUpFactor;
} else if (e.getKeyCode() == KeyEvent.VK_MINUS){
scaleFactor = scaleDownFactor;
} else {
super.keyPressed(e);
}
fontScale = fontScale * scaleFactor;
setFontScale(scaleFactor, parentFrame.getComponents());
SwingTools.setFontScale(scaleFactor);
parentFrame.repaint();
} else {
super.keyPressed(e);
}
}
});
this.frame = parentFrame;
this.frame.setTitle("JSoar Debugger - " + proxy.getName());
this.agent = proxy;
proxy.getInterpreter().addCommand("load-plugin", loadPluginCommand);
proxy.getInterpreter().addCommand("edit-production", new EditProductionCommand(agent.getAgent()));
agent.getAgent().getRhsFunctions().registerHandler(new AcceptRhsFunction());
this.docking = new CControl(this.frame);
this.docking.setTheme(ThemeMap.KEY_ECLIPSE_THEME);
// Track selection to active view
this.docking.addFocusListener(new CFocusListener() {
@Override
public void focusLost(CDockable dockable)
{
}
@Override
public void focusGained(final CDockable newDockable)
{
SelectionProvider provider = Adaptables.adapt(newDockable, SelectionProvider.class);
if(provider != null)
{
selectionManager.setSelectionProvider(provider);
}
// HACK: For some reason the WM tree briefly gets focus which messes this
// up when using a hotkey to switch to the trace view. So invoke later
// after everything settles down.
SwingUtilities.invokeLater(() ->
{
if(newDockable instanceof AbstractAdaptableView)
{
((AbstractAdaptableView) newDockable).activate();
}
});
}
});
this.add(docking.getContentArea(), BorderLayout.CENTER);
initActions();
this.add(status = new StatusBar(proxy), BorderLayout.SOUTH);
factory = new StopCommandViewFactory(this);
factory.setDefaultLocation(docking.getDefaultLocation());
docking.addMultipleDockableFactory("stop-command-factory", factory);
initViews();
initMenuBar();
initToolbar();
// Track the agent name in the title bar
saveListener(proxy.getProperties().addListener(SoarProperties.NAME, new PropertyListener() {
@Override
public void propertyChanged(PropertyChangeEvent event)
{
frame.setTitle("JSoar Debugger - " + event.getNewValue());
}}));
// Track agent's running state
saveListener(proxy.getProperties().addListener(SoarProperties.IS_RUNNING, new PropertyListener() {
@Override
public void propertyChanged(PropertyChangeEvent event)
{
updateActionsAndStatus();
}}));
// Update after init-soar
proxy.getEvents().addListener(AfterInitSoarEvent.class, saveListener(event ->
{
proxy.getPrinter().flush();
newUpdateCompleter(true).finish(null);
}));
// Update when the agent stops running
proxy.getEvents().addListener(StopEvent.class, saveListener(event ->
{
proxy.getPrinter().flush();
newUpdateCompleter(false).finish(null);
}));
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e)
{
final Preferences winPrefs = getWindowPrefs();
final Rectangle r = frame.getBounds();
if(frame.getExtendedState() == JFrame.NORMAL)
{
winPrefs.putInt("x", r.x);
winPrefs.putInt("y", r.y);
winPrefs.putInt("width", r.width);
winPrefs.putInt("height", r.height);
}
exit();
}});
final Preferences winPrefs = getWindowPrefs();
if(winPrefs.get("x", null) != null)
{
frame.setBounds(winPrefs.getInt("x", 0),
winPrefs.getInt("y", 0),
winPrefs.getInt("width", 1200),
winPrefs.getInt("height", 1024));
}
else
{
frame.setSize(1200, 1024);
frame.setLocationRelativeTo(null); // center
}
readDefaultLayout();
update(false);
}
public static void setFontScale(float scaleFactor, Component[] components)
{
// SwingTools.setFontScale(scaleFactor);
for(Component c: components){
if (c instanceof Container){
setFontScale(scaleFactor,((Container) c).getComponents());
}
c.setFont(c.getFont().deriveFont(c.getFont().getSize()*scaleFactor));
}
}
private void readDefaultLayout()
{
try
{
final InputStream in = JSoarDebugger.class.getResourceAsStream("layout.xml");
if(in != null)
{
try
{
final XElement xml = XIO.readUTF(in);
this.docking.readXML(xml);
}
finally
{
in.close();
}
}
}
catch (IOException e)
{
logger.error("Failed to load default debugger layout: " + e.getMessage(), e);
}
}
private Preferences getWindowPrefs()
{
return getPreferences().node("window");
}
private void saveListener(PropertyListenerHandle listener)
{
propertyListeners.add(listener);
}
private SoarEventListener saveListener(SoarEventListener listener)
{
soarEventListeners.add(listener);
return listener;
}
private void initViews()
{
addView(new ProductionEditView(this));
addView(new ProductionListView(this));
addView(new PartialMatchesView(this));
addView(new MatchSetView(this));
addView(new TraceView(this));
addView(new WmeSearchView(this));
addView(new WmeSupportView(this));
addView(new PreferencesView(this));
addView(new GoalStackView(this));
addView(new GdsView(this));
addView(new WorkingMemoryView(this));
}
private T addView(T view)
{
return addView(view, true);
}
private T addView(T view, boolean visible)
{
views.add(view);
docking.addDockable(view);
if(visible)
{
view.setVisible(true);
}
return view;
}
private T addView(T view)
{
return addView(view, true);
}
private T addView(T view, boolean visible)
{
views.add(view);
docking.addDockable(view);
if(visible)
{
view.setVisible(true);
}
return view;
}
public ThreadedAgent getAgent()
{
return agent;
}
public SelectionManager getSelectionManager()
{
return selectionManager;
}
public RunControlModel getRunControlModel()
{
return runControlModel;
}
public ActionManager getActionManager()
{
return actionManager;
}
public void updateActionsAndStatus()
{
if(SwingUtilities.isEventDispatchThread())
{
actionManager.updateActions();
status.refresh(false);
}
else
{
SwingUtilities.invokeLater(this::updateActionsAndStatus);
}
}
void addPlugin(JSoarDebuggerPlugin plugin)
{
plugins.add(plugin);
}
public void exit()
{
detach();
if(resetPreferencesAtExit)
{
try
{
getPreferences().removeNode();
}
catch (BackingStoreException e)
{
logger.error(e.getMessage(), e);
}
try {
Prefs.getLayoutFile().deleteOnExit();
} catch (IOException e) {
e.printStackTrace();
}
}
final Object closeAction = providerProperties.get(DebuggerProvider.CLOSE_ACTION);
if(closeAction == null || closeAction == CloseAction.EXIT)
{
System.exit(0);
}
}
public static Preferences getPreferences() {
if (PREFERENCES == null) {
System.setProperty("java.util.prefs.PreferencesFactory", PrefsFactory.class.getName());
PREFERENCES = Preferences.userRoot().node("org/jsoar/debugger");
}
return PREFERENCES;
}
public void restoreLayout()
{
try {
docking.readXML(Prefs.getLayoutFile());
} catch (IOException e) {
e.printStackTrace();
}
// TODO: Implement layout storage in a way that doesn't suck.
}
private void initActions()
{
new ExitAction(actionManager);
new RunAction(actionManager);
new StopAction(actionManager);
new InitSoarAction(actionManager);
new SourceFileAction(actionManager);
new ExciseProductionAction(actionManager);
new SetBreakpointAction(actionManager);
new AboutAction(actionManager);
new EditProductionAction(actionManager);
new RestoreLayoutAction(actionManager);
new StopCommandAction(actionManager);
new MatchesProductionAction(actionManager, false);
new MatchesProductionAction(actionManager, true);
}
@SuppressWarnings("serial")
private void initMenuBar()
{
final JMenuBar bar = new JMenuBar();
final JMenu fileMenu = new JMenu("File");
fileMenu.add(actionManager.getAction(SourceFileAction.class));
fileMenu.addSeparator();
fileMenu.add(new AbstractAction("Reset preferences ...") {
private static final long serialVersionUID = -294498142478298760L;
@Override
public void actionPerformed(ActionEvent e)
{
resetPreferencesAtExit = true;
JOptionPane.showMessageDialog(frame, "Preferences will be reset next time the debugger is loaded.");
}});
fileMenu.addSeparator();
fileMenu.add(actionManager.getAction(ExitAction.class));
bar.add(fileMenu);
final RootMenuPiece viewMenu = new RootMenuPiece( "View", false );
// L&F is cute, but for some reason, switching L&F breaks the trace command box
// viewMenu.add(new SubmenuPiece( "Look and feel", true, new CLookAndFeelMenuPiece( docking )));
viewMenu.getMenu().addSeparator();
viewMenu.getMenu().add(actionManager.getAction(StopCommandAction.class));
viewMenu.add(new SeparatingMenuPiece(
new SubmenuPiece( "Theme", true, new CThemeMenuPiece( docking )),
true, true, false));
final SubmenuPiece layoutMenu = new SubmenuPiece("Layout", false,
new CLayoutChoiceMenuPiece( docking, false ));
layoutMenu.getMenu().add(actionManager.getAction(RestoreLayoutAction.class));
viewMenu.add(layoutMenu);
viewMenu.getMenu().add(new AbstractAction("Save Layout to File")
{
@Override
public void actionPerformed(ActionEvent e)
{
try
{
docking.writeXML(Prefs.getLayoutFile());
}
catch (IOException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
viewMenu.getMenu().addSeparator();
JCheckBoxMenuItem autoCompletionsMenuItem = new JCheckBoxMenuItem("Automatically Show Command Completions", isAutoCompletionsEnabled());
viewMenu.getMenu().add(autoCompletionsMenuItem);
autoCompletionsMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
AbstractButton aButton = (AbstractButton) event.getSource();
boolean selected = aButton.getModel().isSelected();
getPreferences().put("autoShowCommandCompletions", String.valueOf(selected));
}
});
JCheckBoxMenuItem autoHelpMenuItem = new JCheckBoxMenuItem("Automatically Show Command Help", isAutoHelpEnabled());
viewMenu.getMenu().add(autoHelpMenuItem);
autoHelpMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
AbstractButton aButton = (AbstractButton) event.getSource();
boolean selected = aButton.getModel().isSelected();
getPreferences().put("autoShowHelp", String.valueOf(selected));
}
});
new ViewSelectionMenu( docking, viewMenu.getMenu());
bar.add(viewMenu.getMenu());
final JMenu runMenu = new JMenu("Run");
runMenu.add(actionManager.getAction(RunAction.class));
runMenu.add(actionManager.getAction(StopAction.class));
runMenu.addSeparator();
runMenu.add(new StepAction(actionManager, "Forever", RunType.FOREVER, "ctrl shift F"));
runMenu.add(new StepAction(actionManager, "1 Elaboration", RunType.ELABORATIONS, "ctrl shift E"));
runMenu.add(new StepAction(actionManager, "1 Phase", RunType.PHASES, "ctrl shift P"));
runMenu.add(new StepAction(actionManager, "1 Decision", RunType.DECISIONS, "ctrl shift D"));
runMenu.addSeparator();
runMenu.add(actionManager.getAction(InitSoarAction.class));
bar.add(runMenu);
final JMenu toolsMenu = new JMenu("Tools");
toolsMenu.add(new GarbageCollectorAction(actionManager));
bar.add(toolsMenu);
final JMenu helpMenu = new JMenu("Help");
helpMenu.add(new UrlAction(actionManager, "JSoar Home Page", resources.getString("jsoar.site.url")));
helpMenu.add(new UrlAction(actionManager, "CSoar Home Page", resources.getString("csoar.site.url")));
helpMenu.add(new AbstractAction("Command Help") {
@Override
public void actionPerformed(ActionEvent e)
{
Callable callable = () -> {
SoarCommand cmd = getAgent().getInterpreter().getCommand("help", null);
cmd.execute(null, new String[] {"help"});
getAgent().getPrinter().flush();
return null;
};
getAgent().execute(callable , null);
}});
helpMenu.add(new UrlAction(actionManager, "Quick Help", JSoarDebugger.class.getResource("/org/jsoar/debugger/jsoar quick help.html").toString()));
helpMenu.addSeparator();
helpMenu.add(actionManager.getAction(AboutAction.class));
bar.add(helpMenu);
frame.setJMenuBar(bar);
}
private void initToolbar()
{
JToolBar bar = new JToolBar();
bar.setFloatable(false);
bar.add(new RunControlPanel(this));
add(bar, BorderLayout.NORTH);
}
public void update(final boolean afterInitSoar)
{
updateActionsAndStatus();
final List refreshables = Adaptables.adaptCollection(views, Refreshable.class);
for(Refreshable r : refreshables)
{
r.refresh(afterInitSoar);
}
}
/**
* Executes the CompletionHandler on the Swing thread. Do not do any agent interaction in here!
* @param afterInitSoar True if calling this in response to Soar being (re)initialized
*/
public CompletionHandler newUpdateCompleter(final boolean afterInitSoar)
{
return SwingCompletionHandler.newInstance( new CompletionHandler() {
@Override
public void finish(Void result)
{
update(afterInitSoar);
}
});
}
public static void main(final String[] args)
{
SwingTools.initializeLookAndFeel();
float scale = Float.parseFloat(System.getProperty("fontScale","1.0"));
SwingTools.setFontScale(scale);
fontScale = scale;
SwingUtilities.invokeLater(() -> initialize(args));
}
/**
* Attach a new debugger window to the given threaded agent. This function
* must be called from the Swing event thread!
*
* @param proxy an initialized threaded agent to attach to
* @return the debugger
*/
public static JSoarDebugger attach(ThreadedAgent proxy, Map properties)
{
synchronized(debuggers)
{
JSoarDebugger debugger = debuggers.get(proxy);
if(debugger == null)
{
//DockingManager.setFloatingEnabled(true);
debugger = new JSoarDebugger(properties);
final JXFrame frame = new JXFrame();
frame.setContentPane(debugger);
debugger.initialize(frame, proxy);
frame.setVisible(true);
debuggers.put(proxy, debugger);
proxy.getEvents().addListener(ThreadedAgentDetachedEvent.class, new ThreadedAgentDetachedEventListener());
}
else
{
debugger.frame.setVisible(true);
debugger.frame.requestFocus();
}
return debugger;
}
}
private static class ThreadedAgentDetachedEventListener implements SoarEventListener
{
@Override
public void onEvent(SoarEvent event)
{
if(event instanceof ThreadedAgentDetachedEvent) {
ThreadedAgentDetachedEvent threadedAgentDetachedEvent = (ThreadedAgentDetachedEvent)event;
ThreadedAgent agent = threadedAgentDetachedEvent.getAgent();
JSoarDebugger debugger = JSoarDebugger.debuggers.get(agent);
if(debugger != null) {
debugger.exit();
}
agent.getEvents().removeListener(ThreadedAgentDetachedEvent.class, this);
}
}
}
public static void exit(ThreadedAgent proxy) {
synchronized(debuggers)
{
JSoarDebugger debugger = debuggers.get(proxy);
if(debugger != null) {
debugger.exit();
} else {
logger.warn("Tried to close debugger for agent {}, but no debugger is open.", proxy.getName());
}
}
}
public static JSoarDebugger getDebugger(ThreadedAgent proxy) {
return debuggers.get(proxy);
}
/**
* Detach debugger from agent
*/
public void detach()
{
synchronized(debuggers)
{
logger.info(String.format("Detaching from agent '" + agent + "'"));
// clean up soar prop listeners
for(PropertyListenerHandle listener : propertyListeners)
{
listener.removeListener();
}
// clean up soar event listener
for(SoarEventListener listener : soarEventListeners)
{
agent.getEvents().removeListener(null, listener);
}
soarEventListeners.clear();
// clean up disposables
runControlModel.dispose();
for(Disposable d : Adaptables.adaptCollection(views, Disposable.class))
{
d.dispose();
}
views.clear();
if(frame.isVisible())
{
frame.setVisible(false);
}
for(JSoarDebuggerPlugin plugin : plugins)
{
plugin.shutdown();
}
plugins.clear();
debuggers.remove(agent);
// If the agent was created by this debugger, dispose it. This is important
// so things like SMEM database will be flushed at shutdown.
if(shouldDisposeAgent())
{
agent.dispose();
}
}
}
private boolean shouldDisposeAgent()
{
return this == agent.getProperties().get(CREATED_BY) ||
EnumSet.of(CloseAction.EXIT, CloseAction.DISPOSE).
contains((CloseAction) providerProperties.get(DebuggerProvider.CLOSE_ACTION)) ;
}
/**
* This is identical to {@link #main(String[])}, but it must be called from
* the Swing event thread. Also the look and feel must be initialized prior
* to calling this.
*
* @param args command-line arguments
*/
public static JSoarDebugger initialize(final String[] args)
{
final ThreadedAgent agent = ThreadedAgent.create();
final JSoarDebugger debugger = attach(agent, new HashMap());
agent.getProperties().setProvider(CREATED_BY, new PropertyProvider()
{
@Override
public JSoarDebugger get()
{
return debugger;
}
@Override
public JSoarDebugger set(JSoarDebugger value)
{
throw new UnsupportedOperationException("Can't set " + CREATED_BY);
}
});
debugger.agent.execute(() ->
{
for(String arg : args)
{
try
{
SoarCommands.source(debugger.getAgent().getInterpreter(), arg);
}
catch (SoarException e)
{
logger.error("Error sourcing file '" + arg + "': " + e.getMessage(), e);
debugger.getAgent().getPrinter().error("Error sourcing file '%s': %s", arg, e.getMessage());
}
}
debugger.getAgent().getPrinter().flush();
return null;
}, debugger.newUpdateCompleter(false));
return debugger;
}
/**
* Creates and returns a {@link DebuggerProvider} that will open this
* debugger when an agent calls the debug RHS function
*
* @return a new debugger provider that opens this debugger with a default
* configuration
*/
public static DebuggerProvider newDebuggerProvider()
{
return newDebuggerProvider();
}
/* (non-Javadoc)
* @see org.jsoar.util.adaptables.Adaptable#getAdapter(java.lang.Class)
*/
@Override
public Object getAdapter(Class klass)
{
if(klass.equals(SoarCommandInterpreter.class))
{
return getAgent().getInterpreter();
}
if(klass.equals(Agent.class))
{
return agent.getAgent();
}
if(klass.equals(ThreadedAgent.class))
{
return agent;
}
if(klass.equals(SelectionManager.class))
{
return selectionManager;
}
if(klass.equals(RunControlModel.class))
{
return runControlModel;
}
if(klass.equals(ActionManager.class))
{
return actionManager;
}
Object o = Adaptables.findAdapter(views, klass);
if(o != null)
{
return o;
}
return Adaptables.findAdapter(plugins, klass);
}
@Override
public String toString()
{
return frame.getTitle();
}
public void addStopCommandView()
{
factory.setDefaultLocation(views.get(0).getBaseLocation());
addView(new StopCommandView(factory, this));
}
public boolean isAutoCompletionsEnabled() {
return getPreferences().getBoolean("autoShowCommandCompletions", true);
}
public boolean isAutoHelpEnabled() {
return getPreferences().getBoolean("autoShowHelp", true);
}
}