OK the demo should work fine--it stops working when I remove the onxyzzyClick() functions and use a single onClick() while forming the buttons with
Button(button_name, self) and no other changes. Suddenly the button-objects will not pass to MakeTree()'s __init__ and I *get this (void 0) is not a function. Michael Moore * On Wed, Sep 12, 2012 at 11:11 AM, Michael Moore <[email protected] > wrote: > I think I found the problem. No, I wasn't in Windows. I spend very > little time in that state of depression. > > OK we have a tree. The root is always the user and the leaf is always the > action script for a job to be submitted to a grid. The action scripts are > named and the names are unique... Usr names are also unique. > > A user can have projects which is a container, similar to a folder. The > projects are unique by name within the user namespace, but also have > associated with them an id which is universally unique. > Within a project are analysis runs. Each analysis run is named uniquely > in the project namespace. Analysis Runs contain a series of workflows. > The workflows are bash scripts which may call several programs and which > have instantiated parameters within the analysis run. > > Inside that environment, we have functionality that goes to buttons > > Add Project--valid ONLY when the user is selected. > > Rename Project > Delete Project > Duplicate Analysis Run (from another project) > Those three are valid only when a project is selected. > > Then when an Analysis Run is selected > Add Workflow > Rename Analysis Run > Delete Analysis Run > Go To Run Menu > > And finally: when a workflow is selected... > Insert Workflow Above Current Selection > Delete Workflow > > The question arises, will this be enough in terms of categorical > containers (two levels). I am assuming it is not going to be adequate > moving forward (remember someone's famous pronouncement that any program > can run in 640K? > > So I want to build the page(s) to be data-driven. With a csv of the > layers and their names, and button functionality--the controller can > produce JSON responses that provide a list of buttons for each layer and > the layer to which they belong, and also a flattened list of nodes for the > user tree. I am putting sample data in the main() of this to demonstrate > how it might work. > > I have solved half the problem... When the selection occurs within the > tree, the buttons appropriate appear. The other part, using a dispatcher > with onClick() doesn't seem quite so hopeful. Of course since there are > several points where some regeneration is needed to add another layer of > nodes, we could look at metaprogramming to autogenerate this page and > submit it to pyjsbuild. But I cannot aford toupees for all the Java > programmers around here, and I am sure the word Metaprogramming would > precipitate a session of breast-beating and hair tearing. I left out the > other page elements as they are not germane to the discussion... The > default html template is ok, and the css stylesheet .... Well the > stylesheet needs at least the line > > .gwt-TreeItem-selected {background-color: #5ff1f3;} > > > #!/opt/pylib/pypy-1.9/bin/pypy #attach to whatever python you are using > from pyjamas.ui.SimplePanel import SimplePanel > from pyjamas.ui.ScrollPanel import ScrollPanel > from pyjamas.ui.Tree import Tree > from pyjamas.ui.TreeItem import TreeItem > from pyjamas import DOM > from pyjamas import Window > from pyjamas.ui.RootPanel import RootPanel > from pyjamas.ui.HTML import HTML > from pyjamas.HTTPRequest import HTTPRequest > import pyjd # dummy in pyjs > from pyjamas.ui.TextArea import TextArea > from pyjamas.ui.Label import Label > from pyjamas.ui.Button import Button > from pyjamas.ui.VerticalPanel import VerticalPanel > from pyjamas.ui.HorizontalPanel import HorizontalPanel > from pyjamas.ui.ListBox import ListBox > from pyjamas.JSONService import JSONProxy > from pyjamas.ui.TabPanel import TabPanel > from pyjamas.ui.TextBox import TextBox > from pyjamas.ui.PasswordTextBox import PasswordTextBox > from pyjamas.ui.NamedFrame import NamedFrame > from pyjamas.ui.Frame import Frame > from pyjamas.ui.Hidden import Hidden > from pyjamas.ui.FormPanel import FormPanel > > # some of those imports are unnecessary fro the demo purpose, but rather > represent wht I am using in the finished product. > > class BeyondDesignLimitError(Excepton): > pass > > class ButtonPanel(VerticalPanel): > def __init__(self, button_list, test=False): > VerticalPanel.__init__(self) > self.button_list=button_list > self.buttons = [] > self.button_dict={0:[],1:[],2:[],3:[],4:[],5:[],6:[]} > > > for (button_name, button_level) in self.button_list: > self.buttons.append(Button(button_name,getattr(self,"on%sClick" > %button_name.replace(" ","")))) > self.buttons[-1].setVisible(test) > self.buttons[-1].setWidth('180px') > self.button_dict[button_level].append(self.buttons[-1]) > self.add(self.buttons[-1]) > > def onAddProjectClick(): > Window.alert("You Clicked Add Project") > # This seems to work, with the specific button functions ID'd > # But try onClick() with a dispatcher and we go sideways... > > def onRenameProjectClick(): > Window.alert("You Clicked Rename Project") > > def onDeleteProjectClick(): > Window.alert("You Clicked remove Project") > > def onAddAnalysisRunClick(): > Window.alert("You Clicked Add Analysis Run") > > def onDuplicateAnalysisRunClick(): > Window.alert("you clicked to Duplicate Analysis Run from some" > " other project") > > def onDeleteAnalysisRunClick(): > Window.alert("You Clicked remove Analysis Run") > > def onRenameAnalysisRunClick(): > Window.alert("You Clicked rename Analysis Run") > > def onAddWorkflowClick(): > Window.alert("You Clicked Add Workflow") > > def onGoToRunMenuClick(): > Window.alert("You Clicked Go To Run Menu") > > def onInsertWorkflowAboveCurrentSelectionClick(): > Window.alert("You Clicked for inserting a workflow") > > def onDeleteWorkflowClick(): > Window.alert("You Clicked to remove a workflow from the AR" > " list") > > class MainTree(ScrollPanel): > > def __init__(self, arc,b): > self.buttons=b.buttons #Note that the use of a local instance > variable is necessary > self.button_dict=b.button_dict # Same caution as above. > ScrollPanel.__init__(self, widget) > self.setHeight(450) > self.setWidth(280) > self.node_dict = {} > tree = Tree() > tree.addTreeListener(self) > levels = [[] for i in range(MAXLEVELS)] > while arc: > obj, (valuex, level,), = arc.pop(0) > if level == 0: > s1=self.createItem(obj, value=(valuex, level)) > s1.setState(True, fireEvents=False) > levels[0].append(s1) > continue > if level>0 and level<MAXLEVELS+1: > levels[level].append(levels[level-1][-1].addItem( > self.createItem(obj, value = (valuex,level)))) > levels[level][-1].setState(False, fireEvents=False) > continue > else: > raise BeyondDesignLimitError > tree.addItem(s1) > tree.ensureSelectedItemVisible() > self.add(tree) > > > def createItem(self, label, value=None): > item = TreeItem(label) > DOM.setStyleAttribute(item.getElement(), "cursor", > "pointer","images") > if value is not None: > item.setUserObject(value) > return item > > > def onTreeItemSelected(self, item): > > level = item.getUserObject()[1] > for bat in self.buttons: > bat.setVisible(False) > for bat in self.button_dict[level]: > bat.setVisible(True) > > Window.alert("You clicked on " + value) > > > def onTreeItemStateChanged(self, item): > pass # We ignore this. > """************End of MainTRee******************""" > > def traveler(node, ndex=0, blist=None): > """Small utility function in controller to flatten user tree adapted > to immediate data""" > if blist is None: > blist = [] > # > # blist.append((node.name, (node.id, ndex))) > # uncomment this ^^ and comment that VV for full JSONRPC > # Current setup is demo > # > blist.append((node.name, (0,ndex))) #that > if node.isLeaf(): > return > ndex += 1 > for cnode in node.child: > traveler(cnode, ndex=ndex, blist=blist) > return blist > """That function is not to be used in the main app on a page, just in the > controller""" > > > """Next is for demo purposes only""" > """The data model has this class 'Nodal' as an ABCMeta and used as a > mixin""" > class TTS(object): > def __init__(self, name, child=[]): > self.name = name > self.child = child > def isLeaf(self): > return not self.child > """End of Demo purposes only""" > > MAXLEVELS = 10 > USER = 'User' > > def main(): > root = RootPanel() > """ Demo only--real button list generated other side of JSONRPC""" > button_list = [('Add Project',0), > ('Rename Project',1), > ('Delete Project', 1), > ('Duplicate Analysis Run', 1), > ('Add Analysis Run',1), > ('Rename Analysis Run',2), > ('Delete Analysis Run',2), > ('Add Workflow',2), > ('Go To Run Menu', 2), > ('Delete Workflow',3), > ('Insert Workflow Above Current Selection', 3)] > > b = ButtonPanel(button_list) > buttons = [el[0] for el in button_list] > button_dict = {} > for i in range(4): > button_dict[i] = [] > for (button_name, cat) in button_list: > button_dict[cat].append(button_name) > built222 = [TTS('performance_plot',[]), TTS('howler_algorithm', [])] > built221 = [TTS('wf9',[])] > built123 = [TTS('sum_stats', [])] > built122 = [TTS('sum_stats',[])] > built121 = [TTS('scan_reads',[]),TTS('analyze_reads',[])] > built023 = [TTS('wf7',[]), TTS('performance_plot',[])] > built021 = [TTS('wf1',[])] > built022 = [TTS('wf1',[]), TTS('scan_reads',[]), TTS('analyze > reads',[])] > built02 = [TTS('SNP calls',built021), > TTS('contrast bwa/bismark', built022), > TTS('test_fidelity',built023)] > built12 = [TTS('export',built121), TTS('fastq',built122), > TTS('bam', built123)] > built22 = [TTS('Mosaik',built221), TTS('Measurements', built222)] > blis1 = [TTS('Special Alignment',built02), > TTS('Scan',built12), > TTS('SureSelect', built22)] > trroot = TTS(USER,blis1) > # user_list is passed in as a value in a JSON object (Python dict) > arc = traveler(trroot) > """Ideally, arc is passed as a JSON object value (list of tuples). """ > t=MainTree(arc,b) > h=HorizontalPanel() > v=VerticalPanel() > v.add(t) > h.add(v) > v1=VerticalPanel() > v1.add(b) > h.add(v1) > h.add(b) > root.add(h) > if __name__ == '__main__': > main() > > > > On Wed, Sep 12, 2012 at 9:29 AM, C Anthony Risinger <[email protected]>wrote: > >> On Tue, Sep 11, 2012 at 5:53 PM, Michael Moore >> <[email protected]> wrote: >> > >> > If anyone knows how to automagically make one function in a Tree class >> > instantiation recognize objects from anothe class (buttons), maybe I can >> > avoid giving some Java programmers a conniption by not using Python to >> put >> > together a source file on the basis of number of layers or node levels >> in a >> > tree and then exec'ing it before handing it over to pyjsbuild. >> >> you'll need to whip up a small example highlighting the problem -- i'm >> not sure i even know what you're asking. >> >> in 99% of cases problems can be attributed to the application, and >> every now and again is a bug in pyjs somewhere ... sadly, the errors >> are not particularly clear, and even this depends on the build opts >> used ... >> >> ... are you building with `--enable-strict`? you may be using python >> features in the application code but not enabling them in the build. >> >> ... are you building with `--enable-debug`? this can improve the >> debugging experience, but it's value is subjective ...YMMV >> >> ... are you on Windows? download/install `comtypes` and use native >> "pyjd" runners ... this will run your app code in a real python >> interpreter, and is massively valuable for development. >> >> ^^^^ if you're not on Windows a new runner [giwebkit] "should" be >> available in the coming days ... i had a deadline at work sucking up >> all my time recently, but this weekend the family is out of town and i >> intend to merge it, regardless of any remaining bugs (if any ;-) >> > > > >> >> -- >> >> C Anthony >> >> -- >> >> >> >> > --
