Changeset 1666

Show
Ignore:
Timestamp:
12/10/06 19:49:40 (2 years ago)
Author:
eblot
Message:

RevtreePlugin:

  • Fix up XHTML tags in preference form
  • Add AJAX-style tooltips for changesets (based on jQuery and jTip)
  • Use inline SVG (will not work on old browsers)
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • revtreeplugin/0.10/revtree/htdocs/css/revtree.css

    r1653 r1666  
     1div#settings { 
     2} 
    13form#prefs { 
    24 margin-top: 2em;    
     
    2022 align: right;  
    2123} 
    22  
    2324div.revtree div#errormsg { 
    2425 border: solid red 2px; 
    2526 background-color: #fcc; 
    2627} 
    27  
    2828div.revprops { 
    2929 padding-left: 2ex; 
     
    3535 border-right: solid 1px #333; 
    3636} 
    37  
    3837div#treestyle div { 
    3938   display: block; 
     
    4746   padding-left: 3ex; 
    4847} 
    49  
    5048div#update { 
    5149 border-right: none; 
    5250} 
     51#prefs { 
     52 position: relative; 
     53 float: left; 
     54} 
     55div.svg { 
     56 position: relative; 
     57 float: left; 
     58} 
     59 
     60/* jTip */ 
     61#JT_arrow_left{ 
     62        background-image: url(../images/arrow_left.gif); 
     63        background-repeat: no-repeat; 
     64        background-position: left top; 
     65        position: absolute; 
     66        z-index:101; 
     67        left:-12px; 
     68        height:23px; 
     69        width:10px; 
     70    top:-3px; 
     71} 
     72#JT_arrow_right{ 
     73        background-image: url(../images/arrow_right.gif); 
     74        background-repeat: no-repeat; 
     75        background-position: left top; 
     76        position: absolute; 
     77        z-index:101; 
     78        height:23px; 
     79        width:11px; 
     80   top:-2px; 
     81} 
     82#JT { 
     83        position: absolute; 
     84        z-index:100; 
     85        border: 2px solid #CCCCCC; 
     86        background-color: #fff; 
     87} 
     88#JT_copy{ 
     89        padding:10px 10px 10px 10px; 
     90        color:#333333; 
     91} 
     92.JT_loader{ 
     93        background-image: url(../images/loader.gif); 
     94        background-repeat: no-repeat; 
     95        background-position: center center; 
     96        width:100%; 
     97        height:12px; 
     98} 
     99#JT_close_left{ 
     100        background-color: #CCCCCC; 
     101        text-align: left; 
     102        padding-left: 8px; 
     103        padding-bottom: 5px; 
     104        padding-top: 2px; 
     105        font-weight:bold; 
     106} 
     107#JT_close_right{ 
     108        background-color: #CCCCCC; 
     109        text-align: left; 
     110        padding-left: 8px; 
     111        padding-bottom: 5px; 
     112        padding-top: 2px; 
     113        font-weight:bold; 
     114} 
     115#JT_copy p{ 
     116margin:3px 0; 
     117} 
     118#JT_copy img{ 
     119        padding: 1px; 
     120        border: 1px solid #CCCCCC; 
     121} 
     122.jTip{ 
     123cursor:help; 
     124} 
     125.jTip a[title] { 
     126   /* hide default tooltips */ 
     127   display: none; 
     128} 
  • revtreeplugin/0.10/revtree/svgview.py

    r1652 r1666  
    251251                              str(self._revision), FONT_SIZE, FONT_NAME) 
    252252        self._text.attributes['style'] = 'fill:%s' % self._textcolor.rgb() 
    253         self._link = SVG.link(plink('%s/changeset/%d' % \ 
    254                               (self._parent.urlbase(), self._revision)),  
    255                               elements=[self._widget, self._text]) 
     253         
     254        link = "%s/revtree_log/?rev=%d&link=%s/changeset/%d" \ 
     255            % (self._parent.urlbase(), self._revision,  
     256               self._parent.urlbase(), self._revision) 
     257        self._link = SVG.link(link, elements=[self._widget, self._text]) 
    256258        if self._revision: 
    257259            self._link.attributes['id'] = 'rev%d' % self._revision 
     260            self._link.attributes['title'] = 'Changeset %d' % self._revision 
    258261                     
    259262    def visible(self): 
     
    756759        seed(0) 
    757760         
    758     def __str__(self): 
    759         """Render the revision tree as a SVG string""" 
    760         d = SVG.drawing() 
    761         d.setSVG(self._svg) 
    762         return d.toXml() 
    763          
    764761    def add_enhancer(self, enhancer): 
    765762        self._enhancers.append(enhancer) 
    766763         
    767     def save(self, filename): 
    768         """Save the revision tree in a file""" 
    769         d = SVG.drawing() 
    770         d.setSVG(self._svg) 
    771         d.toXml(filename) 
    772  
    773764    def position(self): 
    774765        """Return the position of the revision tree widget""" 
     
    900891    def svg(self): 
    901892        return self._svg 
     893 
     894    def __str__(self): 
     895        """Render the revision tree as a SVG string""" 
     896        import cStringIO 
     897        xml=cStringIO.StringIO() 
     898        self._svg.toXml(0, xml) 
     899        return xml.getvalue() 
     900         
     901    def save(self, filename): 
     902        """Save the revision tree in a file""" 
     903        d = SVG.drawing() 
     904        d.setSVG(self._svg) 
     905        d.toXml(filename) 
    902906         
    903907    def render(self, linkparent=False): 
  • revtreeplugin/0.10/revtree/templates/revtree.cs

    r1653 r1666  
    2121</script> 
    2222 
    23 <form id="prefs" method="get" action=""> 
    24  <div> 
    25   <div class="revprops"> 
    26     <fieldset id="properties"> 
    27      <legend>Filters</legend> 
    28      <div class="field"> 
    29       <label for="branch">Branch</label> 
    30       <select id="branch" name="branch"><?cs each:br = revtree.branches ?> 
    31        <option value="<?cs var:br ?>" <?cs if:revtree.branch == br  
    32        ?>selected="selected"<?cs /if ?>><?cs var:br ?></option><?cs 
    33       /each ?></select> 
     23<div id="settings"> 
     24 <form id="prefs" method="get" action=""> 
     25  <div> 
     26   <div class="revprops"> 
     27     <fieldset id="properties"> 
     28      <legend>Filters</legend> 
     29      <div class="field"> 
     30       <label for="branch">Branch</label> 
     31       <select id="branch" name="branch"><?cs each:br = revtree.branches ?> 
     32        <option value="<?cs var:br ?>" <?cs if:revtree.branch == br  
     33        ?>selected="selected"<?cs /if ?>><?cs var:br ?></option><?cs 
     34       /each ?></select> 
     35      </div> 
     36      <div class="field"> 
     37       <label for="author">Author</label> 
     38       <select id="author" name="author"><?cs each:auth = revtree.authors ?> 
     39        <option value="<?cs var:auth ?>" <?cs if:revtree.author == auth  
     40        ?>selected="selected"<?cs /if ?>><?cs var:auth ?></option><?cs 
     41       /each ?></select> 
     42      </div> 
     43     </fieldset> 
     44    </div> 
     45  
     46    <div class="revprops"> 
     47     <fieldset id="limits"> 
     48      <legend>Revisions</legend> 
     49      <div class="field"> 
     50       <input type="radio" id="limperiod" name="limits" value="limperiod" <?cs  
     51        if:revtree.limits == "limperiod" ?> checked="checked"<?cs /if ?>/> 
     52       <label for="period">Show last </label> 
     53       <select id="period" name="period"> 
     54        <?cs each:per = revtree.periods ?><option value="<?cs  
     55         var:per.value ?>" <?cs if:revtree.period == per.value  
     56         ?>selected="selected"<?cs /if ?>><?cs var:per.label ?></option> 
     57         <?cs /each ?></select> 
     58      </div> 
     59      <div class="field"> 
     60       <input type="radio" id="limrev" name="limits" value="limrev" <?cs  
     61        if:revtree.limits == "limrev" ?> checked="checked"<?cs /if ?>/> 
     62       <label for="revmin">From </label> 
     63        <select id="revmin" name="revmin"> 
     64         <?cs each:rev = revtree.revisions ?><option value="<?cs  
     65         var:rev ?>" <?cs if:revtree.revmin == rev ?>selected="selected"<?cs  
     66         /if ?>><?cs var:rev?></option> 
     67         <?cs /each ?></select> 
     68       <label for="revmax">up to </label> 
     69        <select id="revmax" name="revmax"> 
     70         <?cs each:rev = revtree.revisions ?><option value="<?cs  
     71         var:rev ?>" <?cs if:revtree.revmax == rev ?>selected="selected"<?cs  
     72         /if ?>><?cs var:rev ?></option> 
     73         <?cs /each ?></select> 
     74      </div> 
     75     </fieldset> 
     76    </div> 
     77  
     78    <div class="revprops" id="treestyle"> 
     79     <fieldset> 
     80      <legend>Style</legend> 
     81       <div class="field"> 
     82         <div> 
     83           <input type="radio" id="compact" name="treestyle" value="compact" <?cs  
     84          if:revtree.treestyle == "compact" ?> checked="checked"<?cs /if ?>/> 
     85         <label for="compact">Compact</label> 
     86         </div> 
     87         <div> 
     88         <input type="radio" id="timeline" name="treestyle" value="timeline" <?cs  
     89           if:revtree.treestyle == "timeline" ?> checked="checked"<?cs /if ?>/> 
     90          <label for="compact">Timeline</label> 
     91         </div> 
     92       </div> 
     93     </fieldset> 
     94    </div> 
     95  
     96    <div class="revprops" id="options"> 
     97     <fieldset id="options"> 
     98      <legend>Options</legend> 
     99      <div class="field"> 
     100       <input type="hidden" name="checkbox_hideterm"/> 
     101       <input type="checkbox" id="hideterm" 
     102         name="hideterm" <?cs if:revtree.hideterm 
     103         ?>checked="checked"<?cs /if ?> value="1"/><label for="hideterm">Hide  
     104         terminated branches</label> 
     105      </div> 
     106     </fieldset> 
     107    </div> 
     108  
     109    <div class="revprops" id="update"> 
     110     <div class="buttons"> 
     111      <input type="submit" value="Update"/> 
    34112     </div> 
    35      <div class="field"> 
    36       <label for="author">Author</label> 
    37       <select id="author" name="author"><?cs each:auth = revtree.authors ?> 
    38        <option value="<?cs var:auth ?>" <?cs if:revtree.author == auth  
    39        ?>selected="selected"<?cs /if ?>><?cs var:auth ?></option><?cs 
    40       /each ?></select> 
    41      </div> 
    42     </fieldset> 
    43    </div> 
    44  
    45    <div class="revprops"> 
    46     <fieldset id="limits"> 
    47      <legend>Revisions</legend> 
    48      <div class="field"> 
    49       <input type="radio" id="limperiod" name="limits" value="limperiod" <?cs  
    50        if:revtree.limits == "limperiod" ?> checked="checked"<?cs /if ?>/> 
    51       <label for="period">Show last </label> 
    52       <select id="period" name="period"> 
    53        <?cs each:per = revtree.periods ?><option value="<?cs  
    54         var:per.value ?>" <?cs if:revtree.period == per.value  
    55         ?>selected="selected"<?cs /if ?>><?cs var:per.label ?></option> 
    56         <?cs /each ?></select> 
    57      </div> 
    58      <div class="field"> 
    59       <input type="radio" id="limrev" name="limits" value="limrev" <?cs  
    60        if:revtree.limits == "limrev" ?> checked="checked"<?cs /if ?>/> 
    61       <label for="revmin">From </label> 
    62        <select id="revmin" name="revmin"> 
    63         <?cs each:rev = revtree.revisions ?><option value="<?cs  
    64         var:rev ?>" <?cs if:revtree.revmin == rev ?>selected="selected"<?cs  
    65         /if ?>><?cs var:rev?></option> 
    66         <?cs /each ?></select> 
    67       <label for="revmax">up to </label> 
    68        <select id="revmax" name="revmax"> 
    69         <?cs each:rev = revtree.revisions ?><option value="<?cs  
    70         var:rev ?>" <?cs if:revtree.revmax == rev ?>selected="selected"<?cs  
    71         /if ?>><?cs var:rev ?></option> 
    72         <?cs /each ?></select> 
    73      </div> 
    74     </fieldset> 
    75    </div> 
    76  
    77    <div class="revprops" id="treestyle"> 
    78     <fieldset> 
    79      <legend>Style</legend> 
    80       <div class="field"> 
    81         <div> 
    82           <input type="radio" id="compact" name="treestyle" value="compact" <?cs  
    83          if:revtree.treestyle == "compact" ?> checked="checked"<?cs /if ?>/> 
    84         <label for="compact">Compact</label> 
    85         </div> 
    86         <div> 
    87         <input type="radio" id="timeline" name="treestyle" value="timeline" <?cs  
    88           if:revtree.treestyle == "timeline" ?> checked="checked"<?cs /if ?>/> 
    89          <label for="compact">Timeline</label> 
    90         </div> 
    91       </div> 
    92    </div> 
    93  
    94    <div class="revprops" id="options"> 
    95     <fieldset id="options"> 
    96      <legend>Options</legend> 
    97      <div class="field"> 
    98       <input type="hidden" name="checkbox_hideterm"> 
    99       <input type="checkbox" id="hideterm" 
    100         name="hideterm" <?cs if:revtree.hideterm 
    101         ?>checked="checked"<?cs /if ?> value="1"/><label for="hideterm">Hide  
    102         terminated branches</label> 
    103      </div> 
    104     </fieldset> 
    105    </div> 
    106  
    107    <div class="revprops" id="update"> 
    108     <div class="buttons"> 
    109      <input type="submit" value="Update"/> 
    110113    </div> 
    111   </div> 
    112  </div
    113 </form
     114  </div> 
     115 </form
     116</div
    114117 
    115118<?cs if revtree.legend ?> 
     
    125128<?cs else ?> 
    126129<div class="svg"> 
    127  <embed src="<?cs var:revtree.svg.src ?>" type="image/svg+xml" width="<?cs 
    128    var:revtree.svg.width ?>" height="<?cs var:revtree.svg.height ?>"></embed> 
     130  <?cs if revtree.svg.src ?><object data="<?cs  
     131  var:revtree.svg.src ?>" type="image/svg+xml" width="<?cs  
     132  var:revtree.svg.width ?>" height="<?cs var:revtree.svg.height  
     133  ?>"></object><?cs else ?><?cs var:revtree.svg.image ?><?cs /if ?> 
    129134</div> 
    130135<?cs /if ?> 
  • revtreeplugin/0.10/revtree/tests/revgen.py

    r1633 r1666  
    3333    repos = Repository(env, 'anonymous') 
    3434    bcre = re.compile(r'^(?P<branch>branches/[^/]+|trunk|data)' 
    35                       r'(/(?P<path>.*))?$') 
     35                      r'(?:/(?P<path>.*))?$') 
    3636    revrange = (1400,1520) 
    3737    repos.build(bcre, revrange, timerange=None) 
  • revtreeplugin/0.10/revtree/web_ui.py

    r1652 r1666  
    1818 
    1919from trac.core import * 
     20from trac.perm import IPermissionRequestor 
    2021from trac.util import Markup, TracError 
    2122from trac.web import IRequestHandler 
    22 from trac.web.chrome import add_stylesheet, INavigationContributor, \ 
    23                             ITemplateProvider 
     23from trac.web.chrome import add_stylesheet, add_script, \ 
     24                            INavigationContributor, ITemplateProvider 
    2425from trac.web.href import Href 
    25 from trac.wiki import WikiSystem 
    26 from trac.perm import IPermissionRequestor 
     26from trac.wiki import wiki_to_oneliner, WikiSystem 
     27 
    2728from revtree import Repository, SvgRevtree, ChangesetEmptyRange 
    2829from revtree.enhancer import Enhancer 
     
    169170 
    170171    def match_request(self, req): 
    171         return re.match(r'/revtree/?', req.path_info) is not None 
     172        match = re.match(r'/revtree(_log)?/?', req.path_info) 
     173        if match: 
     174            if match.group(1): 
     175                req.args['log'] = True 
     176            return True 
    172177 
    173178    def process_request(self, req): 
    174179        req.perm.assert_permission('REVTREE_VIEW') 
    175180             
     181        if req.args.has_key('log'): 
     182            return self._process_log(req) 
     183        else: 
     184            return self._process_revtree(req) 
     185             
     186    def _process_log(self, req): 
     187        """Handle AJAX log requests""" 
     188        try: 
     189            rev = int(req.args['rev']) 
     190            repos = self.env.get_repository(req.authname) 
     191            chgset = repos.get_changeset(rev) 
     192            wikimsg = wiki_to_oneliner(chgset.message, self.env, None,  
     193                                       shorten=False) 
     194            # FIXME: check if there is a better way to discard ellipsis 
     195            wikimsg = Markup(wikimsg.replace('...', '')); 
     196            req.hdf['revtree_log.rev'] = rev 
     197            req.hdf['revtree_log.message'] = wikimsg 
     198            return 'revtree_log.cs', 'application/xhtml+xml' 
     199        except: 
     200            raise TracError, "Invalid revision log request" 
     201         
     202    def _process_revtree(self, req): 
     203        """Handle revtree generation requests""" 
    176204        revstore = RevtreeStore(self.env, req.authname, \ 
    177205                                (self.oldest, self.youngest), 
     
    187215        req.hdf['title'] = 'Revision Tree' 
    188216        req.hdf['revtree.periods'] = self._get_periods() 
     217 
     218        # add javascript for AJAX tooltips  
     219        add_script(req, 'revtree/js/jquery.js') 
     220        add_script(req, 'revtree/js/svgtip.js')     
    189221 
    190222        try: 
     
    212244            svgrevtree.build() 
    213245            svgrevtree.render() 
    214             svgrevtree.save(os.path.join(self.cache_dir, filename)) 
    215246            extent = svgrevtree.extent() 
    216247            extent = ((extent[0]*self.scale)/100,(extent[1]*self.scale)/100) 
     
    222253            else: 
    223254                src = "%s/%s" % (self.cache_url, filename) 
    224             req.hdf['revtree.svg.src'] = src 
     255            #svgrevtree.save(os.path.join(self.cache_dir, filename)) 
     256            #req.hdf['revtree.svg.src'] = src 
     257            req.hdf.set_unescaped('revtree.svg.image', str(svgrevtree)) 
    225258            (w,h) = extent 
    226259            #(w,h) = (900, (900*h)/w) 
     
    263296                                                                                
    264297        add_stylesheet(req, 'revtree/css/revtree.css') 
    265         return 'revtree.cs', None 
     298        return 'revtree.cs', 'application/xhtml+xml' 
    266299 
    267300    # ITemplateProvider 
     
    288321        bre = self.config.get('revtree', 'branch_re', 
    289322                  r'^(?P<branch>branches/[^/]+|trunk|data)' 
    290                   r'(/(?P<path>.*))?$') 
     323                  r'(?:/(?P<path>.*))?$') 
    291324        self.bcre = re.compile(bre) 
    292325        self.urlbase = self.config.get('trac', 'base_url') 
  • revtreeplugin/0.10/setup.py

    r1633 r1666  
    1616 
    1717PACKAGE = 'RevtreePlugin' 
    18 VERSION = '0.4.0
     18VERSION = '0.4.1
    1919 
    2020setup ( 
     
    3131        'revtree': [ 
    3232            'htdocs/css/*.css', 
     33            'htdocs/js/*.js', 
    3334            'templates/*.cs' 
    3435        ]