Open mast-eu opened 5 years ago
Please coordinate the thinking with moving out plugins from the main application, like in #6415 and #5574
I created a new project to track all issues related to the topic.
@RussKie: Maybe it's just me, but I do not find any project. Where exactly is it?
I do not find any project
https://github.com/orgs/gitextensions/projects/3#card-20603187
I don't know if it's on purpose but that's not a public project... (page 404)
I don't know if it's on purpose but that's not a public project... (page 404)
@RussKie can change
Please try again
That's Ok. 👍
Few extra API good to have:
HasUI: bool
to indicate whether a plugin should have a menu (e.g. JIRA integration plugin doesn't have a UI)IsConfigurable: bool
to indicate whether a plugin can be configured by a user
LoadSettings: ?
- to load settings to present in a settings UISaveSettings: ?
- to save settingsNB: names/signatures are open to discussion
Few extra API good to have:
HasUI: bool
to indicate whether a plugin should have a menu (e.g. JIRA integration plugin doesn't have a UI)
IsConfigurable: bool
to indicate whether a plugin can be configured by a user
LoadSettings: ?
- to load settings to present in a settings UISaveSettings: ?
- to save settingsNB: names/signatures are open to discussion
What about implement this by querying interfaces?
Like if Plugin class implements interface IPluginsMenuItemProvider
or ISettingsContainer
..
Or go even further and use more MEF exports, like VS?
I am not that familiar with MEF, but that may as well work. Will probably be nicer to deal with too.
Hypothetical example: Support for extending GE main menu.
Contract:
public interface IMainMenuFactory
{
ToolStripMenuItem Create(Context context);
}
Plugin implementation:
[Export(typeof(IMainMenuFactory))]
[Order(After = GitExtensions.MainMenuDefaultItems.Commands)]
public class BundleBackuperMainMenuFactory : IMainMenuFactory
{
public ToolStripMenuItem Create(Context context)
{
var item = new ToolStripMenuItem("Bundles", OnClick);
//...
return item;
}
}
Consument (somewhere deeply inside FormBrowse.cs):
class FormBrowse
{
//...
[ImportMany(typeof(IMainMenuFactory))
public IEnumerable<Lazy<IMainMenuFactory, OrderMetadata>> MainMenuFactories { get; set; }
//...
private void InitializeMainMenu()
{
InitializeDefaultMainMenu();
var context = new Context();
var factories = MainMenuFactories);
foreach (var factory in MainMenuFactories)
{
var item = factory.Value.Create(context);
var index = OrderMetadataSorder.GetPosition(factory.Metadata);
mainMenu.Items.Insert(index, item);
}
}
//...
}
(These snippets possibly won't compile)
I'm a bit hesitant allowing plugins create top level menus, this may get unruly - what if a user installed a dozen of plugins?
I think all plugins should reside under "Plugins" menu, as we currently have. If a plugin has a UI, then a plugin gets added to the list.
At least for now I don't think we should overcomplicate the implementation.
@RussKie It was primarily meant as an example of how to make extension points using MEF.
About extending main menu, I see your point. But on the other hand, for both plugins I have on GitHub, "Bundle Backuper" and "Solution Runner", it quite fits. Do you have some alternative suggestions?
Do you have some alternative suggestions?
Keep them under "Plugins" menu. We could allow each plugin to add buttons to a special plugin toolstrip, however a user must be able to toggle buttons (from settings).
Keep them under "Plugins" menu.
My terrible UX-me says it won't be so easy to use, but ok.
We could allow each plugin to add buttons to a special plugin toolstrip, however a user must be able to toggle buttons (from settings).
Settings for menu will be really cool.
That's how many other applications deal with plugins - Notepad++ or VS2019 to name a few
On Thu, 6 Jun 2019 at 16:22, Marek Fišera notifications@github.com wrote:
Keep them under "Plugins" menu.
My terrible UX-me says it won't be so easy to use, but ok.
We could allow each plugin to add buttons to a special plugin toolstrip, however a user must be able to toggle buttons (from settings).
Settings for menu will be really cool.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/gitextensions/gitextensions.extensibility/issues/6?email_source=notifications&email_token=ABBTEXTXWTEYRAHDVSKMAUDPZCULHA5CNFSM4HSSSM52YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODXB3JTA#issuecomment-499365068, or mute the thread https://github.com/notifications/unsubscribe-auth/ABBTEXSFKCKZK6F56OMA3A3PZCULHANCNFSM4HSSSM5Q .
We could do it here https://github.com/gitextensions/gitextensions/pull/8574
We could do it here gitextensions/gitextensions#8574
I'm not sure yet. Do you already have something specific in mind?
I'm not sure yet. Do you already have something specific in mind?
Please see the changes. There are also thoughts to implement all dependencies in one method.
public class GitUIEventArgs : CancelEventArgs
{
public GitUIEventArgs(IWin32Window ownerForm, IGitUICommands gitUICommands)
: base(cancel: false)
{
OwnerForm = ownerForm;
GitUICommands = gitUICommands;
}
public IGitUICommands GitUICommands { get; }
public IWin32Window OwnerForm { get; }
public IGitModule GitModule => GitUICommands.GitModule;
}
I don't see what it is for. IGitUICommands really needed only . Owner form is always active form. Isn't that so?
public bool Execute(GitUIEventArgs args) => public bool Execute()
public interface IGitUICommands
{
event EventHandler<GitUIPostActionEventArgs> PostCommit;
event EventHandler<GitUIEventArgs> PostRepositoryChanged;
event EventHandler<GitUIPostActionEventArgs> PostSettings;
event EventHandler<GitUIPostActionEventArgs> PostUpdateSubmodules;
event EventHandler<GitUIEventArgs> PostBrowseInitialize;
event EventHandler<GitUIEventArgs> PostRegisterPlugin;
event EventHandler<GitUIEventArgs> PreCommit;
We can use the interface as in the case of subscribing to the registration event.
public sealed class SomePlugin: IPostCommitHandler
{
public void OnPostCommit()
{
}
}
I want to start a discussion about new plugin entry points, to see which ones are of common interest and feasible.
Currently the entry points for plugins are:
Execute()
: Runs when a plugin's name in thePlugins
menu is clicked. This usually shows a dialog for further interactions.Register()
: Runs every time when a repo is loaded.Unregister()
: Runs when a repo is unloaded, either by switching to another repo or by closing GE.These work well for the existing plugins, but IMHO can be a limitation for new ones. Thus, some ideas for further, optional entry points:
Plugins > plugin_name
, to run different actions without the need for an own dialog.Plugins
menu there as well, but passing an additional argument to the plugin to distinguish whether the call comes from the main form or from the dashboard.All of these should be optional. Each plugin should declare which ones (if any) it implements. This way, backwards compatibility is ensured and the existing plugins continue to work as before.