package org.rstudio.studio.client.workbench.addins;
import com.google.gwt.user.client.Command;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.rstudio.core.client.CommandWithArg;
import org.rstudio.core.client.Pair;
import org.rstudio.core.client.command.AddinCommandBinding;
import org.rstudio.core.client.command.EditorCommandManager.EditorKeyBindings;
import org.rstudio.core.client.command.KeyMap;
import org.rstudio.core.client.command.KeyMap.CommandBinding;
import org.rstudio.core.client.command.KeyMap.KeyMapType;
import org.rstudio.core.client.command.KeyboardShortcut.KeySequence;
import org.rstudio.core.client.command.ShortcutManager;
import org.rstudio.core.client.files.FileBacked;
import org.rstudio.studio.client.application.events.EventBus;
import org.rstudio.studio.client.workbench.MainWindowObject;
import org.rstudio.studio.client.workbench.addins.Addins.RAddin;
import org.rstudio.studio.client.workbench.addins.Addins.RAddins;
import org.rstudio.studio.client.workbench.addins.events.AddinRegistryUpdatedEvent;
import org.rstudio.studio.client.workbench.events.SessionInitEvent;
import org.rstudio.studio.client.workbench.events.SessionInitHandler;
import org.rstudio.studio.client.workbench.model.Session;
import org.rstudio.studio.client.workbench.views.source.SourceWindowManager;
import java.util.ArrayList;
import java.util.List;
@Singleton
public class AddinsCommandManager
{
@Inject
public AddinsCommandManager(EventBus events,
final Session session)
{
events_ = events;
bindings_ = new FileBacked<EditorKeyBindings>(
KEYBINDINGS_PATH,
false,
EditorKeyBindings.create());
// load addin bindings on session init
events_.addHandler(
SessionInitEvent.TYPE,
new SessionInitHandler()
{
@Override
public void onSessionInit(SessionInitEvent sie)
{
MainWindowObject.rAddins().set(session.getSessionInfo().getAddins());
loadBindings();
}
});
// set bindings when updated (e.g. through ModifyKeyboardShortcuts widget)
events_.addHandler(
AddinsKeyBindingsChangedEvent.TYPE,
new AddinsKeyBindingsChangedEvent.Handler()
{
@Override
public void onAddinsKeyBindingsChanged(AddinsKeyBindingsChangedEvent event)
{
registerBindings(event.getBindings(), null);
}
});
// update addin bindings when registry populated
events_.addHandler(
AddinRegistryUpdatedEvent.TYPE,
new AddinRegistryUpdatedEvent.Handler()
{
@Override
public void onAddinRegistryUpdated(AddinRegistryUpdatedEvent event)
{
// all windows will receive this event, so just let the main window
// cache the addins in its own window
if (SourceWindowManager.isMainSourceWindow())
MainWindowObject.rAddins().set(event.getData());
loadBindings();
}
});
}
public void addBindingsAndSave(final EditorKeyBindings newBindings,
final CommandWithArg<EditorKeyBindings> onLoad)
{
bindings_.execute(new CommandWithArg<EditorKeyBindings>()
{
@Override
public void execute(EditorKeyBindings currentBindings)
{
currentBindings.insert(newBindings);
bindings_.set(currentBindings, new Command()
{
@Override
public void execute()
{
loadBindings(onLoad);
}
});
}
});
}
public void loadBindings()
{
loadBindings(null);
}
public void loadBindings(final CommandWithArg<EditorKeyBindings> afterLoad)
{
bindings_.execute(new CommandWithArg<EditorKeyBindings>()
{
@Override
public void execute(EditorKeyBindings bindings)
{
registerBindings(bindings, afterLoad);
}
});
}
private void registerBindings(final EditorKeyBindings bindings,
final CommandWithArg<EditorKeyBindings> afterLoad)
{
List<Pair<List<KeySequence>, CommandBinding>> commands =
new ArrayList<Pair<List<KeySequence>, CommandBinding>>();
RAddins rAddins = MainWindowObject.rAddins().get();
for (String id : bindings.iterableKeys())
{
List<KeySequence> keyList = bindings.get(id).getKeyBindings();
RAddin addin = rAddins.get(id);
if (addin == null)
continue;
CommandBinding binding = new AddinCommandBinding(addin);
commands.add(new Pair<List<KeySequence>, CommandBinding>(keyList, binding));
}
KeyMap map = ShortcutManager.INSTANCE.getKeyMap(KeyMapType.ADDIN);
for (int i = 0; i < commands.size(); i++)
{
map.setBindings(
commands.get(i).first,
commands.get(i).second);
}
if (afterLoad != null)
afterLoad.execute(bindings);
}
public void resetBindings()
{
resetBindings(null);
}
public void resetBindings(final Command afterReset)
{
bindings_.set(EditorKeyBindings.create(), new Command()
{
@Override
public void execute()
{
if (afterReset != null)
afterReset.execute();
}
});
}
public RAddins getRAddins()
{
return MainWindowObject.rAddins().get();
}
private final FileBacked<EditorKeyBindings> bindings_;
private static final String KEYBINDINGS_PATH = "~/.R/rstudio/keybindings/addins.json";
// Injected ----
private EventBus events_;
}