X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=unfold%2Fplugin.py;h=229f196c3bf6a2dd5d889f8c99c8512114dce3d9;hb=350a118a4f8e3329f39fe7f245cb27388a3756f0;hp=1b7105204741f165a89cccf44c848755160848da;hpb=b709866ba93d98c32127ff4deae5b783e271e5b3;p=myslice.git diff --git a/unfold/plugin.py b/unfold/plugin.py index 1b710520..229f196c 100644 --- a/unfold/plugin.py +++ b/unfold/plugin.py @@ -16,11 +16,14 @@ from unfold.prelude import Prelude # . True : to debug all plugin DEBUG= False -DEBUG= [ 'QuickFilter' ] +#DEBUG= [ 'SimpleList' ] +#DEBUG=True # decorator to deflect calls on Plugin to its Prelude through self.page.prelude def to_prelude (method): def actual (self, *args, **kwds): + if not self.page: # jordan + return None prelude_method=Prelude.__dict__[method.__name__] return prelude_method(self.page.prelude,*args, **kwds) return actual @@ -31,10 +34,14 @@ class Plugin: # we just need this to be unique in a page domid=0 - @staticmethod - def newdomid(): + # when a domid is not set by the caller, we name plugins after their respective class as well, + # so as to limit name clashes between different views + # this has to see with the UI storing the last-seen status of plugins based on their id + # put it more bluntly it is recommended that a domid should be set + # and maybe xxx we should just enforce that... + def newdomid(self): Plugin.domid += 1 - return "plugin-%d"%Plugin.domid + return "plugin-%s-%d"%(self.__class__.__name__.lower(),Plugin.domid) ########## # Constructor @@ -42,10 +49,26 @@ class Plugin: # . page: 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) - # . toggled: if togglable, what's the initial status # . visible: if not set the plugin does not show up at all # (not quite sure what this was for) + # . togglable: whether it can be turned on and off by clicking on the title (like PleKitToggle) + # . toggled: whether the plugin should startup open/shown or closed/hidden + # possible values are + # .. True : start up open/hidden + # .. False : start up closed/shown + # .. 'persistent' : start up as it was the last time that browser showed it (based on 'domid') + # NOTE that it is required for you to set a domid if you want to use persistent mode + # since domid is the key for storing that data in the browser storage space + # .. None : if not passed to __init__ at all, then the default_toggled() method is called + # .. : anything else, defaults to True + # . outline_complete: whether the overall plugin (body + toggle buttons/title) needs to receive + # a border and extra space + # . outline_body : same but for the plugin body only + # for these 2 outline_ flags, possible values mimick the above behaviour, i.e.: + # .. True: : outline is on + # .. False: : outline is off + # .. None: : calls default_outline_complete() on the plugin object + # #### internal data # . domid: created internally, but can be set at creation time if needed # useful for hand-made css, or for selecting an active plugin in a composite @@ -55,18 +78,28 @@ class Plugin: # p=Plugin(foo='bar') # which will result in 'foo' being accessible to the template engine # - def __init__ (self, page, title, domid=None, - visible=True, togglable=True, toggled=True, **settings): + def __init__ (self, page, title=None, domid=None, + visible=True, togglable=None, toggled=None, + outline_complete=None, outline_body=None, + **settings): self.page = page - self.title=title # callers can provide their domid for css'ing - if not domid: domid=Plugin.newdomid() + if not domid: domid=self.newdomid() self.domid=domid + # title is shown when togglable + #if not title: title="Plugin title for %s"%domid + self.title=title self.classname=self._py_classname() self.plugin_classname=self._js_classname() self.visible=visible - self.togglable=togglable - self.toggled=toggled + if togglable is None: self.togglable=self.default_togglable() + else: self.togglable=togglable + if toggled is None: self.toggled=self.default_toggled() + else: self.toggled=toggled + if outline_complete is None: self.outline_complete=self.default_outline_complete() + else: self.outline_complete=outline_complete + if outline_body is None: self.outline_body=self.default_outline_body() + else: self.outline_body=outline_body # what comes from subclasses for (k,v) in settings.iteritems(): setattr(self,k,v) @@ -77,7 +110,11 @@ class Plugin: 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.page.record_plugin(self) + if self.page: # I assume we can have a None page (Jordan) + self.page.record_plugin(self) + + def __repr__ (self): + return "[%s]:%s"%(self.classname,self.domid) def _py_classname (self): try: return self.__class__.__name__ @@ -98,11 +135,11 @@ class Plugin: if setting=='plugin_uuid': value=self.domid elif setting=='query_uuid': - try: value=self.query.uuid + try: value=self.query.query_uuid except: return '%s:"undefined"'%setting else: value=getattr(self,setting,None) - if not value: value = "unknown-setting-%s"%setting + if value is None: value = "unknown-setting-%s"%setting # first try to use to_json method (json.dumps not working on class instances) try: value_json=value.to_json() except: value_json=json.dumps(value,separators=(',',':')) @@ -112,6 +149,9 @@ class Plugin: # and add plugin_uuid: domid in the mix # NOTE this plugin_uuid thing might occur in js files from joomla/js, ** do not rename ** def settings_json (self): + exposed_settings=self.json_settings_list() + if 'query' in exposed_settings: + print "WARNING, cannot expose 'query' directly in json_settings_list, query_uuid is enough" result = "{" result += ",".join([ self.setting_json(setting) for setting in self.json_settings_list() ]) result += "}" @@ -121,11 +161,8 @@ class Plugin: # need to be prepared for js - meaning their json settings get exposed to js # others just get displayed and that's it def export_json_settings (self): - return 'query' in self.__dict__ + return 'query_uuid' in self.json_settings_list() - def start_with_spin (self): - return self.export_json_settings() - # returns the html code for that plugin # in essence, wraps the results of self.render_content () def render (self, request): @@ -134,17 +171,32 @@ class Plugin: # shove this into plugin.html env = {} env ['plugin_content']= plugin_content - # need_spin is used in plugin.html - self.need_spin=self.start_with_spin() env.update(self.__dict__) + # translate high-level 'toggled' into 4 different booleans + self.need_toggle = False + if self.toggled=='persistent': + # start with everything turned off and let the js callback do its job + env.update({'persistent_toggle':True,'display_hide_button':False, + 'display_show_button':False,'display_body':False}) + elif self.toggled==False: + env.update({'persistent_toggle':False,'display_hide_button':False, + 'display_show_button':True,'display_body':False}) + else: + env.update({'persistent_toggle':False,'display_hide_button':True, + 'display_show_button':False,'display_body':True}) + if self.need_debug(): + print "rendering plugin.html with env keys %s"%env.keys() + for (k,v) in env.items(): + if "display" in k or "persistent" in k: print k,'->',v result = render_to_string ('plugin.html',env) # export this only for relevant plugins if self.export_json_settings(): 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) + js_init = render_to_string ( 'plugin-init.js', env ) + # make sure this happens first in js + self.add_js_init_chunks (js_init) # interpret the result of requirements () self.handle_requirements (request) @@ -157,7 +209,12 @@ class Plugin: def render_content (self, request): """Should return an HTML fragment""" template = self.template_file() - env=self.template_env(request) + # start with a fresh one + env={} + # add our own settings as defaults + env.update(self.__dict__) + # then the things explicitly defined in template_env() + env.update(self.template_env(request)) if not isinstance (env,dict): raise Exception, "%s.template_env returns wrong type"%self.classname result=render_to_string (template, env) @@ -196,6 +253,8 @@ class Plugin: @to_prelude def add_css_files (self):pass @to_prelude + def add_js_init_chunks (self):pass + @to_prelude def add_js_chunks (self):pass @to_prelude def add_css_chunks (self):pass @@ -214,6 +273,11 @@ class Plugin: def template_file (self): return "undefined_template" def template_env (self, request): return {} + def default_togglable (self): return False + def default_toggled (self): return 'persistent' + def default_outline_complete (self):return False + def default_outline_body(self): return False + # # tell the framework about requirements (for the document
) # # the notion of 'Media' in django provides for medium-dependant # # selection of css files @@ -235,7 +299,7 @@ class Plugin: # mandatory : define the fields that need to be exposed to json as part of # plugin initialization # mention 'domid' if you need plugin_uuid - # also 'query_uuid' gets replaced with query.uuid + # also 'query_uuid' gets replaced with query.query_uuid def json_settings_list (self): return ['json_settings_list-must-be-redefined'] # might also define these ones: @@ -245,6 +309,3 @@ class Plugin: # # whether we export the json settings to js # def export_json_settings (self) - # - # whether we show an initial spinner - # def start_with_spin (self)