source: trunk/www/views/formulas/edit_formula.jsp @ 3913

Last change on this file since 3913 was 3913, checked in by Nicklas Nordborg, 14 years ago

Fixes #778: Add expression to formula

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Id
File size: 17.0 KB
Line 
1<%-- $Id: edit_formula.jsp 3913 2007-11-06 09:42:09Z nicklas $
2  ------------------------------------------------------------------
3  Copyright (C) 2006 Jari Hakkinen, Nicklas Nordborg, Martin Svensson
4  Copyright (C) 2007 Nicklas Nordborg
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 2
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 this program; if not, write to the Free Software
21  Foundation, Inc., 59 Temple Place - Suite 330,
22  Boston, MA  02111-1307, USA.
23  ------------------------------------------------------------------
24
25
26  @author Nicklas
27  @version 2.0
28--%>
29<%@ page session="false"
30  import="net.sf.basedb.core.SessionControl"
31  import="net.sf.basedb.core.DbControl"
32  import="net.sf.basedb.core.Item"
33  import="net.sf.basedb.core.ItemContext"
34  import="net.sf.basedb.core.Permission"
35  import="net.sf.basedb.core.Formula"
36  import="net.sf.basedb.core.Coloring"
37  import="net.sf.basedb.core.RawDataType"
38  import="net.sf.basedb.core.RawDataTypes"
39  import="net.sf.basedb.core.RawDataProperty"
40  import="net.sf.basedb.core.Project"
41  import="net.sf.basedb.core.PermissionDeniedException"
42  import="net.sf.basedb.util.Values"
43  import="net.sf.basedb.clients.web.Base"
44  import="net.sf.basedb.clients.web.util.HTML"
45  import="java.util.List"
46%>
47<%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
48<%@ taglib prefix="t" uri="/WEB-INF/tab.tld" %>
49<%
50final Item itemType = Item.FORMULA;
51final SessionControl sc = Base.getExistingSessionControl(pageContext, true);
52final ItemContext cc = Base.getAndSetCurrentContext(sc, itemType, null, null);
53final int itemId = cc.getId();
54final String ID = sc.getId();
55final float scale = Base.getScale(sc);
56final DbControl dc = sc.newDbControl();
57try
58{
59  String title = null;
60  Formula formula = null;
61  Formula.Type currentType = null;
62  Formula.Parser currentParser = null;
63  Formula.AverageMethod currentAverageMethod = null;
64  RawDataType currentRawDataType = null;
65  RawDataType defaultRawDataType = null;
66  List<String> expressions = null;
67  Coloring coloring = null;
68
69  int activeProjectId = sc.getActiveProjectId();
70  if (activeProjectId > 0)
71  {
72    Project activeProject = Project.getById(dc, activeProjectId);
73    defaultRawDataType = activeProject.getDefaultRawDataType();
74  } 
75  if (itemId == 0)
76  {
77    title = "Create formula";
78    cc.removeObject("item");
79    String recentType = cc.getRecent("FormulaType", 0);
80    String filterType = cc.getPropertyValue("type");
81    if (filterType != null) currentType =  Formula.Type.fromValue(Values.getInt(filterType));
82    if (currentType == null && recentType != null) currentType = Formula.Type.valueOf(recentType);
83    if (currentType == null) currentType = Formula.Type.COLUMN_EXPRESSION;
84    currentParser = Formula.Parser.fromValue(Values.getInt(cc.getPropertyValue("parser"), 
85      Formula.Parser.JEP.getValue()));
86    currentAverageMethod = Formula.AverageMethod.fromValue(Values.getInt(cc.getPropertyValue("averageMethod"),
87      Formula.AverageMethod.ARITHMETIC_MEAN.getValue()));
88    currentRawDataType = RawDataTypes.getRawDataType(cc.getPropertyValue("rawDataType"));
89    if (currentRawDataType == null)
90    {
91      currentRawDataType = RawDataTypes.getRawDataType(cc.getRecent("RawDataType", 0));
92    }
93    coloring = new Coloring();
94    coloring.setUsingColors(Values.getBoolean(cc.getPropertyValue("coloring.usingColors")));
95    coloring.setLogarithmic(Values.getBoolean(cc.getPropertyValue("coloring.logarithmic")));
96    coloring.setMinValue(Values.getFloat(cc.getPropertyValue("coloring.minValue"), null));
97    coloring.setMidValue(Values.getFloat(cc.getPropertyValue("coloring.midValue"), null));
98    coloring.setMaxValue(Values.getFloat(cc.getPropertyValue("coloring.maxValue"), null));
99   
100    currentRawDataType = currentRawDataType != null ? currentRawDataType : defaultRawDataType;
101  }
102  else
103  {
104    formula = Formula.getById(dc, itemId);
105    currentParser = formula.getParser();
106    currentAverageMethod = formula.getAverageMethod();
107    currentType = formula.getFormulaType();
108    currentRawDataType = formula.getRawDataType();
109    expressions = formula.getFormulas();
110    coloring = formula.getColoring();
111    cc.setObject("item", formula);
112    title = "Edit formula -- " + HTML.encodeTags(formula.getName());
113  }
114  if (formula != null) formula.checkPermission(Permission.WRITE);
115 
116  final String clazz = "class=\"text\"";
117  final String requiredClazz = "class=\"text required\"";
118  %>
119  <base:page type="popup" title="<%=title%>">
120  <base:head scripts="tabcontrol.js" styles="tabcontrol.css">
121    <script language="JavaScript">
122    // Validate the "Formula" tab
123    function validateFormula()
124    {
125      var frm = document.forms['formula'];
126      if (Main.trimString(frm.name.value) == '')
127      {
128        alert("You must enter a name");
129        frm.name.focus();
130        return false;
131      }
132      var type = frm.type[frm.type.selectedIndex].value;
133      var numFormulas = frm.expressions.length;
134      var numChannels = frm.channels.value;
135      if (type == '<%=Formula.Type.INTENSITY_EXPRESSION.name()%>' || type == '<%=Formula.Type.INTENSITY_TRANSFORMATION.name()%>')
136      {
137        // One formula per channel required
138        if (numFormulas != numChannels)
139        {
140          alert('You must enter one formula for each channel for type = ' + frm.type[frm.type.selectedIndex].text);
141          return false;
142        }
143      }
144      else
145      {
146        // Only one formula can be specified
147        if (numFormulas != 1)
148        {
149          alert('You can only enter one formula for type = ' + frm.type[frm.type.selectedIndex].text);
150          return false;
151        }
152      }
153     
154      if (frm.use_colors.checked && !frm.use_colors.disabled)
155      {
156        var minValue = parseFloat(frm.min_value.value);
157        var midValue = parseFloat(frm.mid_value.value);
158        var maxValue = parseFloat(frm.max_value.value);
159        if (isNaN(minValue))
160        {
161          alert('No min value has been specified');
162          frm.min_value.focus();
163          return false;
164        }
165        if (isNaN(midValue))
166        {
167          alert('No mid value has been specified');
168          frm.mid_value.focus();
169          return false;
170        }
171        if (isNaN(maxValue))
172        {
173          alert('No max value has been specified');
174          frm.max_value.focus();
175          return false;
176        }
177        if (minValue > midValue)
178        {
179          alert('The min value (' + minValue + ') can\'t be greater than the mid value (' + midValue + ')');
180          return false;
181        }
182        if (midValue > maxValue)
183        {
184          alert('The mid (' + midValue + ') value can\'t be greater than the max value (' + maxValue + ')');
185          return false;
186        }
187      }
188      return true;
189    }
190
191    // Submit the form
192    function saveSettings()
193    {
194      var frm = document.forms['formula'];
195      if (TabControl.validateActiveTab('settings'))
196      {
197        for (var i = 0; i < frm.expressions.length; i++)
198        {
199          Forms.createHidden(frm, 'formulas', frm.expressions[i].text);
200        }
201        frm.channels.disabled = false; // Otherwise the channels info, isn't sent
202        frm.submit();
203      }
204    }
205   
206    function init()
207    {
208      <%
209      if (formula == null)
210      {
211        %>
212        var frm = document.forms['formula'];
213        frm.name.focus();
214        frm.name.select();
215        <%
216      }
217      %>
218      formulaTypeOnChange();
219    }
220    var rawDataTypes = new Array();
221    <%
222    for (RawDataType rdt : RawDataTypes.getRawDataTypes())
223    {
224      %>
225      rawDataTypes['<%=rdt.getId()%>'] = <%=rdt.getChannels()%>;
226      var a = new Array();
227      <%
228      for (RawDataProperty rp : rdt.getProperties())
229      {
230        %>
231        a['<%=rp.getName()%>'] = 1;
232        <%
233      }
234      %>
235      rawDataTypes['<%=rdt.getId()%>.properties'] = a;
236      <%
237    }
238    %>
239   
240    function rawDataTypeOnChange()
241    {
242      var frm = document.forms['formula'];
243      var rdt = frm.rawdatatype[frm.rawdatatype.selectedIndex].value;
244      if (rdt != '')
245      {
246        frm.channels.value = rawDataTypes[rdt];
247        frm.channels.disabled = true;
248        Main.addClass(frm.channels, 'disabled');
249        Main.removeClass(frm.channels, 'required');
250      }
251      else
252      {
253        frm.channels.disabled = false;
254        Main.removeClass(frm.channels, 'disabled');
255        Main.addClass(frm.channels, 'required');
256      }
257    }
258
259    var selectedExpressionIndex = -1;
260    function expressionsOnClick()
261    {
262      var frm = document.forms['formula'];
263      selectedExpressionIndex = frm.expressions.selectedIndex;
264      frm.expression.value = frm.expressions[selectedExpressionIndex].text;
265    }
266
267    function expressionOnBlur()
268    {
269      var frm = document.forms['formula'];
270      if (selectedExpressionIndex >= 0)
271      {
272        frm.expressions[selectedExpressionIndex].text = frm.expression.value;
273      }
274    }
275   
276    function removeOnClick()
277    {
278      var frm = document.forms['formula'];
279      if (selectedExpressionIndex >= 0)
280      {
281        frm.expressions[selectedExpressionIndex] = null;
282        selectedExpressionIndex = -1;
283      }
284    }
285   
286    function addOnClick()
287    {
288      var frm = document.forms['formula'];
289      if (frm.expression.value != '')
290      {
291        frm.expressions[frm.expressions.length] = new Option(frm.expression.value);
292        selectedExpressionIndex = frm.expressions.length - 1;
293        frm.expressions.selectedIndex = selectedExpressionIndex;
294      }
295    }
296   
297    function openExpressionBuilder()
298    {
299      var frm = document.forms['formula'];
300      var rdt = frm.rawdatatype[frm.rawdatatype.selectedIndex].value;
301      var formulaType = frm.type[frm.type.selectedIndex].value;
302      var channels = frm.channels.value;
303      var restrictions = formulaType == '<%=Formula.Type.COLUMN_RESTRICTION.name()%>';
304      Main.expressionBuilder('<%=ID%>', 'Expression', 'formula', 'expression', formulaType, rdt, channels, restrictions, null, 'setExpressionFromBuilder');
305    }
306 
307    function setExpressionFromBuilder(form, textarea, value)
308    {
309      var frm = document.forms['formula'];
310      frm[textarea].value = value;
311      if (frm.expressions.length == 0)
312      {
313        addOnClick();
314      }
315      else
316      {
317        expressionOnBlur();
318      }
319    }
320 
321    var useColors = new Array();
322    var supportsAverage = new Array();
323    <%
324    for (Formula.Type ft : Formula.Type.values())
325    {
326      %>
327      useColors['<%=ft.name()%>'] = <%=ft.canUseColoring()%>;
328      supportsAverage['<%=ft.name()%>'] = <%=ft.supportsAverage()%>;
329      <%
330    }
331    %>
332 
333    function useColorsOnClick()
334    {
335      var frm = document.forms['formula'];
336      var useColors = frm.use_colors.checked && !frm.use_colors.disabled;
337      frm.min_value.disabled = !useColors;
338      frm.mid_value.disabled = !useColors;
339      frm.max_value.disabled = !useColors;
340      frm.logarithmic.disabled = !useColors;
341      if (useColors)
342      {
343        Main.addClass(frm.min_value, 'required');
344        Main.addClass(frm.mid_value, 'required');
345        Main.addClass(frm.max_value, 'required');
346      }
347      else
348      {
349        Main.removeClass(frm.min_value, 'required');
350        Main.removeClass(frm.mid_value, 'required');
351        Main.removeClass(frm.max_value, 'required');
352      }
353    }
354   
355    function formulaTypeOnChange()
356    {
357      var frm = document.forms['formula'];
358      var formulaType = frm.type[frm.type.selectedIndex].value;
359      var use = useColors[formulaType];
360      frm.use_colors.disabled = !use;
361      useColorsOnClick();
362      var supportsAvg = supportsAverage[formulaType];
363      frm.averageMethod.disabled = !supportsAvg;
364      if (!supportsAvg) frm.averageMethod.selectedIndex = 0;
365    }
366    </script>
367  </base:head>
368  <base:body onload="init()">
369    <p>
370    <form action="index.jsp?ID=<%=ID%>" method="post" name="formula" onsubmit="return false;">
371    <input type="hidden" name="cmd" value="UpdateItem">
372
373    <h3 class="docked"><%=title%> <base:help tabcontrol="settings" /></h3>
374    <t:tabcontrol id="settings" contentstyle="<%="height: "+(int)(scale*380)+"px;"%>" 
375      position="bottom"  remember="<%=formula != null%>">
376    <t:tab id="info" title="Formula" validate="validateFormula()" helpid="formula.edit">
377      <table class="form" cellspacing=0>
378      <tr>
379        <td class="prompt">Name</td>
380        <td><input <%=requiredClazz%> type="text" name="name" 
381          value="<%=HTML.encodeTags(formula == null ? Values.getString(cc.getPropertyValue("name"), "New formula") : formula.getName())%>" 
382          size="40" maxlength="<%=Formula.MAX_NAME_LENGTH%>"></td>
383      </tr>
384      <tr>
385        <td class="prompt">Type</td>
386        <td>
387          <select name="type" class="required" onchange="formulaTypeOnChange()">
388          <%
389          for (Formula.Type type : Formula.Type.values())
390          {
391            String selected = type == currentType ? "selected" : "";
392            %>
393            <option value="<%=type.name()%>" <%=selected%>><%=HTML.encodeTags(type.toString())%>
394            <%
395          }
396          %>
397          </select>
398        </td>
399      </tr>
400      <tr>
401        <td class="prompt">Parser</td>
402        <td>
403          <select name="parser" class="required">
404          <%
405          for (Formula.Parser parser : Formula.Parser.values())
406          {
407            String selected = parser == currentParser ? "selected" : "";
408            %>
409            <option value="<%=parser.name()%>" <%=selected%>><%=HTML.encodeTags(parser.toString())%>
410            <%
411          }
412          %>
413          </select>
414        </td>
415      </tr>
416      <tr>
417        <td class="prompt">Raw data type</td>
418        <td>
419          <select name="rawdatatype" onchange="rawDataTypeOnChange()">
420          <option value="">- none -
421          <%
422          for (RawDataType rdt : RawDataTypes.getRawDataTypes())
423          {
424            String selected = rdt == currentRawDataType ? "selected" : "";
425            %>
426            <option value="<%=rdt.getId()%>" <%=selected%>><%=HTML.encodeTags(rdt.getName())%>
427            <%
428          }
429          %>
430          </select>
431        </td>
432      </tr>
433      <tr>
434        <td class="prompt">Channels</td>
435        <td><input <%=currentRawDataType != null ? "class=\"text disabled\" disabled" : requiredClazz%> type="text" name="channels" 
436          value="<%=formula == null ? (currentRawDataType == null ? Values.getInt(cc.getPropertyValue("channels")) : currentRawDataType.getChannels()) : formula.getChannels()%>" 
437          size="12" maxlength="10" onkeypress="return Numbers.integerOnly(event)"
438          ></td>
439      </tr>
440      <tr valign="top">
441        <td class="prompt">Expressions</td>
442        <td>
443          <table border="0" cellspacing="0" cellpadding="2">
444          <tr>
445            <td>
446            <select name="expressions" size="3" style="width: 26em;"
447              onchange="expressionsOnClick()" multiple class="required">
448              <%
449              if (expressions != null)
450              {
451                for (String expression : expressions)
452                {
453                  %>
454                  <option><%=HTML.encodeTags(expression)%>
455                  <%
456                }
457              }
458              %>
459            </select>
460            </td>
461            <td><base:button onclick="removeOnClick()" title="Remove" /></td>
462          </tr>
463          <tr>
464          <td>
465            <input type="text" name="expression" class="text" style="width: 26em;"
466              maxlength="<%=Formula.MAX_FORMULA_LENGTH%>"
467              onblur="expressionOnBlur()">
468          </td>
469          <td>
470            <base:button onclick="addOnClick()" title="Add" />
471          </td>
472          <td>
473            <base:button onclick="openExpressionBuilder()" 
474              image="expression_builder.gif"
475              title="Expression builder&hellip;" />
476          </td>
477          </table>
478        </td>
479      </tr>
480      <tr>
481        <td class="prompt">Avg. method</td>
482        <td>
483          <select name="averageMethod" class="required">
484          <%
485          for (Formula.AverageMethod method : Formula.AverageMethod.values())
486          {
487            String selected = method == currentAverageMethod ? "selected" : "";
488            %>
489            <option value="<%=method.name()%>" <%=selected%>><%=HTML.encodeTags(method.toString())%>
490            <%
491          }
492          %>
493          </select>
494        </td>
495      </tr>
496     
497      <tr>
498        <td class="prompt">Use colors</td>
499        <td>
500          <input type="checkbox" name="use_colors" value="1" 
501            <%=coloring.isUsingColors() ? "checked" : "" %>
502            onclick="useColorsOnClick()">
503         
504          <b>Min value</b>
505          <input type="text" class="text" name="min_value"
506             value="<%=Values.formatNumber(coloring.getMinValue(), -1)%>"
507             size="6" maxlength="6"
508             onkeypress="return Numbers.numberOnly(event)"
509             >
510          <b>Mid value</b>
511          <input type="text" class="text" name="mid_value"
512             value="<%=Values.formatNumber(coloring.getMidValue(), -1)%>"
513             size="6" maxlength="6"
514             onkeypress="return Numbers.numberOnly(event)"
515             >
516          <b>Max value</b>
517          <input type="text" class="text" name="max_value"
518             value="<%=Values.formatNumber(coloring.getMaxValue(), -1)%>"
519             size="6" maxlength="6"
520             onkeypress="return Numbers.numberOnly(event)"
521             >
522             <br>
523          <input type="checkbox" name="logarithmic" value="1" 
524            <%=coloring.isLogarithmic() ? "checked" : "" %>>
525          <b>Logarithmic</b>
526        </td>
527      </tr>
528
529      <tr valign=top>
530        <td class="prompt">Description</td>
531        <td nowrap>
532          <textarea <%=clazz%> rows="4" cols="40" name="description" wrap="virtual"
533            ><%=HTML.encodeTags(formula == null ? cc.getPropertyValue("description") : formula.getDescription())%></textarea>
534          <a href="javascript:Main.zoom('Description', 'formula', 'description')"
535            title="Edit in larger window"><base:icon image="zoom.gif" /></a>
536        </td>
537      </tr>
538      </table>
539      <div align=right>&nbsp;<i><base:icon image="required.gif" /> = required information</i></div>
540    </t:tab>
541    </t:tabcontrol>
542
543    <table align="center">
544    <tr>
545      <td width="50%"><base:button onclick="saveSettings()" title="Save" /></td>
546      <td width="50%"><base:button onclick="window.close()" title="Cancel" /></td>
547    </tr>
548    </table>
549    </form>
550  </base:body>
551  </base:page>
552  <%
553}
554finally
555{
556  if (dc != null) dc.close();
557}
558%>
Note: See TracBrowser for help on using the repository browser.