diff --git a/components/tools/OmeroWeb/omeroweb/webclient/controller/container.py b/components/tools/OmeroWeb/omeroweb/webclient/controller/container.py index 585e2c0515c..8a53ead99f7 100755 --- a/components/tools/OmeroWeb/omeroweb/webclient/controller/container.py +++ b/components/tools/OmeroWeb/omeroweb/webclient/controller/container.py @@ -177,6 +177,29 @@ def getPlateId(self): elif self.acquisition: return self.acquisition._obj.plate.id.val + + def listFigureScripts(self, objDict=None): + """ + This configures all the Figure Scripts, setting their enabled status given the + currently selected object (self.image etc) or batch objects (uses objDict). + """ + figureScripts = [] + # id is used in url and is mapped to full script path by views.figure_script() + splitView = {'id': 'SplitView', 'name':'Split View Figure', 'enabled': False, + 'tooltip': "Create a figure of images, splitting their channels into separate views"} + # Split View Figure is enabled if we have at least one image with SizeC > 1 + if self.image: + splitView['enabled'] = (self.image.getSizeC() > 1) + elif objDict is not None: + if 'image' in objDict: + for i in objDict['image']: + if i.getSizeC() > 1: + splitView['enabled'] = True + break + figureScripts.append(splitView) + return figureScripts + + def openAstexViewerCompatible(self): """ Is the image suitable to be viewed with the Volume viewer 'Open Astex Viewer' applet? diff --git a/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/css/dusty.css b/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/css/dusty.css index 74e7619c6fa..d84644a15b6 100755 --- a/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/css/dusty.css +++ b/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/css/dusty.css @@ -136,6 +136,7 @@ button::-moz-focus-inner { .btn_group {background: url(../../webgateway/img/icon_add_group.png )center center no-repeat;} .btn_delete {background: url(../../webgateway/img/icon_delete.png )center center no-repeat;} .btn_edit {background: url(../../webgateway/img/icon_edit.png )center center no-repeat;} + .btn_figscripts {background: url(../../webgateway/img/icon_figure_scripts.png) center center no-repeat;} .btn_fspath {background: url(../../webgateway/img/icon_fs_path.png )center center no-repeat;} .btn_link {background: url(../../webgateway/img/icon_link.png )center center no-repeat;} @@ -163,7 +164,7 @@ button::-moz-focus-inner { display:block; } - #general_tab .btn_download span { + .toolbar_dropdown .btn span { width:20px; height:18px; display:block; @@ -173,18 +174,19 @@ button::-moz-focus-inner { background: url(../../webgateway/img/icon_download2.png) center center no-repeat; } - #download_dropdown .dropdown { - right: 0px; - left: auto; - } - #download_dropdown { + .toolbar_dropdown { float:right; margin-left: 5px; + position: relative; + } + .toolbar_dropdown .dropdown { + right: -35px; + left: auto; } - #download_dropdown .dropdown:before { + .toolbar_dropdown .dropdown:before { left: 68% !important; } - #download_dropdown ul a { + .toolbar_dropdown ul a { background: none; font-size: 80%; } @@ -406,7 +408,7 @@ button::-moz-focus-inner { } .btn_text span { - padding:6px 10px !important; + padding:3px 7px !important; } @@ -487,7 +489,7 @@ button::-moz-focus-inner { width:12px; height:12px; position:absolute; - z-index:99; + z-index:90; right:5px; top:5px; -webkit-border-radius:20px; diff --git a/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/css/layout.css b/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/css/layout.css index 653fae84879..6d9579e0295 100755 --- a/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/css/layout.css +++ b/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/css/layout.css @@ -534,7 +534,7 @@ /* Right Inner Content */ .right_tab_inner { - padding:15px; + padding:10px 15px; overflow: auto; top:6px ;bottom:0px; left:0px; right:0px; position: absolute; @@ -549,7 +549,7 @@ /* Seperator */ hr { - margin:15px 0; + margin:10px 0; display:block; border:none; border-bottom: solid 1px rgba(255,255,255,.8); @@ -588,7 +588,7 @@ .data_heading { - margin-bottom:20px; + margin-bottom:15px; border-bottom:solid 1px hsl(210,10%,90%); overflow:hidden; -webkit-box-shadow:0 1px 0 rgba(255,255,255,.5); @@ -597,7 +597,7 @@ -moz-box-shadow:0 1px 0 rgba(255,255,255,.5); /* FF3.5+ */ box-shadow:0 1px 0 rgba(255,255,255,.5); /* Opera 10.5, IE 9.0 */ - padding:10px 0; + padding:10px 0 5px 0; } @@ -2284,7 +2284,22 @@ width: 250px; } +/* Figure scripts dialog */ +.rowDragHandle { + float: left; + visibility: hidden; + position: relative; + left: -5px; + width: 11px; + height: 30px; + border-radius: 4px; + cursor: pointer; + background:#ddd url(../image/drag_handle_arrows_up-down.png) no-repeat center center; +} +tr.figImageData:hover .rowDragHandle { + visibility: visible; +} diff --git a/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/image/drag_handle_arrows_up-down.png b/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/image/drag_handle_arrows_up-down.png new file mode 100644 index 00000000000..e72d9a1c064 Binary files /dev/null and b/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/image/drag_handle_arrows_up-down.png differ diff --git a/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/javascript/ome.split_view_figure.js b/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/javascript/ome.split_view_figure.js new file mode 100644 index 00000000000..4067854c9e5 --- /dev/null +++ b/components/tools/OmeroWeb/omeroweb/webclient/static/webclient/javascript/ome.split_view_figure.js @@ -0,0 +1,313 @@ +// +// Copyright (C) 2013 University of Dundee & Open Microscopy Environment. +// All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// + +$(document).ready(function() { + OME.setupAjaxError("{% url fsend %}"); // just in case! + + $('#script_form').ajaxForm({ + success: function(data) { + window.opener.OME.showActivities(); + self.close(); + } + }); + + + // Basically what we're doing here is supplementing the form fields + // generated from the script itself to make a nier UI. + // We use these controls to update the paramter fields themselves, + // as well as updating the Figure preview. + + $("#enableScalebar").click(function(){ + var enabled = $(this).is(":checked"); + if (enabled) { + $("input[name=Scalebar]").removeAttr("disabled").focus(); + } else { + $("input[name=Scalebar]").attr("disabled", "disabled"); + } + }); + + var $channelNamesMap = $("#channelNamesMap"), + $figure_table = $("#figure_table"), + $columnNames = $(".split_column .channel_name", $figure_table), + $mergedNames = $("div.merged_name", $figure_table), + $splitIndexes = $("input[name='Split_Indexes']"); + + var updateChannelNames = function() { + // Update Channel-Names map index:Name + var activeCs = [], + cNames = []; + $("#split_channels input[type=checkbox]").each(function(i) { + var cName = $('input[type=text]', $(this).parent()).val(), + idx = parseInt( $(this).attr('name'), 10 ); + cNames.push(cName); + if ($(this).is(":checked")) { + activeCs.push(idx); + } + }); + $('input[name*=Channel_Names_value]', $channelNamesMap).each(function(c){ + $(this).val( cNames[c] ); + }); + // Update Split Indexes + $splitIndexes.val(activeCs.join(",")); + // Update Figure - channels on/off + $figure_table.find('tr').each(function(){ + $(this).find('td.split_column').each(function(c) { + if (activeCs.indexOf(c) > -1) { + $(this).show(); + } else { + $(this).hide(); + } + }); + }); + // Update Figure - channel Names + $columnNames.each(function(i){ // Column names + $(this).text(cNames[i]); + }); + $mergedNames.each(function(i){ // Merged names + $(this).text(cNames[i]); + }); + + }; + // Add / Remove Channels + $("#split_channels input[type=checkbox]").click(updateChannelNames); + // Renaming Channels + $("#split_channels input[type=text]").keyup(updateChannelNames); + + var $mergecColoursMap = $("#mergedColoursMap"); + var updateMergedChannels = function() { + // Update Merged-Colours map index:colourInt + $mergecColoursMap.empty(); + var mergedCs = [], + mergedColurs = []; + $("#merged_channels input[type=checkbox]:checked").each(function(i){ + var colourInt = $(this).attr('value'), + idx = parseInt( $(this).attr('name'), 10 ), + html = "" + + ""; + mergedCs.push(idx+1); // Use 1-based Channel idx for rendering + $(html).appendTo($mergecColoursMap); + }); + // Update url of merged panels in Figure + $(".merged_column img").each(function(){ + // remember original src + var $this = $(this); + if (typeof $this.data('src') === 'undefined') { + $this.data('src', $this.attr('src')); + } + var newSrc = $this.data('src') + "?c=" + mergedCs.join(","); + $this.attr('src', newSrc); + }); + // Merged Channel names + $mergedNames.each(function(i) { + if (mergedCs.indexOf(i+1) > -1) { + $(this).show(); + } else { + $(this).hide(); + } + }); + + }; + // When merged channels are toggled + $("#merged_channels input[type=checkbox]").click(function() { + updateMergedChannels(); + updateGrey(); + }); + + // Used to make sure we don't have white labels (on white background!) + var checkNotWhite = function(cssColour) { + if (cssColour === "rgb(255, 255, 255)") { + cssColour = "rgb(0,0,0)"; + } + return cssColour; + }; + // checkNotWhite for each of the mergedNames + $mergedNames.each(function(){ + var $mn = $(this); + $mn.css('color', checkNotWhite($mn.css('color'))); + }); + + var $splitPanelsGrey = $("input[name=Split_Panels_Grey]"); + var updateGrey = function() { + // Split Channels grey if 'splitPanelsGrey' OR channel is not merged + var grey = $splitPanelsGrey.is(":checked"), + mergedCs = []; + $("#merged_channels input[type=checkbox]:checked").each(function(i){ + mergedCs.push( parseInt( $(this).attr('name'), 10 )); + }); + $columnNames.each(function(i){ + var $this = $(this); + // Note the original color if we haven't done so already + if (typeof $this.data('color') === 'undefined') { + $this.data('color', checkNotWhite($this.css('color'))); + } + // Apply color or black to column Names + if (grey && mergedCs.indexOf(i) > -1) { + $this.css('color', $this.data('color')); + } else { + $this.css('color', 'rgb(0,0,0)'); + } + }); + // Update url of split panels in Figure + $(".split_column img").each(function(){ + // remember original src + var $this = $(this), + colIdx = parseInt($this.attr("colIdx"), 10), + chGrey = (grey || (mergedCs.indexOf(colIdx) === -1)), + flag = chGrey ? "g" : "c"; + if (typeof $this.data('src') === 'undefined') { + $this.data('src', $this.attr('src')); + } + var newSrc = $this.data('src') + "&m=" + flag; + $this.attr('src', newSrc); + }); + }; + // Update grey on checkbox click + $splitPanelsGrey.click(updateGrey); + + // Merged names + $("input[name=Merged_Names]").click(function(){ + if ( $(this).is(":checked") ) { + $("#merged_label").hide(); + $("#merged_names").show(); + } else { + $("#merged_label").show(); + $("#merged_names").hide(); + } + }); + + + // Z selection. + // NB: We disable Z-projection by clearing the zStart and zEnd fields. + var $zRangeSlider = $("#zRangeSlider"), + $zProjectionControls = $("#zProjectionControls"), + $zStart = $("input[name=Z_Start]"), + $zEnd = $("input[name=Z_End]"), + zMin = parseInt($zStart.val(), 10), + zMax = parseInt($zEnd.val(), 10), + $algorithm = $("select[name=Algorithm]"), + $stepping = $("input[name=Stepping]"); + $zRangeSlider.slider({ + range: true, + min: zMin, + max: zMax, + values: [ zMin, zMax ], + slide: function( event, ui ) { + $zStart.val(ui.values[ 0 ]); + $zEnd.val(ui.values[ 1 ]); + } + }).slider( "disable" ); // enable if user chooses zProjection + $("input[name=zProjection]").click(function(){ + if($(this).attr('value') === "z_projection"){ + $zRangeSlider.slider( "enable" ); + $zProjectionControls.show(); + $zStart.removeAttr("disabled"); + $zEnd.removeAttr("disabled"); + $algorithm.removeAttr("disabled"); + $stepping.removeAttr("disabled"); + } else { + $zProjectionControls.hide(); + $zRangeSlider.slider( "disable" ); + $zStart.attr("disabled", "disabled"); + $zEnd.attr("disabled", "disabled"); + $algorithm.attr("disabled", "disabled"); + $stepping.attr("disabled", "disabled"); + } + }); + // Don't allow users to type values here + $zStart.keydown(function(){ return false; }); + $zEnd.keydown(function(){ return false; }); + + + // Image Labels + var $Image_Labels = $("select[name=Image_Labels]"), + $rowLabels = $(".rowLabel>div"), + $imgName = $("div.imgName"), + $imgTags = $("div.imgTags"), + $imgDatasets = $("div.imgDatasets"); + $Image_Labels.change(function(){ + var labels = $(this).val(); + $rowLabels.hide(); // hide all then show one... + if (labels == "Image Name") { + $imgName.show(); + } else if (labels == "Datasets") { + $imgDatasets.show(); + } else if (labels == "Tags") { + $imgTags.show(); + } + updateColWidths(); + }); + + + // Drag and Drop to re-order rows + $('table tbody').sortable({ + disabled: false, + items: 'tr.figImageData', + handle: '.rowDragHandle', + opacity: 0.7, + axis: 'y', + forceHelperSize: true, + update: function( e, ui ) { + var sortedIds = [] + $(".figImageData").each(function(){ + sortedIds.push($(this).attr('data-imageId') ); + }); + $("input[name=IDs]").val(sortedIds.join(",")); + } + }); + // set widths, so that while rows are drag-n-dropped, widths stay the same + var updateColWidths = function() { + $(".figImageData>td") + .removeAttr('width') // clear any previous setting + .each(function(){ + var $td = $(this); + $td.attr('width', $td.width()); + }); + } + + // Lets sync everything to start with: + updateChannelNames(); + updateMergedChannels(); + updateGrey(); + updateColWidths(); + + + // Bonus feature - Zoom the preview thumbs with slider + // Make a list of styles (for quick access on zoom) + var img_panel_styles = []; + $(".img_panel").each(function(){ + img_panel_styles.push(this.style); + }); + var setImgSize = function(size) { + var i, l = img_panel_styles.length; + for (i=0; i. +// + /*global OME:true */ if (typeof OME === "undefined") { OME = {}; @@ -283,6 +301,36 @@ OME.deleteItem = function(event, domClass, url) { return false; }; +// More code that is shared between metadata_general and batch_annotate panels +// Called when panel loaded. Does exactly what it says on the tin. +OME.initToolbarDropdowns = function() { + // -- Toolbar buttons - show/hide dropdown options -- + $(".toolbar_dropdown ul").css('visibility', 'hidden'); + // show on click + var $toolbar_dropdownlists = $(".toolbar_dropdown ul"); + $(".toolbar_dropdown button").click(function(e) { + // hide any other lists that might be showing... + $toolbar_dropdownlists.css('visibility', 'hidden'); + // then show this one... + $("ul", $(this).parent()).css('visibility', 'visible'); + e.preventDefault(); + return false; + }); + // on hover-out, hide drop-down menus + $toolbar_dropdownlists.hover(function(){}, function(){ + $(this).css('visibility', 'hidden'); + }); + + // For Figure scripts, we need a popup: + $("#figScriptList li a").click(function(event){ + if (!$(this).parent().hasClass("disabled")) { + OME.openScriptWindow(event, 800, 600); + } + event.preventDefault(); + return false; + }); +}; + jQuery.fn.tooltip_init = function() { $(this).tooltip({ bodyHandler: function() { diff --git a/components/tools/OmeroWeb/omeroweb/webclient/templates/webclient/annotations/batch_annotate.html b/components/tools/OmeroWeb/omeroweb/webclient/templates/webclient/annotations/batch_annotate.html index ead6c1872c1..5c4abe9fadd 100644 --- a/components/tools/OmeroWeb/omeroweb/webclient/templates/webclient/annotations/batch_annotate.html +++ b/components/tools/OmeroWeb/omeroweb/webclient/templates/webclient/annotations/batch_annotate.html @@ -242,6 +242,9 @@ var url = $(this).attr('href'); OME.deleteItem(event, "file_ann_wrapper", url); }); + + + OME.initToolbarDropdowns(); }); @@ -261,7 +264,7 @@ -

+

Annotate {{ obj_labels|length }} objects: @@ -278,16 +281,28 @@

{% endfor %} +

+ +
-

+ + {% include "webclient/annotations/includes/figure_scripts_menu.html" %} + + + +
diff --git a/components/tools/OmeroWeb/omeroweb/webclient/templates/webclient/annotations/includes/figure_scripts_menu.html b/components/tools/OmeroWeb/omeroweb/webclient/templates/webclient/annotations/includes/figure_scripts_menu.html new file mode 100644 index 00000000000..728670631fa --- /dev/null +++ b/components/tools/OmeroWeb/omeroweb/webclient/templates/webclient/annotations/includes/figure_scripts_menu.html @@ -0,0 +1,36 @@ +{% comment %} + +{% endcomment %} + + +
+ + +
\ No newline at end of file diff --git a/components/tools/OmeroWeb/omeroweb/webclient/templates/webclient/annotations/includes/toolbar.html b/components/tools/OmeroWeb/omeroweb/webclient/templates/webclient/annotations/includes/toolbar.html new file mode 100644 index 00000000000..b60edb888ab --- /dev/null +++ b/components/tools/OmeroWeb/omeroweb/webclient/templates/webclient/annotations/includes/toolbar.html @@ -0,0 +1,70 @@ +{% comment %} + +{% endcomment %} + + +
+ + + + + + + {% if manager.image %} + +
+ + +
+ + {% if manager.image.showOriginalFilePaths %} + + + {% endif %} + + {% endif %} + + + + {% include "webclient/annotations/includes/figure_scripts_menu.html" %} + +
+
\ No newline at end of file diff --git a/components/tools/OmeroWeb/omeroweb/webclient/templates/webclient/annotations/metadata_general.html b/components/tools/OmeroWeb/omeroweb/webclient/templates/webclient/annotations/metadata_general.html index 877128ff962..75f1312815f 100644 --- a/components/tools/OmeroWeb/omeroweb/webclient/templates/webclient/annotations/metadata_general.html +++ b/components/tools/OmeroWeb/omeroweb/webclient/templates/webclient/annotations/metadata_general.html @@ -285,18 +285,8 @@ }); - // -- Download options -- - $("#download_dropdown ul").css('visibility', 'hidden'); - // show on click - $("#show_download_dropdown").click(function(e) { - $("ul", $(this).parent()).css('visibility', 'visible'); - e.preventDefault(); - return false; - }); - // on hover-out, hide drop-down menus - $("#download_dropdown ul").hover(function(){}, function(){ - $(this).css('visibility', 'hidden'); - }); + // We do this here and in batch_annotate panel + OME.initToolbarDropdowns(); // Handle Download actions $("#create-ometiff").click(function(e){ @@ -448,54 +438,32 @@ {% if manager.image %} + {% include "webclient/annotations/includes/toolbar.html" %} + {% with obj=manager.image nameText=manager.image.name %} {% include "webclient/annotations/includes/name.html" %} {% endwith %} - -
-

- Image ID: {{ manager.image.id }} + +
+ +

+ {{ manager.obj_type }} ID: {{ manager.obj_id }}

- - - - - - - - - {% if manager.image.showOriginalFilePaths %} - - - {% endif %} -
{% if manager.image.showOriginalFilePaths %} @@ -511,16 +479,10 @@

- - + {% if manager.openAstexViewerCompatible %} -
- +
@@ -562,23 +524,19 @@

{% else %} {% if manager.dataset %} + {% include "webclient/annotations/includes/toolbar.html" %} + {% with obj=manager.dataset nameText=manager.dataset.name %} {% include "webclient/annotations/includes/name.html" %} {% endwith %} -

- Dataset ID: {{ manager.dataset.id }} - - - -

+ +

+ {{ manager.obj_type }} ID: {{ manager.obj_id }} +

+
@@ -599,22 +557,18 @@

{% else %} {% if manager.project %} + {% include "webclient/annotations/includes/toolbar.html" %} + {% with obj=manager.project nameText=manager.project.name %} {% include "webclient/annotations/includes/name.html" %} {% endwith %} +

- Project ID: {{ manager.project.id }} - - - -

+ {{ manager.obj_type }} ID: {{ manager.obj_id }} + +
@@ -638,29 +592,29 @@

{% if manager.well %} - + {% include "webclient/annotations/includes/toolbar.html" %} + + {% with obj=manager.well.getWellSample.image nameText=manager.well.getWellSample.image.name %} {% include "webclient/annotations/includes/name.html" %} {% endwith %} -

- Image ID: {{ manager.well.getWellSample.image.id }} Well ID: {{ manager.well.id }} - - - + + +

+ Image ID: {{ manager.well.getWellSample.image.id }} + Well ID: {{ manager.well.id }}

- +
+
@@ -676,11 +630,14 @@

{% else %} {% if manager.acquisition %} + {% include "webclient/annotations/includes/toolbar.html" %} + {% with obj=manager.acquisition nameText=manager.acquisition.name %} {% include "webclient/annotations/includes/name.html" %} {% endwith %} +

Plate Run ID: {{ manager.acquisition.id }} @@ -692,7 +649,7 @@

- +
@@ -713,21 +670,16 @@

{% else %} {% if manager.plate %} + {% include "webclient/annotations/includes/toolbar.html" %} + {% with obj=manager.plate nameText=manager.plate.name %} {% include "webclient/annotations/includes/name.html" %} {% endwith %} +

- Plate ID: {{ manager.plate.id }} - - - + {{ manager.obj_type }} ID: {{ manager.obj_id }}


@@ -757,21 +709,15 @@

{% else %} {% if manager.screen %} + {% include "webclient/annotations/includes/toolbar.html" %} + {% with obj=manager.screen nameText=manager.screen.name %} {% include "webclient/annotations/includes/name.html" %} {% endwith %}

- Screen ID: {{ manager.screen.id }} - - - + {{ manager.obj_type }} ID: {{ manager.obj_id }}


@@ -1047,6 +993,10 @@

Contained in Datasets

{% if manager.tag %} + + + {% include "webclient/annotations/includes/toolbar.html" %} +
@@ -1054,17 +1004,8 @@

Contained in Datasets

{% include "webclient/annotations/includes/name.html" %} {% endwith %} -

- Tag ID: {{ manager.tag.id }} - - - -

+ +
diff --git a/components/tools/OmeroWeb/omeroweb/webclient/templates/webclient/base/includes/script_launch_head.html b/components/tools/OmeroWeb/omeroweb/webclient/templates/webclient/base/includes/script_launch_head.html index b8b0fd6a816..68e300a4d97 100644 --- a/components/tools/OmeroWeb/omeroweb/webclient/templates/webclient/base/includes/script_launch_head.html +++ b/components/tools/OmeroWeb/omeroweb/webclient/templates/webclient/base/includes/script_launch_head.html @@ -20,17 +20,8 @@ {% endblock %} diff --git a/components/tools/OmeroWeb/omeroweb/webclient/templates/webclient/scripts/split_view_figure.html b/components/tools/OmeroWeb/omeroweb/webclient/templates/webclient/scripts/split_view_figure.html new file mode 100644 index 00000000000..d9d09f7d372 --- /dev/null +++ b/components/tools/OmeroWeb/omeroweb/webclient/templates/webclient/scripts/split_view_figure.html @@ -0,0 +1,401 @@ +{% extends "webgateway/base/base_header.html" %} +{% load i18n %} + +{% comment %} + +{% endcomment %} + +{% comment %} + +{% endcomment %} + +{% block title %} + Create Split View Figure +{% endblock %} + + + +{% block script %} + {{ block.super }} + {% include "webgateway/base/includes/script_src_jquery.html" %} + {% include "webgateway/base/includes/script_src_popup.html" %} + {% include "webgateway/base/includes/jquery-ui.html" %} + + + + + + + +{% endblock %} + + +{% block middle_header_left %} + +{% endblock %} + + +{% block content %} + + +
+ +
+ +
+ +

Create Split View Figure

+ +
+ + + + + Figure Name: + + + + + Format: + + + +
+ + + Show Scalebar: + + Length (microns): + + + + + Overlay Colour: + + + + + +
+ + + Panel Width: + + + + + Panel Height: + + + + +
+ Z section: Last Viewed: + + Z Projection: + + + + +
+ + +
+ + +
+ + Channel Names: +
+ {% for c in channels %} + + + {% endfor %} +
+ +
+ Split Indexes: + +
+ + Merged Colours +
+ {% for c in channels %} + + + {% endfor %} +
+
+ +
+ + + + + + + + + + + + {% for c in channels %} + + {% endfor %} + + +
+
+ Split Panels Grey: + +
+
+
+ Merged Names: +
+
+ + +
+ + +
+
+ + + {% for c in channels %} + + {% endfor %} + +
+
+ +
+
+
+ + + + +
+ + + + + + +
+
+ + + + {% for c in channels %} + + {% endfor %} + + + + {% for imgData in imgDict %} + + + + {% for ch in channels %} + + {% endfor %} + + + {% endfor %} +
+ + {{ c.getLabel }} + + + {% for c in channels %} +
{{ c.getLabel }}
+ {% endfor %} +
+
+
+
+ {{ imgData.name }} +
+ + +
+
+ +
+
+
+ +
+
+
+
+ +
+{% endblock %} diff --git a/components/tools/OmeroWeb/omeroweb/webclient/urls.py b/components/tools/OmeroWeb/omeroweb/webclient/urls.py index ce729f403c1..a3fd59a5812 100755 --- a/components/tools/OmeroWeb/omeroweb/webclient/urls.py +++ b/components/tools/OmeroWeb/omeroweb/webclient/urls.py @@ -132,6 +132,8 @@ url( r'^script_ui/(?P[0-9]+)/$', views.script_ui, name='script_ui' ), # shows a form for running a script url( r'^script_run/(?P[0-9]+)/$', views.script_run, name='script_run' ), # runs the script - parameters in POST url( r'^get_original_file/(?:(?P[0-9]+)/)?$', views.get_original_file, name="get_original_file"), # for stderr, stdout etc + url( r'^figure_script/(?P((?i)SplitView|RoiSplit))/$', + views.figure_script, name='figure_script' ), # shows a form for running a script # ome_tiff_script: generate OME-TIFF and attach to image (use script service). Must be POST url( r'^ome_tiff_script/(?P[0-9]+)/$', views.ome_tiff_script, name='ome_tiff_script' ), diff --git a/components/tools/OmeroWeb/omeroweb/webclient/views.py b/components/tools/OmeroWeb/omeroweb/webclient/views.py index 2108e90343e..691ab645d9c 100755 --- a/components/tools/OmeroWeb/omeroweb/webclient/views.py +++ b/components/tools/OmeroWeb/omeroweb/webclient/views.py @@ -818,6 +818,7 @@ def load_metadata_details(request, c_type, c_id, conn=None, share_id=None, **kwa if share_id is None: template = "webclient/annotations/metadata_general.html" manager.annotationList() + figScripts = manager.listFigureScripts() form_comment = CommentAnnotationForm(initial=initial) else: template = "webclient/annotations/annotations_share.html" @@ -825,7 +826,8 @@ def load_metadata_details(request, c_type, c_id, conn=None, share_id=None, **kwa if c_type in ("tag"): context = {'manager':manager} else: - context = {'manager':manager, 'form_comment':form_comment, 'index':index, 'share_id':share_id} + context = {'manager':manager, 'form_comment':form_comment, 'index':index, + 'share_id':share_id, 'figScripts':figScripts} context['template'] = template context['webclient_path'] = request.build_absolute_uri(reverse('webindex')) return context @@ -1090,6 +1092,7 @@ def batch_annotate(request, conn=None, **kwargs): manager = BaseContainer(conn) batchAnns = manager.loadBatchAnnotations(objs) + figScripts = manager.listFigureScripts(objs) obj_ids = [] obj_labels = [] @@ -1101,7 +1104,8 @@ def batch_annotate(request, conn=None, **kwargs): link_string = "|".join(obj_ids).replace("=", "-") context = {'form_comment':form_comment, 'obj_string':obj_string, 'link_string': link_string, - 'obj_labels': obj_labels, 'batchAnns': batchAnns, 'batch_ann':True, 'index': index} + 'obj_labels': obj_labels, 'batchAnns': batchAnns, 'batch_ann':True, 'index': index, + 'figScripts':figScripts} context['template'] = "webclient/annotations/batch_annotate.html" context['webclient_path'] = request.build_absolute_uri(reverse('webindex')) return context @@ -2400,6 +2404,61 @@ def script_ui(request, scriptId, conn=None, **kwargs): return {'template':'webclient/scripts/script_ui.html', 'paramData': paramData, 'scriptId': scriptId} + +@login_required() +@render_response() +def figure_script(request, scriptName, conn=None, **kwargs): + """ + Show a UI for running figure scripts + """ + + imageIds = request.REQUEST.get('Image', None) # comma - delimited list + if imageIds is None: + return HttpResponse("Need to specify Images as /?Image=1,2") + try: + imageIds = [long(i) for i in imageIds.split(",")] + except Exception, e: + return HttpResponse("Need to specify Images as /?Image=1,2") + + images = list( conn.getObjects("Image", imageIds) ) + if len(images) == 0: + raise Http404("No Images found with IDs %s" % imageIds) + + # 'images' list is not sorted. Only use it for validating imageIds + validImages = {} + for img in images: + validImages[img.getId()] = img + imageIds = [iid for iid in imageIds if iid in validImages] + + # Lookup Tags & Datasets (for row labels) + imgDict = [] # A list of data about each image. + for iId in imageIds: + data = {'id':iId} + img = validImages[iId] + data['name'] = img.getName() + tags = [ann.getTextValue() for ann in img.listAnnotations() if ann._obj.__class__ == omero.model.TagAnnotationI] + data['tags'] = tags + data['datasets'] = [d.getName() for d in img.listParents()] + imgDict.append(data) + + # Use the first image as a reference + image = validImages[imageIds[0]] + channels = image.getChannels() + + scriptService = conn.getScriptService() + scriptPath = "/omero/figure_scripts/Split_View_Figure.py" + scriptId = scriptService.getScriptID(scriptPath); + if (scriptId < 0): + raise AttributeError("No script found for path '%s'" % scriptPath) + + idString = ",".join( [str(i) for i in imageIds] ) + + + + return {"template": "webclient/scripts/split_view_figure.html", "scriptId": scriptId, + "image": image, "imgDict": imgDict, "idString":idString, "channels": channels, "tags": tags} + + @login_required() def chgrp(request, conn=None, **kwargs): """ @@ -2464,8 +2523,8 @@ def script_run(request, scriptId, conn=None, **kwargs): continue if pclass.__name__ == 'RMapI': - keyName = "%s_key" % key - valueName = "%s_value" % key + keyName = "%s_key0" % key + valueName = "%s_value0" % key row = 0 paramMap = {} while keyName in request.POST: diff --git a/components/tools/OmeroWeb/omeroweb/webgateway/static/webgateway/css/ome.header.css b/components/tools/OmeroWeb/omeroweb/webgateway/static/webgateway/css/ome.header.css index 6555304856c..e8fc03b7541 100644 --- a/components/tools/OmeroWeb/omeroweb/webgateway/static/webgateway/css/ome.header.css +++ b/components/tools/OmeroWeb/omeroweb/webgateway/static/webgateway/css/ome.header.css @@ -228,7 +228,11 @@ #launch_basket a{ background: url(../img/icon_basket.png) center center no-repeat; } - + + #figScriptButton{ + background: url(../img/icon_figure_scripts.png) center center no-repeat; + } + #scriptButton{ background: url(../img/icon_script.png) center center no-repeat; } @@ -459,12 +463,19 @@ float:none; position:relative; } + + .dropdown li.disabled { + background: transparent; + } + .dropdown li.disabled a { + color: #999; + } - .dropdown > li > a { + /* The menuItem class is added by js to items with children */ + .dropdown > li > a.menuItem { background:url(../img/dropdown_right_arrow.png) 90% center no-repeat; } - - .dropdown > li:hover > a { + .dropdown > li:hover > a.menuItem { background:url(../img/dropdown_right_arrow_hover.png) 90% center no-repeat; } @@ -484,6 +495,12 @@ filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#6B8FB3', endColorstr='#5C7A99',GradientType=0 ); /* IE6-9 */ background:linear-gradient(top, hsl(210,50%,60%) 0%,hsl(210,50%,50%) 100%); /* W3C */ + } + + .dropdown li.disabled:hover { + background: transparent !important; + border-bottom: 1px solid transparent; + border-top: 1px solid transparent; } .dropdown a, #group_user_chooser li strong{ @@ -510,6 +527,10 @@ color:white ; text-shadow:none !important; } + + .dropdown li.disabled:hover a { + color: #999; + } .dropdown li ul li a{ color:#333 !important; diff --git a/components/tools/OmeroWeb/omeroweb/webgateway/static/webgateway/img/icon_figure_scripts.png b/components/tools/OmeroWeb/omeroweb/webgateway/static/webgateway/img/icon_figure_scripts.png new file mode 100644 index 00000000000..f2652d813df Binary files /dev/null and b/components/tools/OmeroWeb/omeroweb/webgateway/static/webgateway/img/icon_figure_scripts.png differ diff --git a/components/tools/OmeroWeb/omeroweb/webgateway/static/webgateway/js/ome.popup.js b/components/tools/OmeroWeb/omeroweb/webgateway/static/webgateway/js/ome.popup.js index ef013ca56c3..55a6aa159b4 100644 --- a/components/tools/OmeroWeb/omeroweb/webgateway/static/webgateway/js/ome.popup.js +++ b/components/tools/OmeroWeb/omeroweb/webgateway/static/webgateway/js/ome.popup.js @@ -34,6 +34,58 @@ jQuery.fn.alternateRowColors = function() { return this; }; + +// Call this on an to only allow numbers. +// I rejects all non-numeric characters but allows paste (then checks value) +// By default it only allows positive ints. +// To allow negative or float values use $(".number").numbersOnly({negative:true, float:true}); +jQuery.fn.numbersOnly = function(options) { + + // First, save the current value (assumed to be valid) + this.each(function() { + $(this).data('numbersOnly', $(this).val()); + }) + .keypress(function(event){ + + // we allow copy, paste, left or right + var allowedChars = [37, 39, 99, 118]; + if (options && options.negative) { + allowedChars.push(45); + } + if (options && options.float) { + allowedChars.push(46); + } + // Reject keypress if not a number and NOT one of our allowed Chars + var charCode = (event.which) ? event.which : event.keyCode; + if (charCode > 31 && (charCode < 48 || charCode > 57) && allowedChars.indexOf(charCode) == -1) { + return false; + } + + // We've allowed keypress (including paste)... + //finally check field value after waiting for keypress to update... + var $this = $(this); + setTimeout(function(){ + var n = $this.val(); + var isNumber = function(n) { + if (n.length === 0) { + return true; // empty strings are allowed + } + return !isNaN(parseFloat(n)) && isFinite(n); + }; + // If so, save to 'data', otherwise revert to 'data' + if (isNumber(n)) { + $this.data('numbersOnly', n); // update + } else { + $this.val( $this.data('numbersOnly') ); + } + }, 10); + + return true; + }); + + return this; +}; + OME.openPopup = function(url) { // IE8 doesn't support arbitrary text for 'name' 2nd arg. #6118 var owindow = window.open(url, '', 'height=600,width=850,left=50,top=50,toolbar=no,menubar=no,scrollbars=yes,resizable=yes,location=no,directories=no,status=no'); @@ -44,9 +96,9 @@ OME.openPopup = function(url) { }; -OME.openCenteredWindow = function(url) { - var width = 550; - var height = 600; +OME.openCenteredWindow = function(url, w, h) { + var width = w ? +w : 550; + var height = h ? +h : 600; var left = parseInt((screen.availWidth/2) - (width/2), 10); var top = 0; var windowFeatures = "width=" + width + ",height=" + height + ",status=no,resizable=yes,scrollbars=yes,menubar=no,toolbar=no,left=" + left + ",top=" + top + "screenX=" + left + ",screenY=" + top; @@ -58,6 +110,17 @@ OME.openCenteredWindow = function(url) { }; +OME.openScriptWindow = function(event, width, height) { + // open script url, providing Data_Type and IDs params in request + var script_url = $(event.target).attr('href'); + if (script_url == "#") return false; + + script_url += "?"+ OME.get_tree_selection(); + OME.openCenteredWindow(script_url, width, height); + return false; +}; + + /* * Returns a string representing the currently selected items in the $.jstree. * E.g. "Image=23,34,98&Dataset=678" @@ -115,13 +178,13 @@ OME.get_tree_selection = function() { OME.confirm_dialog = function(dialog_text, callback, title, button_labels, width, height) { if ((typeof title == "undefined") || (title === null)) { - var title = "Confirm"; + title = "Confirm"; } if ((typeof width == "undefined") || (width === null)) { - var width = 350; + width = 350; } if ((typeof height == "undefined") || (height === null)) { - var height = 140; + height = 140; } var $dialog = $("#confirm_dialog"); @@ -637,4 +700,4 @@ if (false) { // set to 'true' to run. NB: Need to uncomment ' } console.dir(differences); // comment out to keep jsHint happy! }, 1000); -} \ No newline at end of file +}