source: trunk/www/views/experiments/bioassaysets/view_bioassayset.jsp @ 5937

Last change on this file since 5937 was 5937, checked in by Nicklas Nordborg, 11 years ago

References #1655: GUI improvements

  • Fixes rest of view pages in biomaterials menu.
  • Use SVG filter to make disabled button images grayscale.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Id
File size: 19.8 KB
Line 
1<%-- $Id: view_bioassayset.jsp 5937 2012-01-27 11:00:26Z nicklas $
2  ------------------------------------------------------------------
3  Copyright (C) 2006 Jari Häkkinen, Nicklas Nordborg, Martin Svensson
4  Copyright (C) 2007 Johan Enell
5
6  This file is part of BASE - BioArray Software Environment.
7  Available at http://base.thep.lu.se/
8
9  BASE is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License
11  as published by the Free Software Foundation; either version 3
12  of the License, or (at your option) any later version.
13
14  BASE is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  GNU General Public License for more details.
18
19  You should have received a copy of the GNU General Public License
20  along with BASE. If not, see <http://www.gnu.org/licenses/>.
21  ------------------------------------------------------------------
22
23  @author Nicklas
24  @version 2.0
25--%>
26<%@ page pageEncoding="UTF-8" session="false"
27  import="net.sf.basedb.core.SessionControl"
28  import="net.sf.basedb.core.DbControl"
29  import="net.sf.basedb.core.Item"
30  import="net.sf.basedb.core.ItemContext"
31  import="net.sf.basedb.core.Permission"
32  import="net.sf.basedb.core.Experiment"
33  import="net.sf.basedb.core.BioAssaySet"
34  import="net.sf.basedb.core.BioAssay"
35  import="net.sf.basedb.core.Transformation"
36  import="net.sf.basedb.core.Job"
37  import="net.sf.basedb.core.PluginDefinition"
38  import="net.sf.basedb.core.PluginConfiguration"
39  import="net.sf.basedb.core.User"
40  import="net.sf.basedb.core.ItemQuery"
41  import="net.sf.basedb.core.ItemResultList"
42  import="net.sf.basedb.core.Include"
43  import="net.sf.basedb.core.PermissionDeniedException"
44  import="net.sf.basedb.core.PluginDefinition"
45  import="net.sf.basedb.core.ParameterInfo"
46  import="net.sf.basedb.core.RawDataType"
47  import="net.sf.basedb.core.BasicItem"
48  import="net.sf.basedb.core.Nameable"
49  import="net.sf.basedb.core.File"
50  import="net.sf.basedb.core.plugin.GuiContext"
51  import="net.sf.basedb.core.plugin.Plugin"
52  import="net.sf.basedb.core.query.Orders"
53  import="net.sf.basedb.core.query.Hql"
54  import="net.sf.basedb.clients.web.Base"
55  import="net.sf.basedb.clients.web.PermissionUtil"
56  import="net.sf.basedb.clients.web.util.HTML"
57  import="net.sf.basedb.util.Values"
58  import="net.sf.basedb.util.formatter.Formatter"
59  import="net.sf.basedb.clients.web.formatter.FormatterFactory"
60  import="net.sf.basedb.clients.web.extensions.ExtensionsControl"
61  import="net.sf.basedb.clients.web.extensions.JspContext"
62  import="net.sf.basedb.clients.web.extensions.renderer.PrefixSuffixRenderer"
63  import="net.sf.basedb.clients.web.extensions.toolbar.ToolbarUtil"
64  import="net.sf.basedb.clients.web.extensions.plot.OverviewPlotAction"
65  import="net.sf.basedb.clients.web.extensions.plot.PlotGenerator"
66  import="net.sf.basedb.util.extensions.ExtensionsInvoker"
67  import="net.sf.basedb.util.extensions.ActionIterator"
68  import="java.util.Date"
69  import="java.util.Map"
70  import="java.util.Set"
71  import="java.util.List"
72  import="java.util.Iterator"
73%>
74<%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
75<%@ taglib prefix="tbl" uri="/WEB-INF/table.tld" %>
76<%@ taglib prefix="t" uri="/WEB-INF/tab.tld" %>
77<%@ taglib prefix="p" uri="/WEB-INF/path.tld" %>
78<%@ taglib prefix="ext" uri="/WEB-INF/extensions.tld" %>
79<%!
80  private static final Item itemType = Item.BIOASSAYSET;
81  private static final GuiContext guiContext = new GuiContext(itemType, GuiContext.Type.ITEM);
82%>
83<%
84final SessionControl sc = Base.getExistingSessionControl(pageContext, true);
85final String ID = sc.getId();
86final ItemContext cc = Base.getAndSetCurrentContext(sc, itemType, null, null);
87final int itemId = cc.getId();
88final String tabId = Values.getString(request.getParameter("tab"), "properties");
89
90final float scale = Base.getScale(sc);
91final String root = request.getContextPath();
92final DbControl dc = sc.newDbControl();
93try
94{
95  Map<Plugin.MainType, Integer> pluginCount = PluginDefinition.countPlugins(dc, guiContext);
96
97  String title = null;
98  final BioAssaySet bioAssaySet = BioAssaySet.getById(dc, itemId);
99  final Experiment experiment = bioAssaySet.getExperiment();
100  final int experimentId = experiment.getId();
101  final boolean hasDbSpots = bioAssaySet.getNumSpots() > 0;
102  Transformation transformation = bioAssaySet.getTransformation();
103  RawDataType rawDataType = experiment.getRawDataType();
104 
105  Job job = null;
106  boolean readJob = true;
107  PluginDefinition plugin = null;
108  boolean readPlugin = true;
109  PluginConfiguration configuration = null;
110  boolean readConfiguration = true;
111
112  try
113  {
114    job = transformation.getJob();
115  }
116  catch (PermissionDeniedException ex)
117  {
118    readJob = false;
119    readPlugin = false;
120    readConfiguration = false;
121  }
122  if (job != null)
123  {
124    try
125    {
126      plugin = job.getPluginDefinition();
127    }
128    catch (PermissionDeniedException ex)
129    {
130      readPlugin = false;
131    }
132    try
133    {
134      configuration = job.getPluginConfiguration();
135    }
136    catch (PermissionDeniedException ex)
137    {
138      readConfiguration = false;
139    }
140  }
141 
142  final boolean createPermission = experiment.hasPermission(Permission.USE);
143  final boolean writePermission = bioAssaySet.hasPermission(Permission.WRITE);
144  final boolean deletePermission = bioAssaySet.hasPermission(Permission.DELETE);
145  Formatter<Date> dateFormatter = FormatterFactory.getDateFormatter(sc);
146  Formatter<Date> dateTimeFormatter = FormatterFactory.getDateTimeFormatter(sc);
147  JspContext jspContext = ExtensionsControl.createContext(dc, pageContext, guiContext, bioAssaySet);
148  ExtensionsInvoker toolbarInvoker = ToolbarUtil.useExtensions(jspContext);
149  ExtensionsInvoker overviewPlotInvoker = ExtensionsControl.useExtensions(jspContext, 
150      "net.sf.basedb.clients.web.bioassayset.overviewplots");
151  %>
152  <base:page title="<%=title%>">
153  <base:head scripts="table.js,tabcontrol.js,newjoust.js" styles="table.css,toolbar.css,headertabcontrol.css,path.css,newjoust.css">
154    <ext:scripts context="<%=jspContext%>" />
155    <ext:stylesheets context="<%=jspContext%>" />
156    <script language="JavaScript">
157    function editItem()
158    {
159      Main.viewOrEditItem('<%=ID%>', '<%=itemType.name()%>', <%=itemId%>, true);
160    }
161    function deleteItem()
162    {
163      location.replace('index.jsp?ID=<%=ID%>&cmd=DeleteItem&experiment_id=<%=experimentId%>&item_id=<%=itemId%>');
164    }
165    function restoreItem()
166    {
167      location.replace('index.jsp?ID=<%=ID%>&cmd=RestoreItem&experiment_id=<%=experimentId%>&item_id=<%=itemId%>');
168    }
169    function switchTab(tabControlId, tabId)
170    {
171      if (TabControl.isActive(tabControlId, tabId)) return;
172      if (tabId == 'bioassays')
173      {
174        location.href = '../bioassays/index.jsp?ID=<%=ID%>&experiment_id=<%=experimentId%>&bioassayset_id=<%=itemId%>&tab='+tabId;
175      }
176      else if (tabId == 'spotdata')
177      {
178        location.href = '../spotdata/index.jsp?ID=<%=ID%>&experiment_id=<%=experimentId%>&bioassayset_id=<%=itemId%>';
179      }
180      else if ((tabId == 'overviewplots' || tabId == 'cfplots') && tabId != '<%=tabId%>')
181      {
182        location.href = 'index.jsp?ID=<%=ID%>&cmd=ViewItem&experiment_id=<%=experimentId%>&bioassayset_id=<%=itemId%>&tab='+tabId;
183      }
184      else
185      {
186        TabControl.setActiveTab(tabControlId, tabId);
187      }
188    }
189    function runItemPlugin(cmd)
190    {
191      Main.openPopup('index.jsp?ID=<%=ID%>&cmd='+cmd+'&experiment_id=<%=experimentId%>&item_id=<%=itemId%>', 'RunPlugin'+cmd, 750, 500);
192    }
193
194    function ImageQueue(baseId)
195    {
196      this.images = new Array();
197      this.nextImage = 0;
198
199      this.addImage = function(imageId, url)
200      {
201        this.images[this.images.length] = imageId;
202        var img = document.getElementById(imageId);
203        img.realSrc = url;
204      }
205
206      this.loadNextImage = function()
207      {
208        if (this.images.length <= this.nextImage) return;
209        var imageId = this.images[this.nextImage];
210        var img = document.getElementById(imageId);
211        img.src = '../../../images/plot_generating_400x300.gif';
212        img.realImg = new Image();
213        img.realImg.onload = function()
214        {
215          img.src = img.realImg.src;
216          img.style.background = 'transparent';
217          setTimeout('loadNextImage()', 100);
218        };
219        img.realImg.src = img.realSrc;
220        this.nextImage++;
221      }
222    }
223   
224    var plotQueue = new Array();
225    var currentQueue = null;
226    function registerImage(baseId, plotId, url)
227    {
228      if (!currentQueue) currentQueue = baseId;
229      var imageQueue = plotQueue[baseId];
230      if (!imageQueue)
231      {
232        imageQueue = new ImageQueue(baseId);
233        plotQueue[baseId] = imageQueue;
234      }
235      var imageId = baseId + '.' + plotId;
236      imageQueue.addImage(imageId, url);
237    }
238    function switchOverview(tabControlId, tabId)
239    {
240      currentQueue = tabId;
241      TabControl.setActiveTab(tabControlId, tabId);
242      loadNextImage();
243    }
244    function loadNextImage()
245    {
246      var imageQueue = plotQueue[currentQueue];
247      if (imageQueue) imageQueue.loadNextImage();
248    }
249    </script>
250    <style>
251    .plot
252    {
253      border: 1px solid #A0A0A0;
254      background-image: url('../../../images/plot_empty_400x300.png');
255      margin: 2px;
256    }
257    </style>
258  </base:head>
259  <base:body onload="loadNextImage()">
260    <p>
261    <p:path>
262      <p:pathelement title="Experiments" href="<%="../index.jsp?ID="+ID%>" />
263      <p:pathelement title="<%=HTML.encodeTags(experiment.getName())%>" 
264        href="<%="index.jsp?ID="+ID+"&experiment_id="+experimentId%>" />
265      <p:pathelement title="<%=HTML.encodeTags(bioAssaySet.getName())%>" />
266    </p:path>
267   
268    <t:tabcontrol id="view" active="<%=tabId%>" switch="switchTab" remember="false">
269    <t:tab id="properties" title="Properties">
270   
271    <tbl:toolbar
272      >
273      <tbl:button 
274        disabled="<%=writePermission ? false : true%>" 
275        image="edit.gif" 
276        onclick="editItem()" 
277        title="Edit&hellip;" 
278        tooltip="<%=writePermission ? "Edit this bioassay set" : "You do not have permission to edit this bioassay set"%>" 
279      />
280      <tbl:button 
281        disabled="<%=deletePermission ? false : true%>" 
282        image="delete.gif" 
283        onclick="deleteItem()" 
284        title="Delete"
285        visible="<%=!bioAssaySet.isRemoved()%>"
286        tooltip="<%=deletePermission ? "Delete this bioassay set" : "You do not have permission to delete this bioassay set"%>" 
287      />
288      <tbl:button 
289        disabled="<%=writePermission ? false : true%>" 
290        image="restore.gif" 
291        onclick="restoreItem()" 
292        title="Restore"
293        visible="<%=bioAssaySet.isRemoved()%>"
294        tooltip="<%=writePermission ? "Restore this bioassay set" : "You do not have permission to restore this bioassay set"%>" 
295      />
296      <tbl:button 
297        image="import.gif" 
298        onclick="runItemPlugin('ImportItem')" 
299        title="Import&hellip;" 
300        tooltip="Import data" 
301        visible="<%=pluginCount.containsKey(Plugin.MainType.IMPORT)%>"
302      />
303      <tbl:button 
304        image="export.gif" 
305        onclick="runItemPlugin('ExportItem')" 
306        title="Export&hellip;" 
307        tooltip="Export data" 
308        visible="<%=pluginCount.containsKey(Plugin.MainType.EXPORT)%>"
309      />
310      <tbl:button
311        image="plotter.gif"
312        onclick="<%="openPlotTool(" + itemId + ")"%>"
313        title="Plot tool&hellip;"
314        tooltip="A simple tool for generating plots"
315        visible="<%=hasDbSpots%>"
316      />
317      <tbl:button
318        image="explorer.png"
319        onclick="<%="openExperimentExplorer(" + itemId + ")"%>"
320        title="Experiment explorer"
321        tooltip="View the data reporter by reporter"
322        visible="<%=hasDbSpots%>"
323      />
324      <tbl:button
325        disabled="<%=!createPermission%>"
326        image="<%=createPermission ? "filter.gif" : "filter_disabled.gif"%>"
327        onclick="<%="filter(" + itemId +")"%>"
328        title="Filter bioassay set&hellip;"
329        tooltip="<%=createPermission ? 
330          "Create a new bioassay set by filtering this bioassayset" :
331          "You do not have permission analyze this experiment"%>"
332        visible="<%=pluginCount.containsKey(Plugin.MainType.ANALYZE)%>"
333      />
334      <tbl:button 
335        image="runplugin.gif" 
336        onclick="runItemPlugin('RunPlugin')"
337        title="Run plugin&hellip;" 
338        tooltip="Run a plugin" 
339        visible="<%=pluginCount.containsKey(Plugin.MainType.OTHER)%>"
340      />
341      <tbl:button 
342        disabled="<%=!createPermission%>"
343        image="<%=createPermission ? "runplugin.gif" : "runplugin_disabled.gif"%>" 
344        onclick="<%="runAnalysisPlugin(" + itemId + ")"%>"
345        title="Run analysis&hellip;" 
346        tooltip="<%=createPermission ? "Run an analysis plugin" : 
347          "You do not have permission to analyze this experiment"%>"
348        visible="<%=pluginCount.containsKey(Plugin.MainType.ANALYZE)%>"
349      />
350      <ext:render extensions="<%=toolbarInvoker%>" context="<%=jspContext%>" 
351        wrapper="<%=new PrefixSuffixRenderer(jspContext, "<td>", "</td>") %>"/>
352      <tbl:button
353        image="help.png"
354        onclick="<%="Main.openHelp('" + ID +"', 'bioassayset.view.properties')"%>"
355        title="Help&hellip;"
356        tooltip="Get help about this page"
357      />
358      </tbl:toolbar>
359    <div class="boxedbottom">
360      <div class="itemstatus">Permissions on this item: <i><%=PermissionUtil.getFullPermissionNames(bioAssaySet)%></i></div>
361      <%
362      if (bioAssaySet.isRemoved())
363      {
364        %>
365        <div class="itemstatus">
366          <base:icon image="deleted.gif" 
367            visible="<%=bioAssaySet.isRemoved()%>"> This item has been flagged for deletion<br></base:icon>
368        </div>
369        <%
370      }
371      %>
372     
373      <table width="100%">
374      <tr >
375      <td width="50%">
376        <h4>Bioassay set</h4>
377        <table class="form" cellspacing=0>
378        <tr>
379          <td class="prompt">Name</td>
380          <td><%=HTML.encodeTags(bioAssaySet.getName())%></td>
381        </tr>
382        <tr>
383          <td class="prompt">Experiment</td>
384          <td><%=Base.getLinkedName(ID, experiment, false, writePermission)%>
385          (<%=experiment.getRawDataType()%>)</td>
386        </tr>
387        <tr>
388          <td class="prompt">Intensity transformation</td>
389          <td><%=bioAssaySet.getIntensityTransform().toString()%></td>
390        </tr>
391        <tr>
392          <td class="prompt">Spots</td>
393          <td>db: <%=bioAssaySet.getNumSpots()%>; file: <%=bioAssaySet.getNumFileSpots()%></td>
394        </tr>
395        <tr>
396          <td class="prompt">Reporters</td>
397          <td>db: <%=bioAssaySet.getNumReporters()%>; file: <%=bioAssaySet.getNumFileReporters()%></td>
398        </tr>
399        <tr>
400          <td class="prompt">Description</td>
401          <td><%=HTML.niceFormat(bioAssaySet.getDescription())%></td>
402        </tr>
403        </table>
404       
405        <h4>Transformation &amp; job</h4>
406        <table class="form" cellspacing=0>
407        <tr>
408          <td class="prompt">Transformation</td>
409          <td><%=Base.getLinkedName(ID, transformation, false, 
410              transformation.hasPermission(Permission.WRITE))%></td>
411        </tr>
412        <tr>
413          <td class="prompt">Job</td>
414          <td><%=Base.getLinkedName(ID, job, !readJob, false)%></td>
415        </tr>
416        <tr >
417          <td class="prompt">Started</td>
418          <td>
419            <%=job == null ? "" : dateTimeFormatter.format(job.getStarted())%>
420          </td>
421        </tr>
422        <tr >
423          <td class="prompt">Ended</td>
424          <td>
425            <%=job == null ? "" : dateTimeFormatter.format(job.getEnded())%>
426          </td>
427        </tr>
428        <tr >
429          <td class="prompt">Server</td>
430          <td>
431            <%=job == null ? "" : HTML.encodeTags(job.getServer())%>
432          </td>
433        </tr>
434        <tr>
435          <td class="prompt">Description</td>
436          <td><%=HTML.niceFormat(transformation.getDescription())%></td>
437        </tr>
438        </table>
439      </td>
440      <td width="50%">
441        <h4>Plugin &amp; parameters</h4>
442        <table class="form" cellspacing=0>
443        <tr>
444          <td class="prompt">Plugin</td>
445          <td><%=Base.getLinkedName(ID, plugin, 
446              !readPlugin, plugin != null && plugin.hasPermission(Permission.WRITE))%></td>
447        </tr>
448        <tr>
449          <td class="prompt">Plugin configuration</td>
450          <td><%=Base.getLinkedName(ID, configuration, !readConfiguration, 
451            configuration != null && configuration.hasPermission(Permission.WRITE))%></td>
452        </tr>
453        <%
454        if (job != null)
455        {
456          for (String name : job.getParameterNames())
457          {
458            StringBuilder sb = new StringBuilder();
459            String displayValue = "";
460            String description = "";
461            try
462            {
463              ParameterInfo pi = job.getParameterInfo(name);
464              if (pi.getLabel() != null) name = HTML.encodeTags(pi.getLabel());
465              description = HTML.encodeTags(pi.getDescription());
466              List<?> values = pi.getValues();
467              int i = 0;
468              for (Object value : values)
469              {
470                if (value != null)
471                {
472                  if (i > 0) sb.append(", ");
473                  i++;
474                  if (value instanceof BasicItem)
475                  {
476                    BasicItem item = (BasicItem)value;
477                    String itemName = "";
478                    if (item instanceof File)
479                    {
480                      itemName = ((File)item).getPath().toString();
481                    }
482                    else if (item instanceof Nameable)
483                    {
484                      itemName = ((Nameable)item).getName();
485                    }
486                    else
487                    {
488                      itemName = item.toString();
489                    }
490                    sb.append(Base.getLink(ID, HTML.encodeTags(itemName), 
491                      item.getType(), item.getId(), item.hasPermission(Permission.WRITE)));
492                  }
493                  else if (value instanceof Date)
494                  {
495                    sb.append(dateFormatter.format((Date)value));
496                  }
497                  else
498                  {
499                    sb.append(HTML.encodeTags(value.toString()));
500                  }
501                }
502              }
503              displayValue = sb.toString();
504            }
505            catch (Throwable ex)
506            {
507              displayValue = "<i>ERROR: "+ex.getMessage()+"</i>";
508            }
509            %>
510            <tr>
511            <td class="prompt"><span title="<%=description%>"><%=name%></span></td>
512              <td>
513                <%=displayValue%>
514              </td>
515            </tr>
516            <%
517          }
518        }
519        %>
520        </table>
521
522      </td>
523      </tr>
524      </table>
525     
526      <jsp:include page="../../../common/datafiles/list_files.jsp">
527        <jsp:param name="item_type" value="<%=itemType.name()%>" />
528        <jsp:param name="item_id" value="<%=itemId%>" />
529        <jsp:param name="ID" value="<%=ID%>" />
530      </jsp:include>
531     
532      <jsp:include page="../../../common/anytoany/list_anytoany.jsp">
533        <jsp:param name="ID" value="<%=ID%>" />
534        <jsp:param name="item_type" value="<%=itemType.name()%>" />
535        <jsp:param name="item_id" value="<%=itemId%>" />
536        <jsp:param name="title" value="Other items related to this bioassay set" />
537      </jsp:include>
538     
539      <h4 class="docked">Analysis subtree</h4>
540      <jsp:include page="analysis_tree.jsp">
541        <jsp:param name="ID" value="<%=ID%>" />
542        <jsp:param name="experiment_id" value="<%=experimentId%>" />
543        <jsp:param name="item_id" value="<%=itemId%>" />
544      </jsp:include>
545      </div>
546      </t:tab>
547     
548      <t:tab id="annotations" title="Annotations" 
549        tooltip="View annotation values" clazz="white">
550        <jsp:include page="../../../common/annotations/list_annotations.jsp">
551          <jsp:param name="item_type" value="<%=itemType.name()%>" />
552          <jsp:param name="item_id" value="<%=itemId%>" />
553          <jsp:param name="ID" value="<%=ID%>" />
554        </jsp:include>
555      </t:tab>
556     
557      <t:tab id="bioassays" title="Bioassays" />
558     
559      <t:tab id="spotdata" title="Spot data" 
560        visible="<%=hasDbSpots%>" />
561     
562      <t:tab id="overviewplots" title="Overview plots" 
563        tooltip="Predefined plots for all bioassays in this bioassay set"
564        visible="<%=overviewPlotInvoker.getNumExtensions() > 0%>">
565        <%
566        if ("overviewplots".equals(tabId))
567        {
568          ActionIterator<OverviewPlotAction> plots = overviewPlotInvoker.iterate();
569          StringBuilder script = new StringBuilder();
570          %>
571          <t:tabcontrol id="overviewplots" switch="switchOverview">
572          <% 
573          while (plots.hasNext())
574          {
575            OverviewPlotAction action = plots.next();
576            String baseId = plots.getExtension().getId() + "." + action.getId();
577            %>
578            <t:tab 
579              tooltip="<%=action.getDescription() %>"
580              title="<%=action.getTitle()%>"
581              id="<%=baseId%>"
582              >
583              <%
584              for (PlotGenerator generator : action.getPlotGenerators())
585              {
586                String plotId = generator.getId();
587                script.append("registerImage('").append(baseId).append("','")
588                    .append(plotId).append("','")
589                    .append(HTML.javaScriptEncode(generator.getUrl())).append("');\n");
590                %><img id="<%=baseId + "." + plotId%>"
591                  class="plot"
592                  src="../../../images/transparent_pixel.gif"
593                  width="<%=generator.getWidth()%>"
594                  height="<%=generator.getHeight()%>"
595                  alt="<%=HTML.encodeTags(generator.getTitle())%>"
596                >&#8203;&#8203;<%
597              }
598              %>
599            </t:tab>
600            <%
601          }
602          %>
603          </t:tabcontrol>
604          <script language="JavaScript">
605          <%=script%>
606          </script>
607          <%
608        }
609        %>
610      </t:tab>
611      </t:tabcontrol>
612
613  </base:body>
614  </base:page>
615  <%
616}
617finally
618{
619  if (dc != null) dc.close();
620}
621
622%>
Note: See TracBrowser for help on using the repository browser.