Ticket #1322: manipulate_take3_part3.patch

File manipulate_take3_part3.patch, 12.6 KB (added by was, 14 years ago)

this requires that you also install the extcode patch that gives jquery support.

  • sage/server/notebook/cell.py

    # HG changeset patch
    # User William Stein <wstein@gmail.com>
    # Date 1204509750 21600
    # Node ID c1b3be3bcc9235bb90637864aad61e6cea471e2b
    # Parent  48f2d5de9355c29c0d5f477db1d137f8def9bca4
    sage-1322: manipulate -- part 2
    
    diff -r 48f2d5de9355 -r c1b3be3bcc92 sage/server/notebook/cell.py
    a b class Cell(Cell_generic): 
    393393            z = self.output_text(ncols,html,raw,allow_manipulate=False)
    394394            try:
    395395                # Fill in the input valuees
    396                 if hasattr(self, 'manipulate'):
     396                # TODO -- redo
     397                if False and hasattr(self, 'manipulate'):
    397398                    inp = self.manipulate
    398399                    i = inp.lstrip().find('\n'); inp = inp[:i]
    399400                    i = inp.rfind('.'); inp = inp[i+1:]
    class Cell(Cell_generic): 
    404405                output,html = self._manipulate_output
    405406                z = z.replace('<?TEXT>', output.lstrip())
    406407                z = z.replace('<?HTML>', html)
    407 
    408408               
    409409                return z
    410410            except (ValueError, AttributeError), msg:
  • sage/server/notebook/js.py

    diff -r 48f2d5de9355 -r c1b3be3bcc92 sage/server/notebook/js.py
    a b function check_for_cell_update_callback( 
    19901990   
    19911991    set_output_text(id, output_text, output_text_wrapped,
    19921992                    output_html, stat, introspect_html);
    1993    
     1993
    19941994    if (stat == 'd') {
    19951995        active_cell_list = delete_from_array(active_cell_list, id);
    19961996
  • sage/server/notebook/manipulate.py

    diff -r 48f2d5de9355 -r c1b3be3bcc92 sage/server/notebook/manipulate.py
    a b AUTHOR: 
    1616    -- Jason Grout (2008-03): collaborators substantially on the
    1717       design and prototypes.
    1818
    19 TODO/PLAN:
    20    [ ] sliders
    21    [ ] default value
    22    [ ] more widgets
    23    [ ] better widget layout controls
     19TODO:
     20   [ ] get sliders to work
     21   [ ] default values; values after move slider
     22   [ ] implement a color object
     23
     24PLANS and IDEAS:
     25   [ ] automagically determine the type of control from the default
     26       value of the variable.  Here is how this will work:
     27        * u                      blank input field
     28        * u = (umin,umax)        slider; umin must not be a string
     29        * u = (umin,umax,du)     discrete slider
     30        * u = [1,2,3,4]          setter bar: automatically when there are are most 5
     31                                 elements; otherwise a drop down menu
     32        * u = ((xmin,xmax),(ymin,ymax))  2d slider
     33        * u = Graphic            a locator in a 2d plot  (Graphic is a 2d graphics objects)
     34        * u = True or u = False  a checkbox
     35        * u = color(...)         a color slider
     36        * u = "string"           text input field
     37        * u = ('label', obj)     obj can be any of the above; control is labeled with
     38                                 the given label
     39        * u = element            if parent(element)._manipulate_control_(element) is
     40                                 defined, then it will be used.  Otherwise make a
     41                                 text input that coerces input to parent(element)
     42   [ ] tag_cell('foo') -- makes it so one can refer to the current cell
     43       from elsewhere using the tag foo instead of the cell id number
     44       This involves doing something with SAGE_CELL_ID and the cell_id()
     45       method. 
    2446   [ ] 100% doctest coverage
     47   
     48JQUERY:
     49   [ ] tab_view -- represents an object in which clicking the tab
     50                     with label lbl[i] displays expr[i]
     51   [ ] slide_view -- represents an object in which the a list of objects
     52                     are displayed on successive slides.
     53   [ ] framed -- put a frame around an object
     54   [ ] panel -- put an object in a panel
     55   [ ] flot (?)
     56
     57ELEMENTS:
     58   [ ] control: this models the input and other tags in html
     59          align -- left, right, top, texttop, middle, absmiddle, baseline, bottom, absbottom
     60          background -- the color of the background for the cell
     61          frame -- draw a frame around
     62          disabled -- disables the input element when it first loads
     63                      so that the user can not write text in it, or
     64                      select it.
     65          editable -- bool
     66          font_size -- integer
     67          maxlength -- the maximum number of characters allowed in a text field.
     68          name -- defines a unique name for the input element
     69          size -- the size of the input element
     70          type -- button, checkbox, file, password, radio, slider, text, setter_bar, drop_down
     71   [ ] setter bar (buttons)
     72   [ ] checkbox
     73   [ ] color slider
     74   [ ] blank input field
     75   [ ] 2d slider
     76   [ ] locator in a graphic
     77
     78IDEAS for code:
     79
     80@manipulate
     81def foo(x=range(10), y=slider(1,10)):
     82    ...
     83
     84@manipulate
     85def foo(x=random_matrix(ZZ,2))
     86    ...
     87
     88
     89@framed
     90def foo(x,y):
     91    ...
    2592"""
    2693
    2794import inspect
    2895
    2996SAGE_CELL_ID = 0
    3097vars = {}
     98
     99_k = 0
     100def new_adapt_name():
     101    global _k
     102    _k += 1
     103    return 'adapt%s'%_k
     104   
    31105
    32106def html(s):
    33107    """
    def html(s): 
    41115        string -- html format
    42116    """
    43117    print "<html>%s</html>"%s
     118
     119def html_slider(id, callback, margin=0):
     120    s = """<div id='%s' class='ui-slider-1' style="margin:%spx;"><span class='ui-slider-handle'></span></div>"""%(
     121        id, int(margin))
     122
     123    # We now generat javascript that gets run after the above div gets
     124    # inserted. This happens because of the setTimeout function below
     125    # which gets passed an anonymous function.
     126    s += """
     127    <script>
     128    setTimeout(function() {
     129        $('#%s').slider();
     130        $('#%s').bind('click', function () { var position = $('#%s').slider('value',0); %s; });
     131    }, 1)
     132    </script>
     133    """%(id, id, id, callback)
     134    return s
     135   
    44136
    45137class ManipulateControl:
    46138    """
    class ManipulateControl: 
    61153
    62154    def __repr__(self):
    63155        return "A ManipulateControl (abstract base class)"
     156
     157    def adapt(self):
     158        """
     159        Return string representation of function that is called to
     160        adapt the values of this control to Python.
     161        """
     162        name = new_adapt_name()
     163        vars[name] = self._adapt
     164        return 'sage.server.notebook.manipulate.vars[\\"%s\\"]'%name
     165
     166    def _adapt(self, x):
     167        return x
    64168       
    65169    def manipulate(self):
    66170        """
    class ManipulateControl: 
    71175        OUTPUT:
    72176            string -- that is meant to be evaluated in Javascript
    73177        """
    74         return 'manipulate(%s, "sage.server.notebook.manipulate.vars[%s][\\"%s\\"]=sage_eval(r\\"\\"\\""+%s+"\\"\\"\\", globals())\\n%s()");'%(
    75             self.cell_id(), self.cell_id(), self.var(), self.value(), self.function_name())
     178        s = 'manipulate(%s, "sage.server.notebook.manipulate.vars[%s][\\"%s\\"]=sage_eval(r\\"\\"\\"%s("+%s+")\\"\\"\\", globals())\\n%s()");'%(
     179            self.cell_id(), self.cell_id(), self.var(), self.adapt(), self.value(), self.function_name())
     180        return s
    76181
    77182    def function_name(self):
    78183        """
    class TextBox(ManipulateControl): 
    116221        OUTPUT:
    117222             string -- javascript
    118223        """
    119         return "this.value"
    120    
     224        return 'this.value'
     225
    121226    def render(self):
    122227        """
    123228        Render this control as a string.
    class Slider(ManipulateControl): 
    152257        OUTPUT:
    153258             string -- javascript
    154259        """
    155         return "this.value"
     260        return "position"
    156261   
     262    def _adapt(self, position):
     263        # Input position is a string that evals to a float between 0 and 100.
     264        # we translate it into an index into self.__values
     265        v = self.__values
     266        i = int(len(v) * (float(position)/100.0))
     267        if i < 0:
     268            i = 0
     269        elif i >= len(v):
     270            i = len(v) - 1
     271        return v[i]
     272
    157273    def render(self):
    158274        """
    159275        Render this control as a string.
    class Slider(ManipulateControl): 
    161277        OUTPUT:
    162278             string -- html format
    163279        """
    164         return """
    165         SLIDER %s: <input type='text' value='<?%s>' onchange='%s'></input>
    166         """%(self.var(), self.var(), self.manipulate())
     280        return html_slider('slider-%s-%s'%(self.var(), self.cell_id()), self.manipulate())
    167281   
    168282
    169283class ManipulateCanvas:
    class ManipulateCanvas: 
    196310        return """
    197311        <table bgcolor=black cellpadding=3><tr><td bgcolor=white>
    198312        <?TEXT>
    199            <table border=0 width=800px>
     313           <table border=0 width=800px height=500px>
    200314           <tr><td align=center>  <?HTML>  </td></tr>
    201315           </table>
    202316        </td></tr></table>
    def manipulate(f): 
    234348
    235349    if defaults is None:
    236350        defaults = []
    237        
     351
    238352    n = len(args) - len(defaults)
    239     controls = [TextBox(f, v) for v in args[:n]] + \
    240                [defaults[i].render(f, args[i+n]) for i in range(len(defaults))]
    241    
     353    controls = [automatic_control(f, args[i], defaults[i-n] if i >= n else None) for i in range(len(args))]
     354    #controls = [automatic_control(f, v) for v in args[:n]] + \
     355    #           [defaults[i].render(f, args[i+n]) for i in range(len(defaults))]
     356
    242357    C = ManipulateCanvas(controls)
    243    
     358
    244359    vars[SAGE_CELL_ID] = {}
    245360    d = vars[SAGE_CELL_ID]
    246361    for v in args:
    247362         d[v] = ''
    248    
     363
    249364    html(C.render())
    250    
     365
    251366    def g():
    252367        return f(*[d[args[i]] for i in range(len(args))])
    253368    return g   
    class slider(control): 
    299414    def render(self, f, var):
    300415        return Slider(f, var, self.__values)
    301416       
     417def automatic_control(f, v, default):
     418    if isinstance(default, control):
     419        C = default
     420    elif isinstance(default, list):
     421        C = slider(default)
     422    else:
     423        C = text_box(str(default))
     424    return C.render(f, v)
  • sage/server/notebook/notebook.py

    diff -r 48f2d5de9355 -r c1b3be3bcc92 sage/server/notebook/notebook.py
    a b SYSTEMS = ['sage', 'axiom', 'gap', 'gp', 
    3636SYSTEMS = ['sage', 'axiom', 'gap', 'gp', 'jsmath', 'kash', 'latex', 'lisp', 'macaulay2', 'magma', 'maple', 'mathematica', 'matlab', 'maxima', 'mupad', 'mwrank', 'octave', 'python', 'sage', 'sh', 'singular']
    3737
    3838JSMATH = True
     39
     40JQUERY = True
    3941
    4042if is_package_installed("jsmath-image-fonts"):
    4143    JSMATH_IMAGE_FONTS = True
    class Notebook(SageObject): 
    14371439            head += '<script type="text/javascript" src="/javascript/jsmath/jsMath.js"></script>\n'
    14381440            head += "<script type='text/javascript'>jsMath.styles['#jsMath_button'] = jsMath.styles['#jsMath_button'].replace('right','left');</script>\n"
    14391441
     1442        if JQUERY:
     1443            # Load the jquery and ui-jquery javascript library.
     1444            # This is used for manipulate functionality in the notebook, and will be used
     1445            # to enable drag and drop, image zoom, etc.
     1446            head += '''
     1447<script type="text/javascript" src="/javascript/jquery/jquery.js"></script>
     1448<script type="text/javascript" src="/javascript/jqueryui/jquery.dimensions.js"></script>
     1449<script type="text/javascript" src="/javascript/jqueryui/ui.mouse.js"></script>
     1450<script type="text/javascript" src="/javascript/jqueryui/ui.slider.js"></script>
     1451<script type="text/javascript" src="/javascript/jqueryui/ui.draggable.js"></script>
     1452<script type="text/javascript" src="/javascript/jqueryui/ui.draggable.ext.js"></script>
     1453<script type="text/javascript" src="/javascript/jqueryui/ui.resizable.js"></script>
     1454<script type="text/javascript" src="/javascript/jqueryui/ui.dialog.js"></script>
     1455<link rel="stylesheet" href="/javascript/jqueryui/themes/flora/flora.all.css"
     1456   type="text/css" media="screen" title="Flora (Default)">
     1457         '''
     1458
     1459        # This was for syntax hilighting 
    14401460#        head +=' <script type="text/javascript" src="/javascript/highlight/prettify.js"></script>\n'
    14411461#        head += '<link rel=stylesheet href="/css/highlight/prettify.css" type="text/css">\n'
    14421462
    14431463        head +=' <script type="text/javascript" src="/javascript/sage3d.js"></script>\n'
     1464
     1465        # Jmol -- embedded 3d graphics.
    14441466        head +=' <script type="text/javascript" src="/java/jmol/appletweb/Jmol.js"></script>\n'
    1445         head +=' <script>jmolInitialize("/java/jmol");</script>\n' # this must stay in the <body>
     1467       
     1468        head +=' <script>jmolInitialize("/java/jmol");</script>\n' # this must stay in the <head>
    14461469        return head
    14471470
    14481471    def html_worksheet_topbar(self, worksheet, select=None, username='guest'):