Page 2 of 5

Posted: Tue Jun 22, 2010 6:06 pm
by evstevemd
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:

Posted: Tue Jun 22, 2010 8:49 pm
by xaviou
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'

Posted: Wed Jun 23, 2010 5:33 am
by evstevemd
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!

Posted: Wed Jun 23, 2010 2:07 pm
by jfouche
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).

Posted: Wed Jun 23, 2010 3:55 pm
by evstevemd
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 :)

Posted: Thu Jul 01, 2010 6:12 am
by evstevemd
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

Posted: Fri Jul 02, 2010 3:52 pm
by evstevemd
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;
	
	
};

Posted: Fri Jul 02, 2010 4:09 pm
by jfouche
OUps, that's not the good way. Wait until tomorow, i'll have more time for you...

Posted: Fri Jul 02, 2010 4:33 pm
by xaviou
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'

Posted: Fri Jul 02, 2010 4:38 pm
by evstevemd
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

Posted: Fri Jul 02, 2010 4:41 pm
by evstevemd
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

Posted: Fri Jul 02, 2010 4:44 pm
by evstevemd
jfouche wrote:OUps, that's not the good way. Wait until tomorow, i'll have more time for you...
why is it bad?

Posted: Sat Jul 03, 2010 4:56 pm
by evstevemd

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?

Posted: Sat Jul 03, 2010 10:30 pm
by xaviou
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'

Posted: Mon Jul 12, 2010 8:35 am
by evstevemd
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!