home *** CD-ROM | disk | FTP | other *** search
/ Windows News 2005 November / WNnov2005.iso / Windows / Equipement / Blender / blender-2.37a-windows.exe / $_5_ / .blender / scripts / doc_browser.py < prev    next >
Text File  |  2005-04-17  |  12KB  |  457 lines

  1. #!BPY
  2.  
  3. """
  4. Name: 'BPy Doc Browser'
  5. Blender: 232
  6. Group: 'System'
  7. Tip: 'Browse BPython (scripting API) modules doc strings.'
  8. """
  9.  
  10. __author__ = "Daniel Dunbar"
  11. __url__ = ("blender", "elysiun")
  12. __version__ = "1.0"
  13. __bpydoc__ = """\
  14. The "Doc Browser" lets users navigate the documentation strings of part of
  15. the Blender Python API.
  16.  
  17. It doesn't give access yet to object method functions and variables, only to
  18. module functions, but still it is a handy reference.
  19.  
  20. Hotkeys:<br>
  21.     Page Up / Page Down: scroll 5 lines at a time;<br>
  22.     Up / Down arrow keys or mouse wheel: scroll one line at a time.
  23.  
  24. Notes:<br>
  25.     Everyone interested in the bpython api is also invited to read "The Blender
  26. Python API Reference" doc, available online ("Python Scripting Reference"
  27. entry in Blender's Help menu).
  28. """
  29.  
  30.  
  31. # $Id: doc_browser.py,v 1.3 2005/04/16 05:25:41 ianwill Exp $
  32. #
  33. # --------------------------------------------------------------------------
  34. # ***** BEGIN GPL LICENSE BLOCK *****
  35. #
  36. # Copyright (C) 2004:  Daniel Dunbar, ddunbar _at_ diads.com
  37. #
  38. # This program is free software; you can redistribute it and/or
  39. # modify it under the terms of the GNU General Public License
  40. # as published by the Free Software Foundation; either version 2
  41. # of the License, or (at your option) any later version.
  42. #
  43. # This program is distributed in the hope that it will be useful,
  44. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  45. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  46. # GNU General Public License for more details.
  47. #
  48. # You should have received a copy of the GNU General Public License
  49. # along with this program; if not, write to the Free Software Foundation,
  50. # Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  51. #
  52. # ***** END GPL LICENCE BLOCK *****
  53. # --------------------------------------------------------------------------
  54.  
  55. #####
  56. # Blender help browser
  57. # By Daniel Dunbar, 
  58. #
  59. # This should function as a self-explanatory (interface, not code)
  60. # (mostly) help browser. The code is wacky and nasty and or fun,
  61. # but mainly bad, just cause it works doesn't mean its readable! 
  62. # TEEHEE!
  63. #
  64. # The row_draw function could easily be made into a more generic
  65. # and usefull table drawing function... 
  66. #
  67.  
  68. import Blender
  69. from types import ListType, IntType, FloatType, StringType, ModuleType
  70. from Blender.Draw import *
  71. from Blender.BGL import *
  72.  
  73. # Simple version check, since I use the
  74. # buffer calls... DONT use this code,
  75. # assume everyone has 1.73+, and force
  76. # them to upgrade if they dont
  77. try:
  78.     a= BufList
  79.     version= 172
  80. except:
  81.     version= 173
  82.     
  83. # I could have used the split from the string module,
  84. # but some people might not have it
  85. def split(str, on):
  86.     out= [""]
  87.     for s in str:
  88.         if s in on: out.append("")
  89.         else: out[-1]= out[-1]+s
  90.  
  91.     if out[-1]=="": del(out[-1])
  92.  
  93.     return out
  94.  
  95. last_sort= 1; direction= 1
  96. def sort_browselist(type):
  97.     global browselist
  98.     global last_sort, direction
  99.  
  100.     if (type==last_sort): direction= -direction
  101.     else: direction= 1
  102.  
  103.     last_sort= type
  104.  
  105.     if (direction==1):
  106.         def byname(x, y): return cmp(x[0],y[0]);
  107.         def bytype(x, y): return cmp(x[1],y[1])
  108.         def bydata(x, y): return cmp(x[2],y[2])
  109.     else:
  110.         def byname(x, y): return cmp(y[0],x[0]);
  111.         def bytype(x, y): return cmp(y[1],x[1])
  112.         def bydata(x, y): return cmp(y[2],x[2])
  113.  
  114.     if (type==1): browselist.sort(byname)
  115.     elif (type==2): browselist.sort(bytype)
  116.     elif (type==3): browselist.sort(bydata)
  117.  
  118. selected= -1
  119. def view_doc(num):
  120.     global selected, selected_page
  121.  
  122.     if (selected==num): selected= -1
  123.     else: selected= num
  124.  
  125.     selected_page= 0
  126.  
  127. function_filter= 0
  128. def toggle_function_filter():
  129.     global function_filter
  130.  
  131.     function_filter= not function_filter
  132.     make_browselist()
  133.  
  134. def view_page(dir):
  135.     global selected_page
  136.  
  137.     selected_page= selected_page + dir
  138.  
  139. browse_scrollstart= 0
  140. def browse_module(num):
  141.     global browsing, selected, browse_scrollstart
  142.     
  143.     if (num>=0): newstr= browsing.val + "." + browselist[num][0]
  144.     else:
  145.         modules= split(browsing.val, ".")
  146.         newstr= ""
  147.         for m in modules[:-1]:
  148.             newstr= newstr+m
  149.     try:
  150.         browsing= Create(newstr)
  151.         make_browselist()
  152.     except:
  153.         browsing= Create('Blender')
  154.         make_browselist()
  155.         
  156.     browse_scrollstart= 0
  157.     scrolling= 0
  158.     selected= -1
  159.  
  160. def make_browselist():
  161.     global browselist
  162.  
  163.     browselist= []
  164.  
  165.     module= eval(browsing.val)
  166.     items= dir(module)
  167.  
  168.     for item_name in items:
  169.         if (item_name[:2]=='__'): continue
  170.  
  171.         data= [item_name, 'None', '', '']
  172.         item= eval(item_name,module.__dict__)
  173.         t= type(item)
  174.  
  175.         if (t==IntType): data[1]= 'Int'; data[2]= `item`
  176.         elif (t==FloatType): data[1]= 'Float'; data[2]= `item`
  177.         elif (t==StringType): data[1]= 'String'
  178.         elif (t==ModuleType): data[1]= 'Module'
  179.         elif (callable(item)):
  180.             data[1]= 'Function'
  181.             doc= item.__doc__
  182.             if (doc): data[3]= doc
  183.  
  184.         if (function_filter and data[1]!='Function'): continue
  185.  
  186.         browselist.append(data)
  187.  
  188. browsing= Create('Blender')
  189. make_browselist()
  190.  
  191. BROWSE_EVT= 1
  192.  
  193. SORT_BYNAME= 2
  194. SORT_BYTYPE= 3
  195. SORT_BYDATA= 4
  196.  
  197. DOC_PAGE_UP= 5
  198. DOC_PAGE_DOWN= 6
  199.  
  200. BACK_MODULE= 7
  201. CLOSE_VIEW= 8
  202. FILTER_DISPLAY= 9
  203.  
  204. #SCROLLBAR= 10
  205.  
  206. VIEW_DOC= 100
  207. BROWSE_MODULE= 20000
  208.  
  209. scr= Create(0)
  210. browse_scrollstart= 0
  211.  
  212. winrect= [0.0, 0.0, 0.0, 0.0]
  213. def draw():
  214.     global browsing, winrect, scr, browse_scrollstart
  215.  
  216.     # Blender doesn't give us direct access to
  217.     # the window size yet, but it does set the
  218.     # GL scissor box for it, so we can get the 
  219.     # size from that.
  220.  
  221.     if (version<173):
  222.         size= Buffer(GL_FLOAT, None, 4)
  223.         glGetFloat(GL_SCISSOR_BOX, size)
  224.         size= BufList(size)
  225.     else:
  226.         size= Buffer(GL_FLOAT, 4)
  227.         glGetFloatv(GL_SCISSOR_BOX, size)
  228.         size= size.list
  229.  
  230.     winrect= size[:]
  231.  
  232.     size[0]= size[1]= 0.0
  233.     
  234.     # Shrink the size to make a nice frame
  235.     # (also a good technique so you can be sure you are clipping things properly)
  236.     size[0], size[1]= int(size[0]+10), int(size[1]+10)
  237.     size[2], size[3]= int(size[2]-12), int(size[3]-10)
  238.  
  239.     glClearColor(0.6, 0.5, 0.3, 0.0)
  240.     glClear(GL_COLOR_BUFFER_BIT)
  241.  
  242.     # The frame
  243.     glColor3f(0.4, 0.5, 0.2)
  244.     glRectf(size[0], size[1], size[2], size[3])
  245.  
  246.     # Window header    
  247.     glColor3f(0.2, 0.2, 0.4)
  248.     glRectf(size[0], size[3]-25, size[2], size[3])
  249.  
  250.     glColor3f(0.6, 0.6, 0.6)
  251.     glRasterPos2f(size[0]+15, size[3]-17)
  252.     Text("Zr's Help Browser")
  253.  
  254.     Button("Filter", FILTER_DISPLAY, size[2]-400, size[3]-22, 45, 18)
  255.     Button("Back", BACK_MODULE, size[2]-300, size[3]-22, 45, 18)
  256.     browsing= String("Browse: ", BROWSE_EVT, size[2]-250, size[3]-22, 245, 18, browsing.val, 30)
  257.  
  258.     # The real table
  259.     def row_draw(rect, data, cols, cell_colors, text_colors):
  260.         if (len(data)!=len(cols)):
  261.             print "Must have same length data and columns"
  262.             return
  263.  
  264.         if (type(cell_colors)!=ListType): cell_colors= [cell_colors]
  265.         if (type(text_colors)!=ListType): text_colors= [text_colors]
  266.  
  267.         sx= rect[0]
  268.         for i in range(len(data)):
  269.             d= data[i]
  270.             c= cols[i]
  271.     
  272.             c, align= c[0], c[1]
  273.  
  274.             if (type(c)==FloatType): c= c*(rect[2]-rect[0])
  275.             ex= sx + c
  276.  
  277.             color= cell_colors[i%len(cell_colors)]
  278.             apply(glColor3f, color)
  279.             glRectf(sx, rect[1], ex, rect[3])
  280.  
  281.             color= text_colors[i%len(text_colors)]
  282.             apply(glColor3f, color)
  283.  
  284.             if (type(d)==StringType):
  285.                 str_width= len(d)*8
  286.                 if (align=='left'): glRasterPos2f(sx+3, rect[1]+5)
  287.                 elif (align=='center'): glRasterPos2f((sx+ex)/2 - str_width/2 +3, rect[1]+5)
  288.                 elif (align=='right'): glRasterPos2f(ex - str_width -3, rect[1]+5)
  289.  
  290.                 Text(d)
  291.             else:
  292.                 d(map(int,[sx, rect[1], ex, rect[3]]))
  293.  
  294.             sx= ex
  295.     # Some colors
  296.     black= (0.0, 0.0, 0.0)
  297.     white= (1.0, 1.0, 1.0)
  298.     red= (0.8, 0.1, 0.1)
  299.  
  300.     gray0= (0.17, 0.17, 0.17)
  301.     gray1= (0.25, 0.25, 0.25)
  302.     gray2= (0.33, 0.33, 0.33)
  303.     gray3= (0.41, 0.41, 0.41)
  304.     gray4= (0.49, 0.49, 0.49)
  305.     gray5= (0.57, 0.57, 0.57)
  306.     gray6= (0.65, 0.65, 0.65)
  307.  
  308.     cols= [[.3, 'left'], [.2, 'left'], [.4, 'right'], [.1, 'center']]
  309.  
  310.     header= [size[0]+20, size[3]-60, size[2]-40, size[3]-40]
  311.  
  312.     def sort_byname(co): Button("Name",SORT_BYNAME, co[0]+3, co[1], co[2]-co[0]-4, 19)
  313.     def sort_bytype(co): Button("Type",SORT_BYTYPE, co[0]+3, co[1], co[2]-co[0]-4, 19)
  314.     def sort_bydata(co): Button("Data",SORT_BYDATA, co[0]+3, co[1], co[2]-co[0]-4, 19)
  315.  
  316.     row_draw(header, [sort_byname, sort_bytype, sort_bydata,'Link'], cols, [gray0, gray1], gray6)
  317.  
  318.     if (selected!=-1):
  319.         table= [size[0]+20, size[1]+220, size[2]-40, size[3]-60]
  320.     else:
  321.         table= [size[0]+20, size[1]+20, size[2]-40, size[3]-60]
  322.  
  323.     row_height= 25
  324.     items= (table[3]-table[1])/row_height
  325.  
  326.     items= 10
  327.     if (items>len(browselist)): items= len(browselist)
  328.  
  329.     end= len(browselist)-items
  330.     #if (end>0):
  331.     #    scr= Scrollbar(SCROLLBAR, table[2]+5, table[1], 20, table[3]-table[1], scr.val, 0.0, end, 0, "Page Up/Down scrolls list.")
  332.  
  333.     row= table
  334.     row[1]= row[3]-row_height
  335.     start= browse_scrollstart
  336.     if (start+items>len(browselist)): items= len(browselist)-start
  337.     for i in range(items):
  338.         i= start+i
  339.         data= browselist[i][:]
  340.  
  341.         if (i%2): colors= [gray1, gray2]
  342.         else: colors= [gray2, gray3]
  343.  
  344.         # Strange pythonic code
  345.         def view_doc(co,num=i):
  346.             Button("Doc",VIEW_DOC+num, co[0]+3, co[1]+2, co[2]-co[0]-4, 19)
  347.  
  348.         def browse_module(co,num=i):
  349.             Button("Browse",BROWSE_MODULE+num, co[0]+3, co[1]+2, co[2]-co[0]-4, 19)
  350.  
  351.         if (data[1]=='Function'):
  352.             if data[3]:
  353.                 data[3]= view_doc
  354.                 tcolor= black
  355.             else:
  356.                 tcolor= red
  357.                 data[2]= 'NO DOC STRING'
  358.                 data[3]= ''
  359.         else:
  360.             if (data[1]=='Module'): data[3]= browse_module
  361.             else: data[3]= ''
  362.  
  363.             tcolor= black
  364.  
  365.         row_draw(row, data, cols, colors, tcolor)
  366.  
  367.         row[1]= row[1]-row_height
  368.         row[3]= row[3]-row_height
  369.  
  370.     if (selected!=-1):
  371.         table= [size[0]+20, size[1]+20, size[2]-40, size[1]+180]
  372.  
  373.         apply(glColor3f, gray5)
  374.         glRectf(table[0], table[3], table[2], table[3]+20)
  375.         apply(glColor3f, gray2)
  376.         glRectf(table[0], table[1], table[2], table[3])
  377.  
  378.         apply(glColor3f, black)
  379.         glRasterPos2f(table[0]+3, table[3]+5)
  380.         Text("Function: " + browsing.val + "." + browselist[selected][0])
  381.  
  382.         Button("Close", CLOSE_VIEW, table[2]-50, table[3], 45, 18)
  383.  
  384.         row_height= 20
  385.         view_lines= int((table[3]-table[1])/row_height)-1
  386.  
  387.         lines= split(browselist[selected][3], "\n")
  388.         doc_lines= len(lines)
  389.  
  390.         sindex= view_lines*selected_page
  391.         eindex= view_lines*(selected_page+1)
  392.         if (sindex>0):
  393.             sindex= sindex-1
  394.             eindex= eindex-1
  395.  
  396.         lines= lines[sindex:eindex]
  397.  
  398.         y= table[3]-20
  399.         for line in lines:
  400.             glRasterPos2f(table[0]+3, y)
  401.             Text(line)
  402.  
  403.             y= y-20
  404.  
  405.         if (sindex): Button("Page up", DOC_PAGE_UP, table[2]-100, table[3]-20, 90, 18)
  406.         if (eindex<doc_lines): Button("Page down", DOC_PAGE_DOWN, table[2]-100, table[1]+5, 90, 18)
  407.  
  408. lmouse= [0, 0]
  409.  
  410. def fit_scroll():
  411.     global browse_scrollstart, browselist
  412.     if (browse_scrollstart<0): browse_scrollstart= 0
  413.     elif (browse_scrollstart>=len(browselist)): browse_scrollstart= len(browselist)-1
  414.  
  415. def event(evt, val):
  416.     global browse_scrollstart
  417.  
  418.     if (evt==QKEY or evt==ESCKEY): Exit()
  419.     elif val:
  420.         if (evt in [PAGEUPKEY, PAGEDOWNKEY]):
  421.             if (evt==PAGEUPKEY): browse_scrollstart= browse_scrollstart-5
  422.             else: browse_scrollstart= browse_scrollstart+5
  423.         elif (evt in [UPARROWKEY, WHEELUPMOUSE]):
  424.             browse_scrollstart -= 1
  425.         elif (evt in [DOWNARROWKEY, WHEELDOWNMOUSE]):
  426.             browse_scrollstart += 1
  427.         else: return
  428.  
  429.         fit_scroll()
  430.         Redraw()
  431.  
  432. def bevent(evt):
  433.     if (evt==BROWSE_EVT): make_browselist()
  434.  
  435.     elif (evt==SORT_BYNAME): sort_browselist(1)
  436.     elif (evt==SORT_BYTYPE): sort_browselist(2)
  437.     elif (evt==SORT_BYDATA): sort_browselist(3)
  438.     
  439.     elif (evt==DOC_PAGE_UP): view_page(-1)
  440.     elif (evt==DOC_PAGE_DOWN): view_page(1)
  441.  
  442.     elif (evt==BACK_MODULE): browse_module(-1)
  443.     elif (evt==CLOSE_VIEW): view_doc(-1)
  444.     elif (evt==FILTER_DISPLAY): toggle_function_filter()
  445.  
  446.     #elif (evt==SCROLLBAR):
  447.     #    global browse_scrollstart
  448.     #    browse_scrollstart= int(scr.val)
  449.  
  450.     elif (evt>=BROWSE_MODULE): browse_module(evt-BROWSE_MODULE)
  451.     elif (evt>=VIEW_DOC): view_doc(evt-VIEW_DOC)    
  452.  
  453.     Redraw()
  454.  
  455. Register(draw, event, bevent)
  456.