Plugin oriented App Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2292
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania
Contact:

Post by evstevemd » Tue Jun 22, 2010 6:06 pm

I have some "conceptual" problem on how host and plugins exchange events
Edit:
Can that be via Interface? I have to check this on upCase example at home :wink:
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
[Ubuntu 19.04/Windows 10 Pro/MacOS 10.13 - GCC/MinGW/Clang, CodeLite IDE]

User avatar
xaviou
Super wx Problem Solver
Super wx Problem Solver
Posts: 429
Joined: Mon Aug 21, 2006 3:18 pm
Location: Annecy - France
Contact:

Post by xaviou » Tue Jun 22, 2010 8:49 pm

Hi to all !

I am actually working on such an application.
This application is a "ToDo list manager"
It consists of a basic application that manages tasks, sub-tasks, sub-sub-tasks, and so on.
It can be extended with plugins of 3 types:
- datas plugins, that extends tasks properties
- import/export plugins that allows, as their name suggests it, to import or export datas from/to other application like this
- tools plugins, that offers other capabilities to the application (for example, reports creation, auto-update).

The architecture is the following :
- The main app that creates the interface, and shows basics tasks properties
- A "hard linked" dynamic library that contains managers (PluginsManager, SettingsManager, DatasManager, and some usefull functions/classes that can be used by the app or the plugins)
- Differents plugins that are dynamically detected and loaded at runtime

The PluginsManager is the "core class" of the system : it keeps an "ArrayOfPlugins" that are loaded, so it can ask them to do something when needed.
In other cases, Plugins can acces the PluginsManager global object, and use it to send custom events to the app.

I don't know if it is the best way to do a plugins system, but it works perfectly.

If you need more infos on it, do not hesitate to ask for.

Regards

Xav'
My wxWidgets stuff web page : [email protected]'s wxStuff

User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2292
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania
Contact:

Post by evstevemd » Wed Jun 23, 2010 5:33 am

xaviou wrote:Hi to all !

I am actually working on such an application.
This application is a "ToDo list manager"
It consists of a basic application that manages tasks, sub-tasks, sub-sub-tasks, and so on.
It can be extended with plugins of 3 types:
- datas plugins, that extends tasks properties
- import/export plugins that allows, as their name suggests it, to import or export datas from/to other application like this
- tools plugins, that offers other capabilities to the application (for example, reports creation, auto-update).

The architecture is the following :
- The main app that creates the interface, and shows basics tasks properties
- A "hard linked" dynamic library that contains managers (PluginsManager, SettingsManager, DatasManager, and some usefull functions/classes that can be used by the app or the plugins)
- Differents plugins that are dynamically detected and loaded at runtime

The PluginsManager is the "core class" of the system : it keeps an "ArrayOfPlugins" that are loaded, so it can ask them to do something when needed.
In other cases, Plugins can acces the PluginsManager global object, and use it to send custom events to the app.

I don't know if it is the best way to do a plugins system, but it works perfectly.

If you need more infos on it, do not hesitate to ask for.

Regards

Xav'
I think I will need help on that, but I think one Plugin Manager is enough!
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
[Ubuntu 19.04/Windows 10 Pro/MacOS 10.13 - GCC/MinGW/Clang, CodeLite IDE]

jfouche
Super wx Problem Solver
Super wx Problem Solver
Posts: 442
Joined: Tue May 06, 2008 4:52 pm
Location: France

Post by jfouche » Wed Jun 23, 2010 2:07 pm

A solution :

1 - A PluginEvtHandler where you post all yours messages
2 - All plugin subscribe to the plugins events with the PluginEvtHandler class.

Code: Select all

// This sould be a singleton class, to be sure it's unique
class PluginEvtHandler : public wxEvtHandler
{
};

class IPlugin : wxEvtHandler
{
public:
   IPlugin(PluginEvtHandler* handler)
   {
      handler->Connect(My_Evt, ...);
   }
};
To send an event :

Code: Select all

// thePluginEvtHandler is the only instance of PluginEvtHandler 

thePluginEvtHandler->AddPendingEvent( event );
If you want I can provide you a full sample (in a few days, i'm a little bit busy today).
Jérémie

User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2292
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania
Contact:

Post by evstevemd » Wed Jun 23, 2010 3:55 pm

jfouche wrote:A solution :

1 - A PluginEvtHandler where you post all yours messages
2 - All plugin subscribe to the plugins events with the PluginEvtHandler class.

Code: Select all

// This sould be a singleton class, to be sure it's unique
class PluginEvtHandler : public wxEvtHandler
{
};

class IPlugin : wxEvtHandler
{
public:
   IPlugin(PluginEvtHandler* handler)
   {
      handler->Connect(My_Evt, ...);
   }
};
To send an event :

Code: Select all

// thePluginEvtHandler is the only instance of PluginEvtHandler 

thePluginEvtHandler->AddPendingEvent( event );
If you want I can provide you a full sample (in a few days, i'm a little bit busy today).
Thanks and I will appreciate that sample any time :)
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
[Ubuntu 19.04/Windows 10 Pro/MacOS 10.13 - GCC/MinGW/Clang, CodeLite IDE]

User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2292
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania
Contact:

Post by evstevemd » Thu Jul 01, 2010 6:12 am

I have wrote simple buggy plugin in C++ (no wxWidgets for now) to test my understanding of the concept. Please download run and tell me where a I should correct what ;)

It is just to get the concept sunk into my head and it have CodeLite project.

After I pass this one I will go back to wxThing

Thanks
Attachments
PluginX.zip
(448.89 KiB) Downloaded 124 times
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
[Ubuntu 19.04/Windows 10 Pro/MacOS 10.13 - GCC/MinGW/Clang, CodeLite IDE]

User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2292
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania
Contact:

Post by evstevemd » Fri Jul 02, 2010 3:52 pm

Now that I have grasped the concept somehow, I'm swinging to wxWidgets. In my DemoApp I want to expose minimal app, that is wxMenus, wxNotebook, and status bar.
So How do I make abstract class? Should I make multiple inheritance like one below? If no which approach do you suggest? If yes what are pros and cons?

Thanks,

Here is what I think of IPlugin.h

Code: Select all

#include <wx/wx.h>
#include <wx/aui/auibook.h>

class IPlugin: public wxMenu, wxAuiNotebook, wxStatusBarGeneric{
public:
	virtual void addPluginMenuItem(wxMenu* menu) = 0;
	virtual void addMenuwxMenu* menu) = 0;
	virtual wxString getStatusBarText()=0;
	virtual wxString supportedHostVersion()=0;
	
	
};
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
[Ubuntu 19.04/Windows 10 Pro/MacOS 10.13 - GCC/MinGW/Clang, CodeLite IDE]

jfouche
Super wx Problem Solver
Super wx Problem Solver
Posts: 442
Joined: Tue May 06, 2008 4:52 pm
Location: France

Post by jfouche » Fri Jul 02, 2010 4:09 pm

OUps, that's not the good way. Wait until tomorow, i'll have more time for you...
Jérémie

User avatar
xaviou
Super wx Problem Solver
Super wx Problem Solver
Posts: 429
Joined: Mon Aug 21, 2006 3:18 pm
Location: Annecy - France
Contact:

Post by xaviou » Fri Jul 02, 2010 4:33 pm

Hi
jfouche wrote:OUps, that's not the good way.
I agree with that...

I think you should only derive you plugins from wxEvtHandler :

Here is what I've done to create the base class of plugins that can have differents types :

Code: Select all

#include <wx/wx.h>

enum Pugin_Type
{
	PT_UNKNOWN=0,
	PT_DATAS,
	PT_IMPEXP,
	PT_TOOL
};

class PluginBase : public wxEvtHandler
{
	public:
		PluginBase(Pugin_Type type) { m_Type=type; }
		Pugin_Type GetPluginType() { return m_Type; }
		virtual wxString GetPluginName()=0;
	private:
		Pugin_Type m_Type;
};
Then, for each plugin type, I have something like that :
The first type of plugins have to create a wxPanel to extent the main interface :

Code: Select all

class DataPlugin : public PluginBase
{
	public:
		DataPlugin() : PluginBase(PT_DATAS) { }
		virtual wxPanel* CreatePluginPanel(wxWindow* parent)=0;
		//...
};
And, for example, the "Tool" plugin type, that only have a function to be executed from a menu :

Code: Select all

class ToolPlugin : public PluginBase
{
	public:
		ToolPlugin() : PluginBase(PT_TOOL) { }
		virtual bool ExecuteTool(wxXmlNode* datas)=0;
};
Hope it will help you understand the concept...

Regards

Xav'
My wxWidgets stuff web page : [email protected]'s wxStuff

User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2292
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania
Contact:

Post by evstevemd » Fri Jul 02, 2010 4:38 pm

jfouche wrote:OUps, that's not the good way. Wait until tomorow, i'll have more time for you...
Thanks Jeremie,
I will be waiting :P
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
[Ubuntu 19.04/Windows 10 Pro/MacOS 10.13 - GCC/MinGW/Clang, CodeLite IDE]

User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2292
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania
Contact:

Post by evstevemd » Fri Jul 02, 2010 4:41 pm

xaviou wrote:Hi
jfouche wrote:OUps, that's not the good way.
I agree with that...

I think you should only derive you plugins from wxEvtHandler :

Here is what I've done to create the base class of plugins that can have differents types :

Code: Select all

#include <wx/wx.h>

enum Pugin_Type
{
	PT_UNKNOWN=0,
	PT_DATAS,
	PT_IMPEXP,
	PT_TOOL
};

class PluginBase : public wxEvtHandler
{
	public:
		PluginBase(Pugin_Type type) { m_Type=type; }
		Pugin_Type GetPluginType() { return m_Type; }
		virtual wxString GetPluginName()=0;
	private:
		Pugin_Type m_Type;
};
Then, for each plugin type, I have something like that :
The first type of plugins have to create a wxPanel to extent the main interface :

Code: Select all

class DataPlugin : public PluginBase
{
	public:
		DataPlugin() : PluginBase(PT_DATAS) { }
		virtual wxPanel* CreatePluginPanel(wxWindow* parent)=0;
		//...
};
And, for example, the "Tool" plugin type, that only have a function to be executed from a menu :

Code: Select all

class ToolPlugin : public PluginBase
{
	public:
		ToolPlugin() : PluginBase(PT_TOOL) { }
		virtual bool ExecuteTool(wxXmlNode* datas)=0;
};
Hope it will help you understand the concept...

Regards

Xav'
thanks Xav,
my head is tired now after some time of reading and working. I will read it tomorrow
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
[Ubuntu 19.04/Windows 10 Pro/MacOS 10.13 - GCC/MinGW/Clang, CodeLite IDE]

User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2292
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania
Contact:

Post by evstevemd » Fri Jul 02, 2010 4:44 pm

jfouche wrote:OUps, that's not the good way. Wait until tomorow, i'll have more time for you...
why is it bad?
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
[Ubuntu 19.04/Windows 10 Pro/MacOS 10.13 - GCC/MinGW/Clang, CodeLite IDE]

User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2292
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania
Contact:

Post by evstevemd » Sat Jul 03, 2010 4:56 pm

Code: Select all

#include <wx/wx.h>

enum Pugin_Type
{
	PT_UNKNOWN=0,
	PT_DATAS,
	PT_IMPEXP,
	PT_TOOL
};

class PluginBase : public wxEvtHandler
{
	public:
		PluginBase(Pugin_Type type) { m_Type=type; }
		Pugin_Type GetPluginType() { return m_Type; }
		virtual wxString GetPluginName()=0;
	private:
		Pugin_Type m_Type;
};
Then, for each plugin type, I have something like that :
The first type of plugins have to create a wxPanel to extent the main interface :

Code: Select all

class DataPlugin : public PluginBase
{
	public:
		DataPlugin() : PluginBase(PT_DATAS) { }
		virtual wxPanel* CreatePluginPanel(wxAUINotebook* parent)=0;
		
};
so there I have My Notebook plugin, but then I have a question. How can I bind events to my panel before I attach it to AUINotebook? Do i do normal event binding or because it is a plugin there is special way?
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
[Ubuntu 19.04/Windows 10 Pro/MacOS 10.13 - GCC/MinGW/Clang, CodeLite IDE]

User avatar
xaviou
Super wx Problem Solver
Super wx Problem Solver
Posts: 429
Joined: Mon Aug 21, 2006 3:18 pm
Location: Annecy - France
Contact:

Post by xaviou » Sat Jul 03, 2010 10:30 pm

evstevemd wrote:so there I have My Notebook plugin, but then I have a question. How can I bind events to my panel before I attach it to AUINotebook? Do i do normal event binding or because it is a plugin there is special way?
You can absolutely do "normal" event binding, even by a classic event table, or dynamically (my prefered) with the "Connect" method

And events can also be catched by the main application.
For example :

- you create a button on your panel, and you give this button the id "wxID_EXIT"
- your main application has an entry menu with the same id, connected to a method witch allow closing the frame
- if the clic on the button isn't connected to a plugin's method, it will be catched by the frame's one (and I think it will be catched by the frame before it should be catched by the plugin).

Hope I am clear enough : if not, don't hesitate to ask for more details.

Regards

Xav'
My wxWidgets stuff web page : [email protected]'s wxStuff

User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2292
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania
Contact:

Post by evstevemd » Mon Jul 12, 2010 8:35 am

I hope now I'm about to make it. And I thanks you guys who are boosting me a lot :)

However I have another Question on How do I code the Manager and Load the Plugins. I have been thinking and I feel as if I hit a wall, nothing just moves. Would you guys shed light on that?
Thanks!
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
[Ubuntu 19.04/Windows 10 Pro/MacOS 10.13 - GCC/MinGW/Clang, CodeLite IDE]

Post Reply