Info: Extending ToDoList using the exist.io framework

154 views
Skip to first unread message

.dan.g.

unread,
Jan 24, 2017, 12:18:37 AM1/24/17
to ToDoList (AbstractSpoon) Support

Aidan Ryan

unread,
Jan 24, 2017, 6:20:29 PM1/24/17
to ToDoList (AbstractSpoon) Support
Hi Dan, thanks for posting this!

I was hoping to develop this as a plugin to ToDoList itself. It looks like there is some work toward a C# plugin API. Are there any examples I could work from?

-Aidan

On Monday, January 23, 2017 at 9:18:37 PM UTC-8, .dan.g. wrote:

.dan.g.

unread,
Jan 24, 2017, 8:42:00 PM1/24/17
to ToDoList (AbstractSpoon) Support
>> Are there any examples I could work from?

Hi Aidan

So basically your extension just wants to be notified of tasks being completed?

If so, the closest thing would be a UIExtension but it has it's shortcomings as far as you are concerned:

1. It only starts getting notified once the user has switched to it. This is so that extensions the user is not interested in do not take up any cpu or affect performance.
2. All plugins require a C++/CLI 'bridge' dll, but you can easily clone the example one and rename everything using VS or Notepad++, which is what I do!.

ps. I am open to the idea of adding a new plugin type that does not require activation or optionally even have a UI so if you have time it's a discussion I am interested in having.

Aidan Ryan

unread,
Jan 26, 2017, 4:26:01 PM1/26/17
to ToDoList (AbstractSpoon) Support
Thanks for the pointer. I don't think it would be useful if it has to have an active UI to function. Best would be to subscribe to an event published by ToDoList indicating that a task's state changed. If you're interested in supplying this kind of interface I would happily work with you on testing it.

Tangential, why is it necessary to create the shim C++/CLI DLL? Is not not possible for a C# class to implement the IUIExtension COM interface directly?
Message has been deleted

.dan.g.

unread,
Jan 26, 2017, 7:37:19 PM1/26/17
to ToDoList (AbstractSpoon) Support
>> Best would be to subscribe to an event published by ToDoList

Unfortunately that's not exactly the model I have used. Instead TDL calls 'UpdateTasks' on the interface implemented by each plugin.

>> Is not not possible for a C# class to implement the IUIExtension COM interface directly?

Not that I'm aware of. It's a C++ pure virtual interface which is very different from a C# interface.

Aidan Ryan

unread,
Jan 30, 2017, 9:37:27 AM1/30/17
to ToDoList (AbstractSpoon) Support

>> Best would be to subscribe to an event published by ToDoList

Unfortunately that's not exactly the model I have used. Instead TDL calls 'UpdateTasks' on the interface implemented by each plugin.

Understood, that would work just as well. I think you explained this already, but just to clarify -- with the IUIExtension.UpdateTasks model, each plugin must have a user interface, correct?  If my plugin's UI is not active and someone changes a task, when would its UpdateTasks be called?

>> Is not not possible for a C# class to implement the IUIExtension COM interface directly?

Not that I'm aware of. It's a C++ pure virtual interface which is very different from a C# interface.

I see - I took a look at the source. I guess if IUIExtension was a COM interface with a TLB, it could just be imported into a .NET assembly and you wouldn't need the C++/CLI shim. I think you could also create a generic C++/CLI shim that could instantiate an arbitrary extension from a .NET assembly using reflection (late binding) instead directly referencing and coupling to a specific C# assembly/extension. I may take a hack at creating that. 

.dan.g.

unread,
Jan 31, 2017, 9:11:01 PM1/31/17
to ToDoList (AbstractSpoon) Support
>> If my plugin's UI is not active and someone changes a task, when would its UpdateTasks be called?

It wouldn't be, therein lies the problem which will require a new interface type for UI-less plugins.


>> I may take a hack at creating that. 

That would be awesome!

Aidan Ryan

unread,
Feb 27, 2017, 5:04:42 PM2/27/17
to abstractspoon-t...@googlegroups.com

That would be awesome!

 
I took a first stab at this:

     
 
Assembly^ cSharpAssembly = Assembly::LoadFrom("StatsUIExtensionCore.dll");

int count = 0;
array
<Type^>^ types = cSharpAssembly->GetTypes();
System::Collections::IEnumerator^ typeEnumerator = types->GetEnumerator();

while (typeEnumerator->MoveNext())
{
 
Type^ type = dynamic_cast<Type^>(typeEnumerator->Current);
  if (Abstractspoon::Tdl::PluginHelpers::IUIExtension::typeid->IsAssignableFrom(type))
 
{
   
Object^ pluginObject = Activator::CreateInstance(type);
    m_wnd
= dynamic_cast<Abstractspoon::Tdl::PluginHelpers::IUIExtension^>(pluginObject);
    m_source
->RootVisual = dynamic_cast<System::Windows::Media::Visual^>(pluginObject);

   
return true;
 
}
}


This code works to instantiate an arbitrary IUIExtension from a given .NET assembly .DLL file. You could use this in a single generic "bridge" DLL that the core plugin discovery module would re-instantiate and execute for each .DLL, with appropriate exception handling in the case of .DLL files that aren't .NET assemblies.

.dan.g.

unread,
Feb 27, 2017, 8:06:51 PM2/27/17
to ToDoList (AbstractSpoon) Support
Thx a lot Aidan, I will have a think about how this could be applied to 7.2.
Reply all
Reply to author
Forward
0 new messages