rewrite simplelist to use a table (thus datatable-ready) instead of <ul>
[unfold.git] / engine / plugin.py
index f3fae50..99a3ff8 100644 (file)
@@ -6,6 +6,7 @@ import json
 
 from django.template.loader import render_to_string
 
+from engine.pluginset import PluginSet
 from engine.prelude import Prelude
 
 #################### 
@@ -15,7 +16,14 @@ from engine.prelude import Prelude
 # . True : to debug all plugin
 
 DEBUG= False
-DEBUG= [ 'SimpleList' ]
+#DEBUG= [ 'SliceList' ]
+
+# decorator to deflect calls on Plugin to its PluginSet
+def to_prelude (method):
+    def actual (self, *args, **kwds):
+        prelude_method=Prelude.__dict__[method.__name__]
+        return prelude_method(self.pluginset.prelude,*args, **kwds)
+    return actual
 
 class Plugin:
 
@@ -31,6 +39,7 @@ class Plugin:
     ########## 
     # Constructor
     #### mandatory
+    # . pluginset: the context of the request being served
     # . title: is used visually for displaying the widget
     #### optional
     # . togglable: whether it can be turned on and off (like PleKitToggle)
@@ -46,12 +55,14 @@ class Plugin:
     # p=Plugin(foo='bar')
     # which will result in 'foo' being accessible to the template engine
     # 
-    def __init__ (self, title, domid=None,
+    def __init__ (self, pluginset, title, domid=None,
                   visible=True, togglable=True, toggled=True, **settings):
+        self.pluginset = pluginset
         self.title=title
         if not domid: domid=Plugin.newdomid()
         self.domid=domid
-        self.classname=self._classname()
+        self.classname=self._py_classname()
+        self.plugin_classname=self._js_classname()
         self.visible=visible
         self.togglable=togglable
         self.toggled=toggled
@@ -64,11 +75,17 @@ class Plugin:
             print "%s init dbg .... BEG"%self.classname
             for (k,v) in self.__dict__.items(): print "dbg %s:%s"%(k,v)
             print "%s init dbg .... END"%self.classname
+        # do this only once the structure is fine
+        self.pluginset.record_plugin(self)
 
-    def _classname (self): 
+    def _py_classname (self): 
         try:    return self.__class__.__name__
         except: return 'Plugin'
 
+    def _js_classname (self): 
+        try:    return self.plugin_classname ()
+        except: return self._py_classname()
+
     ##########
     def need_debug (self):
         if not DEBUG:           return False
@@ -95,16 +112,18 @@ class Plugin:
     # NOTE this plugin_uuid thing might occur in js files from joomla/js, ** do not rename **
     def settings_json (self):
         result = "{"
-        result += "plugin_uuid:%s,"%self.domid
         result += ",".join([ self.setting_json(setting) for setting in self.json_settings_list() ])
         result += "}"
         return result
 
+    # as a first approximation, only plugins that are associated with a query
+    # need to be prepared for js - others just get displayed and that's it
+    def is_asynchroneous (self):
+        return 'query' in self.__dict__
+    
     # returns the html code for that plugin
     # in essence, wraps the results of self.render_content ()
     def render (self, request):
-        # initialize prelude placeholder if needed
-        self._init_prelude (request)
         # call render_content
         plugin_content = self.render_content (request)
         # shove this into plugin.html
@@ -113,10 +132,12 @@ class Plugin:
         env.update(self.__dict__)
         result = render_to_string ('plugin.html',env)
 
-        env ['settings_json' ] = self.settings_json()
-        # compute plugin-specific initialization
-        js_init = render_to_string ( 'plugin-setenv.js', env )
-        self.add_js_chunks (request, js_init)
+        # export this only for relevant plugins
+        if self.is_asynchroneous():
+            env ['settings_json' ] = self.settings_json()
+            # compute plugin-specific initialization
+            js_init = render_to_string ( 'plugin-setenv.js', env )
+            self.add_js_chunks (js_init)
         
         # interpret the result of requirements ()
         self.handle_requirements (request)
@@ -142,31 +163,6 @@ class Plugin:
             print "%s.render_content: END --------------------"%self.classname
         return result
 
-    #################### requirements/prelude management
-    def _init_prelude (self, request):
-        if not hasattr (request, 'plugin_prelude'): 
-            # include css/plugins.css
-            request.plugin_prelude=Prelude(css_files='css/plugin.css')
-
-    def inspect_request (self, request, message):
-        has=hasattr(request,'plugin_prelude')
-        get=getattr(request,'plugin_prelude','none-defined')
-        print "INSPECT (%s), hasattr %s, getattr %s"%(message,has,get)
-
-    # can be used directly in render_content()
-    def add_js_files (self, request, files):
-        self._init_prelude (request)
-        request.plugin_prelude.add_js_files (files)
-    def add_css_files (self, request, files):
-        self._init_prelude (request)
-        request.plugin_prelude.add_css_files (files)
-    def add_js_chunks (self, request, chunks):
-        self._init_prelude (request)
-        request.plugin_prelude.add_js_chunks (chunks)
-    def add_css_chunks (self, request, chunks):
-        self._init_prelude (request)
-        request.plugin_prelude.add_css_chunks (chunks)
-
     # or from the result of self.requirements()
     def handle_requirements (self, request):
         try:
@@ -175,8 +171,8 @@ class Plugin:
                 if self.need_debug():
                     print "%s: handling requirement %s"%(self.classname,v)
                 method_name='add_'+k
-                method=Plugin.__dict__[method_name]
-                method(self,request,v)
+                method=PluginSet.__dict__[method_name]
+                method(self.pluginset,v)
         except AttributeError: 
             # most likely the object does not have that method defined, which is fine
             pass
@@ -185,6 +181,17 @@ class Plugin:
             traceback.print_exc()
             pass
 
+    #################### requirements/prelude management
+    # just forward to self.pluginset - see decorator above
+    @to_prelude
+    def add_js_files (self):pass
+    @to_prelude
+    def add_css_files (self):pass
+    @to_prelude
+    def add_js_chunks (self):pass
+    @to_prelude
+    def add_css_chunks (self):pass
+
     ######################################## abstract interface
     # your plugin is expected to implement either 
     # (*) def render_content(self, request) -> html fragment
@@ -223,3 +230,5 @@ class Plugin:
     # also 'query_uuid' gets replaced with query.uuid
     def json_settings_list (self): return ['json_settings_list-must-be-redefined']
 
+    # might also define this one; see e.g. slicelist.py that piggybacks simplelist js code
+    # def plugin_classname (self):