From 05e28f9f7c93ed36a0101283fef38d5dd0968218 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20P=C3=B6ckelmann?= <marcus.poeckelmann@informatik.uni-halle.de> Date: Mon, 15 Nov 2021 14:32:49 +0100 Subject: [PATCH] v2.1: added method to invert the edges axis --- catview.js | 535 ++++++++++++++++++++++++++++-------------- demo/demo_bottom.html | 1 + demo/demo_left.html | 1 + demo/demo_right.html | 1 + demo/demo_top.html | 1 + 5 files changed, 363 insertions(+), 176 deletions(-) diff --git a/catview.js b/catview.js index bb2f5d8..5e4b62a 100644 --- a/catview.js +++ b/catview.js @@ -23,16 +23,16 @@ */ // CATview - the Colored & Aligned Texts view -// version 2.0 +// version 2.1 const CATview = new function() { this.debug = false; // initialize attributes - this.initialize = function(_orientation){ + this.initialize = function(_orientation, _x_inverted, _y_inverted){ if(CATview.debug) console.log('CATview.initialize'); - CATview.version = '2.0'; + CATview.version = '2.1'; // id of the parent container that will include CATview CATview.parent_id = 'CATview'; @@ -48,16 +48,22 @@ const CATview = new function() { // CATviews orientation CATview.orientation = ['left', 'right', 'bottom'].indexOf(_orientation) == -1 ? 'top' : _orientation; CATview.vertical = (CATview.orientation == 'left' || CATview.orientation == 'right'); + CATview.x_inverted = (typeof _x_inverted === 'undefined') ? false : _x_inverted; // setting: default order of edges (false → left/top, true → right/bottom) + CATview.y_inverted = (typeof _y_inverted === 'undefined') ? false : _y_inverted; // setting: default order of witnesses (false → top/left, true → bottom/right) // content settings CATview.content = null; - CATview.margin = null; + CATview.space_for_egdes_axis = 24; // reserved drawing size of the edges axis + CATview.space_for_names_axis = 4; // reserved drawing size of the name axis (more size is in respect to the actual names is added in .draw_svg) + CATview.space_for_tool_icons = 22; // reserved drawing size for tool icons + CATview.space_for_other = 2; // reserved size opposite to the edges axis + CATview.margin = {left: 0, top: 0, right: 0, bottom: 0}; CATview.width_content = null; CATview.height_content = null; CATview.edgesAxis = null; CATview.edge_name = null; - CATview.font_size = 14; - CATview.y_inverted = false; // setting: default order of witnesses + CATview.font_size_x = 10; + CATview.font_size_y = 14; CATview.rect_width = null; CATview.rect_height = null; CATview.rect_h_margin = null; @@ -108,6 +114,81 @@ const CATview = new function() { //CATview.color = d3.scaleLinear().domain([0, 1]).range(["#7CCF7C", "c0c"]); }; + // method to set margins and content width/height according to the current orientation of CATview and its axis + this.set_margins = function(){ + if(CATview.debug) + console.log('CATview.set_margins'); + + if(CATview.vertical){ + // handle place of names axis and tool icons in respect to the edges axis direction for vertical orientation of CATview + CATview.margin.top = CATview.x_inverted ? CATview.space_for_tool_icons : CATview.space_for_names_axis; + CATview.margin.bottom = CATview.x_inverted ? CATview.space_for_names_axis : CATview.space_for_tool_icons; + // handle place of the edges axis according to the (left or right) orientation of CATview + CATview.margin.left = CATview.orientation == 'left' ? CATview.space_for_other : CATview.space_for_egdes_axis; + CATview.margin.right = CATview.orientation == 'left' ? CATview.space_for_egdes_axis : CATview.space_for_other; + } else { + // handle place of the edges axis according to the (top or bottom) orientation of CATview + CATview.margin.top = CATview.orientation == 'top' ? CATview.space_for_other : CATview.space_for_egdes_axis; + CATview.margin.bottom = CATview.orientation == 'top' ? CATview.space_for_egdes_axis : CATview.space_for_other; + // handle place of names axis and tool icons in respect to the edges axis direction for horizontal orientation of CATview + CATview.margin.left = CATview.x_inverted ? CATview.space_for_tool_icons : CATview.space_for_names_axis; + CATview.margin.right = CATview.x_inverted ? CATview.space_for_names_axis : CATview.space_for_tool_icons; + } + + // set the available width and height for the content in respect to the margin + CATview.width_content = CATview.width_svg - CATview.margin.left - CATview.margin.right; + CATview.height_content = CATview.height_svg - CATview.margin.top - CATview.margin.bottom; + }; + // method to set scales according to the current orientation of CATview and its axis + this.set_scale_x = function(_from, _to){ + if(CATview.debug) + console.log('CATview.set_scale_y'); + + if(CATview.vertical){ + // vertical orientation (left, right) + if(CATview.x_inverted){ + // inverted egdes axis (starting bottom) + CATview.scale_edges = d3.scaleLinear().domain([_from, _to]).range([CATview.height_content, 0]); + } else { + // normal edges axis (starting top) + CATview.scale_edges = d3.scaleLinear().domain([_from, _to]).range([0, CATview.height_content]); + } + } else { + // horizontal orientation (top, bottom) + if(CATview.x_inverted){ + // inverted egdes axis (starting right) + CATview.scale_edges = d3.scaleLinear().domain([_from, _to]).range([CATview.width_content, 0]); + } else { + // normal edges axis (starting left) + CATview.scale_edges = d3.scaleLinear().domain([_from, _to]).range([0, CATview.width_content]); + } + } + }; + this.set_scale_y = function(){ + if(CATview.debug) + console.log('CATview.set_scale_y'); + + if(CATview.vertical){ + // vertical orientation (left, right) + if(CATview.y_inverted){ + // inverted names axis (starting right) + CATview.scale_names = d3.scaleLinear().domain([-0.5, CATview.names.length - 0.5]).range([CATview.width_content, 0]); + } else { + // normal names axis (starting left) + CATview.scale_names = d3.scaleLinear().domain([-0.5, CATview.names.length - 0.5]).range([0, CATview.width_content]); + } + } else { + // horizontal orientation (top, bottom) + if(CATview.y_inverted){ + // inverted names axis (starting bottom) + CATview.scale_names = d3.scaleLinear().domain([-0.5, CATview.names.length - 0.5]).range([CATview.height_content, 0]); + } else { + // normal names axis (starting top) + CATview.scale_names = d3.scaleLinear().domain([-0.5, CATview.names.length - 0.5]).range([0, CATview.height_content]); + } + } + }; + // query new data from the server and call draw_svg // this requires jQuery this.server_update = function (url, callback){ @@ -166,15 +247,7 @@ const CATview = new function() { CATview.search_results[j][0] += 1; } // update the brush if displayed - if(CATview.display_brush == true && CATview.brush.extent() != [0, 0]) { - let extent = CATview.brush.extent(); - if(col < extent[0]) - extent[0] += 1; - if(col < extent[1]) - extent[1] += 1; - CATview.draw_brush(extent); - CATview.brushing(); - } + // TODO break; case 'remove': CATview.edges.splice(col, 1); @@ -187,15 +260,7 @@ const CATview = new function() { } // update the brush if displayed - if(CATview.display_brush == true && CATview.brush.extent() != [0, 0]) { - let extent = CATview.brush.extent(); - if(col < extent[0]) - extent[0] -= 1; - if(col < extent[1]) - extent[1] -= 1; - CATview.draw_brush(extent); - CATview.brushing(); - } + // TODO break; default: console.log('CATview.data_change: unknown kind of change (' + changes[i][0] + ')'); @@ -203,7 +268,7 @@ const CATview = new function() { } } - CATview.scale_edges = d3.scaleLinear().domain([0, CATview.edges.length + 1]).range([0, CATview.vertical == true ? CATview.height_content : CATview.width_content]); + CATview.set_scale_x(0, CATview.edges.length + 1) CATview.scale_edges_original = CATview.scale_edges.copy(); CATview.refresh_content(CATview.from, CATview.to); return true; @@ -233,81 +298,34 @@ const CATview = new function() { .data(CATview.names) .enter().append("text") .text(function (d) {return d}) - .attr('font-size', CATview.font_size); + .attr('font-size', CATview.font_size_y); // get the dimension of the longest text and add 2 pixels padding let names = document.querySelectorAll('#CATview_prerendered_names text'); for(let i = 0; i < names.length; i++){ if(names_offset < names[i].getComputedTextLength()) names_offset = names[i].getComputedTextLength(); } - names_offset += 2; + CATview.space_for_names_axis += names_offset; //// than remove this temporary elements let element = document.getElementById('CATview_prerendered_names'); element.parentNode.removeChild(element); } - // set margin as well as width and height for the content - if(CATview.orientation == 'left') - CATview.margin = { - top: 2 + names_offset, - bottom: 22, - left: 22, - right: 2}; - else if (CATview.orientation == 'right') - CATview.margin = { - top: 2 + names_offset, - bottom: 22, - left: 2, - right: 22}; - else - CATview.margin = { - top: 2, - bottom: 22, - left: 2 + names_offset, - right: 22}; - CATview.width_content = CATview.width_svg - CATview.margin.left - CATview.margin.right; - CATview.height_content = CATview.height_svg - CATview.margin.top - CATview.margin.bottom; + // initialize margins as well as width and height for the content + CATview.set_margins(); - // set the scales (use one bin offset for the edges-scale) - CATview.scale_edges = d3.scaleLinear().domain([0, CATview.edges.length + 1]).range([0, CATview.vertical == true ? CATview.height_content : CATview.width_content]); - //CATview.scale_names = d3.scale.ordinal().domain(CATview.names.map(function (v, i) { return i})).rangePoints([0, CATview.vertical == true ? CATview.width_content : CATview.height_content], 1); - CATview.scale_names = d3.scaleLinear().domain([-0.5, CATview.names.length - 0.5]).range([0, CATview.vertical == true ? CATview.width_content : CATview.height_content]); + // initialize the scales + CATview.set_scale_x(0, CATview.edges.length + 1) CATview.scale_edges_original = CATview.scale_edges.copy(); + CATview.set_scale_y() // add some zebra stripes CATview.svg.append("g").attr("class", "zebra"); - let zebra_length = CATview.vertical == true ? (CATview.height_svg - CATview.margin.bottom) : (CATview.width_svg - CATview.margin.right); - let zebra_size = CATview.vertical == true ? (Math.floor(CATview.width_content / CATview.names.length * 0.5)) : (Math.floor(CATview.height_content / CATview.names.length * 0.5)) - CATview.svg.select(".zebra").selectAll("rect") - .data(CATview.names) - .enter().append("rect") - .attr("class", "rect-zebra") - .attr("width", CATview.vertical == true ? zebra_size : zebra_length ) - .attr("height", CATview.vertical == true ? zebra_length : zebra_size) // CATview.rect_height) - .attr(CATview.vertical == true ? "y" : "x", 0) - .attr(CATview.vertical == true ? "x" : "y", function(d, i) {return CATview.scale_names(i) - zebra_size / 2.0 + 2.5 }) // a little offset due to font size - .attr("fill", function(d,i) { return i%2==1 ? "#e8e8e8":"transparent";}) + CATview.draw_zebra_stripes(); // add the names-axis - CATview.svg.append("g") - .attr("class", "axis names-axis") - .attr("transform", "translate(" + CATview.margin.left + ", " + CATview.margin.top + ")") - .selectAll("text") - .data(CATview.names) - .enter().append("text") - .text(function (d) {return d}) - .attr(CATview.vertical == true ? "x" : "y", function(d, i) {return CATview.scale_names(i) + 5 }) // a little offset due to font size - .attr("style", "text-anchor: end;") - .attr('font-size', CATview.font_size); - // rotate the names if CATview is in vertical orientation - if(CATview.vertical == true) - CATview.svg.select(".names-axis") - .selectAll("text") - .attr("style", "text-anchor: start;") // rotate at the start of a name - .attr("transform", function(d, i) { - // rotate for 90 degrees than move the names a bit to the right to make them centered - return 'rotate(-90, ' + CATview.scale_names(i) + ', 0)translate(0,' + (CATview.font_size/2) + ')'; - }); + CATview.svg.append("g").attr("class", "axis names-axis"); + CATview.draw_names_axis(); // add the group of tool icons CATview.svg.append("g").attr("class", "tool-icons"); @@ -330,21 +348,9 @@ const CATview = new function() { .attr('style', 'fill-opacity: 0.0;'); // add the edges-axis - switch(CATview.orientation) { - case 'left': - CATview.edgesAxis = d3.axisLeft(CATview.scale_edges); - break; - case 'right': - CATview.edgesAxis = d3.axisRight(CATview.scale_edges); - break; - default: - // numbers of edges at the bottom for top/bottom orientation of CATview - CATview.edgesAxis = d3.axisBottom(CATview.scale_edges); - } - CATview.content.append("g") - .attr("class", "axis edges-axis") - .attr("transform", "translate(" + (CATview.orientation == "right" ? CATview.width_content : "0") + "," + (CATview.vertical == true ? "0" : CATview.height_content) + ")") - .call(CATview.edgesAxis); + CATview.content.append("g").attr("class", "axis edges-axis"); + CATview.draw_edges_axis(); + // add containers for different groups of content CATview.content.append("g").attr("class", "search_results_background"); CATview.content.append("g").attr("class", "alignment"); @@ -375,10 +381,7 @@ const CATview = new function() { if (from == 0) CATview.from = 1; if (to != null) CATview.to = to; // refresh the edges-scale (with one bin offset) - if(CATview.vertical == true) - CATview.scale_edges = d3.scaleLinear().domain([Math.max(CATview.from - 1, 0), Math.min(CATview.to + 1, CATview.edges.length + 1)]).range([0, CATview.height_content]); - else - CATview.scale_edges = d3.scaleLinear().domain([Math.max(CATview.from - 1, 0), Math.min(CATview.to + 1, CATview.edges.length + 1)]).range([0, CATview.width_content]); + CATview.set_scale_x(Math.max(CATview.from - 1, 0), Math.min(CATview.to + 1, CATview.edges.length + 1)) CATview.draw_alignment(); CATview.draw_extra_segments(); @@ -390,43 +393,194 @@ const CATview = new function() { return false; }; - // draws the icons for tools includes in CATview.tools + // draw the axis + this.draw_edges_axis = function(){ + if(CATview.debug) + console.log('CATview.draw_edges_axis'); + + let edges_axis = CATview.svg.select(".edges-axis"); + edges_axis.selectAll('*').remove(); // remove the current content + + let pos_x = 0; + let pos_y = 0; + switch(CATview.orientation) { + case 'left': + CATview.edgesAxis = d3.axisRight(CATview.scale_edges); + pos_x = CATview.width_content; + break; + case 'right': + CATview.edgesAxis = d3.axisLeft(CATview.scale_edges); + break; + case 'bottom': + CATview.edgesAxis = d3.axisTop(CATview.scale_edges); + break; + default: + // numbers of edges at the bottom for top orientation of CATview + CATview.edgesAxis = d3.axisBottom(CATview.scale_edges); + pos_y = CATview.height_content; + } + edges_axis + .attr("transform", "translate(" + pos_x + "," + pos_y + ")") + .call(CATview.edgesAxis); + }; + this.draw_names_axis = function(){ + if(CATview.debug) + console.log('CATview.draw_names_axis') + + let names_axis = CATview.svg.select(".names-axis"); + names_axis.selectAll('*').remove(); // remove the current content + + // place the names axis + if(CATview.x_inverted) + if(CATview.vertical) + names_axis.attr("transform", "translate(" + CATview.margin.left + ", " + (CATview.height_svg - CATview.margin.bottom) + ")"); + else + names_axis.attr("transform", "translate(" + (CATview.width_svg - CATview.margin.right) + ", " + CATview.margin.top + ")"); + else + names_axis.attr("transform", "translate(" + CATview.margin.left + ", " + CATview.margin.top + ")"); + + // add the names + let anchor = 'end'; + if(CATview.vertical){ + if((CATview.orientation == 'left' && CATview.x_inverted) || (CATview.orientation == 'right' && CATview.x_inverted == false)) + anchor = 'start'; + + names_axis.selectAll("text") + .data(CATview.names) + .enter().append("text") + .text(function (d) {return d}) + .attr("x", function(d, i) {return CATview.scale_names(i)}) + .attr("style", "text-anchor: " + anchor + ";") + .attr('font-size', CATview.font_size_y) + .attr("transform", function(d, i) { + // rotate for 90 degrees than move the names a bit to the right to make them centered + return 'rotate(' + (CATview.orientation == 'left' ? 90 : -90) + ', ' + CATview.scale_names(i) + ', 0)translate(0,' + (CATview.font_size_y/2) + ')'; + }); + } else { + if(CATview.x_inverted) + anchor = 'start'; + names_axis.selectAll("text") + .data(CATview.names) + .enter().append("text") + .text(function (d) {return d}) + .attr("y", function(d, i) {return CATview.scale_names(i) + 5 }) // a little offset due to font size + .attr("style", "text-anchor: " + anchor + ";") + .attr('font-size', CATview.font_size_y); + } + }; + + // draws the zebra stripes (gray lines in the background for every second text) + this.draw_zebra_stripes = function(){ + if(CATview.debug) + console.log('CATview.draw_zebra_lines') + + let zebra = CATview.svg.select(".zebra"); + zebra.selectAll('*').remove(); // remove the current content + + let width, height; + if(CATview.vertical){ + height = CATview.height_svg - CATview.space_for_tool_icons; + width = Math.floor(CATview.width_content / CATview.names.length * 0.5) + + } else { + width = CATview.width_svg - CATview.space_for_tool_icons; + height = Math.floor(CATview.height_content / CATview.names.length * 0.5); + } + + let offset = CATview.x_inverted ? CATview.space_for_tool_icons : 0 + + zebra.selectAll("rect") + .data(CATview.names) + .enter().append("rect") + .attr("class", "rect-zebra") + .attr("width", width ) + .attr("height", height) + .attr('x', CATview.vertical == true ? function(d, i) {return CATview.scale_names(i) - width / 2.0 + CATview.margin.left} : offset) + .attr('y', CATview.vertical == true ? offset : function(d, i) {return CATview.scale_names(i) - height / 2.0 + CATview.margin.top}) + .attr("fill", function(d,i) { return i%2==1 ? "#e8e8e8":"transparent";}) + }; + + // draws the icons for tools included in CATview.tools this.draw_tool_icons = function(){ + if(CATview.debug) + console.log('CATview.draw_tool_icons') + let toolicons = CATview.svg.select(".tool-icons"); - toolicons.empty(); + toolicons.selectAll('*').remove(); // remove the current content - let n = CATview.tools.length; + let margin = 3; // extra margin around the tool icon conatiner + let width, height; // available space for the tool icon container + + // place the container for the tool icons + if(CATview.vertical == true){ + width = CATview.width_svg - CATview.margin.left - CATview.margin.right - 2 * margin; + height = CATview.space_for_tool_icons - 2 * margin; + if(CATview.x_inverted) + toolicons.attr("transform", "translate(" + (CATview.margin.left + margin) + ", " + margin + ")"); + else + toolicons.attr("transform", "translate(" + (CATview.margin.left + margin) + ", " + (CATview.height_svg - CATview.margin.bottom + margin) + ")"); + } else { + width = CATview.space_for_tool_icons - 2 * margin; + height = CATview.height_svg - CATview.margin.top - CATview.margin.bottom - 2 * margin; + if(CATview.x_inverted) + toolicons.attr("transform", "translate(" + margin + ", " + (CATview.margin.top + margin) + ")"); + else + toolicons.attr("transform", "translate(" + (CATview.width_svg - CATview.margin.right + margin) + ", " + (CATview.margin.top + margin) + ")"); + } + /*toolicons.append('rect') + .attr("x", -margin) + .attr("y", -margin) + .attr("width", width + 2 * margin) + .attr("height", height + 2 * margin) + .attr('fill', '#ccccff'); + toolicons.append('rect') + .attr("x", 0) + .attr("y", 0) + .attr("width", width) + .attr("height", height) + .attr('fill', '#8888ff');*/ + + let n = CATview.tools.length; // number of tool icons to be placed if(n > 0) { - let e_margin = 3; // margin in direction of edges-axis (small) - let n_margin = 10; // margin in direction of names-axis (large) - let padding = 10; - let w, h; - if(CATview.vertical == true) { - w = Math.floor((CATview.width_content - 2 * n_margin - (n - 1) * padding) / n); - h = CATview.margin.bottom - 2 * e_margin; - } - else { - w = CATview.margin.right - 2 * e_margin; - h = Math.floor((CATview.height_content - 2 * n_margin - (n - 1) * padding) / n); + let padding = 12; + let fontsize; + if(CATview.vertical){ + fontsize = (width - (n-1)*padding) / n; + if(height < fontsize){ + fontsize = height; + padding = (width - n * fontsize) / (n-1) + } + } else { + fontsize = (height - (n-1)*padding) / n; + if(width < fontsize){ + fontsize = width; + padding = (height - n * fontsize) / (n-1) + } } - let font_size = Math.min.apply(null, [20, w, h]); - // increase the padding to fill the complete available space - padding = Math.floor(((CATview.vertical == true ? CATview.width_content : CATview.height_content)) - 2 * n_margin - n * font_size) / (n - 1); for(let i = 0; i < CATview.tools.length; i++){ + let x, y; + if(CATview.vertical == true){ + x = i * (fontsize + padding) + fontsize/2; + y = fontsize/2; + } else { + x = fontsize/2; + y = i * (fontsize + padding) + fontsize/2; + } + toolicons.append('text') .attr("class", "tool-icon") - .attr("x", CATview.vertical == true ? (n_margin + i * (font_size + padding)) : e_margin) - .attr("y", CATview.vertical == true ? (e_margin + font_size) : (n_margin + (i + 1) * font_size + i * padding)) - .on("click", CATview.tools[i][1]) + .attr("x", x) + .attr("y", y) + .attr("style", "text-anchor: middle; dominant-baseline: middle;") + .attr("font-family","FontAwesome") + //.attr("textLength", fontsize) + //.attr("lengthAdjust","spacingAndGlyphs") .text(String.fromCharCode(parseInt(CATview.tools[i][0], 16))) - .attr('font-size', font_size); + .attr('font-size', fontsize - 4) + .attr("transform", (function(){ return 'rotate(' + CATview.tools[i][2] + ' ' + x + ' ' + y + ')' })) + .on("click", CATview.tools[i][1]); } - - if(CATview.vertical == true) - toolicons.attr("transform", "translate(" + (CATview.margin.left) + ", " + (CATview.height_svg - CATview.margin.bottom) + ")"); - else - toolicons.attr("transform", "translate(" + (CATview.width_svg - CATview.margin.right) + ", " + 0 + ")"); } }; @@ -493,13 +647,13 @@ const CATview = new function() { let transform = ''; switch (CATview.orientation) { - case "left": transform = 'rotate(-90)translate(9, -14)'; break; - case "right": transform = 'rotate(90)translate(-9, -14)'; break; + case "left": transform = 'translate(3, 0)'; break; + case "right": transform = 'translate(-3, 0)'; break; default: break; } return transform; }) - .attr('font-size', CATview.font_size); + .attr('font-size', CATview.font_size_x); } else return false; @@ -554,9 +708,6 @@ const CATview = new function() { break; default: // top } - //console.log('x: ' + anchor_x + ' → ' + offset_x) - //console.log('y: ' + anchor_y + ' → ' + offset_y) - //console.log(transform) CATview.edge_name.html(name) .style(anchor_x, offset_x) .style(anchor_y, offset_y) @@ -623,17 +774,13 @@ const CATview = new function() { return false; if (CATview.display_remaining_edges) { CATview.remaining_edges.every(function (edges) { - //console.log(edges); - // stop drawing when the distance of the remaining edges exceed the threshold if (edges[0] > CATview.threshold) { return false; } edges[1].forEach(function (edge) { - //console.log('\t' + edges[0] + '\t' + edge); if (CATview.from <= edge[0][1] + 1 && edge[0][1] + 1 <= CATview.to && CATview.from <= edge[1][1] + 1 && edge[1][1] + 1 <= CATview.to) { - //console.log('\t\tim focus'); CATview.content.select(".remaining_edges").append('line') .attr("class", "remaining") .attr('x1', CATview.scale_edges(edge[0][1] + 1)) @@ -780,29 +927,38 @@ const CATview = new function() { return false; }; + // callback to switch the order of edges + this.invert_edges_axis = function(){ + if(CATview.debug) + console.log('CATview.invert_edges_axis'); + + CATview.x_inverted = !CATview.x_inverted; + + if(CATview.content){ + CATview.set_margins(); + CATview.set_scale_x(); + // relocate the content container + CATview.svg.select(".content").attr("transform", "translate(" + CATview.margin.left + "," + CATview.margin.top + ")"); + CATview.draw_zebra_stripes(); + CATview.draw_edges_axis(); + CATview.draw_names_axis(); + CATview.draw_tool_icons(); + CATview.refresh_content(); + } + else + return false; + }; + // callback to switch the order of text witnesses this.invert_names_axis = function(){ if(CATview.debug) console.log('CATview.invert_names_axis'); - if(CATview.content){ - if(CATview.y_inverted){ - CATview.scale_names = d3.scaleLinear().domain([-0.5, CATview.names.length - 0.5]).range( - [0, CATview.vertical == true ? CATview.width_content : CATview.height_content]); - } - else{ - CATview.scale_names = d3.scaleLinear().domain([-0.5, CATview.names.length - 0.5]).range( - [CATview.vertical == true ? CATview.width_content : CATview.height_content, 0]); - } - CATview.y_inverted = !CATview.y_inverted; + CATview.y_inverted = !CATview.y_inverted; - CATview.svg.select(".names-axis").selectAll("text").remove(); - CATview.svg.select(".names-axis").selectAll("text") - .data(CATview.names) - .enter().append("text") - .text(function (d) {return d}) - .attr(CATview.vertical == true ? "x" : "y", function(d, i) { return CATview.scale_names(i) + 5;}) - .attr("style", "text-anchor: end"); + if(CATview.content){ + CATview.set_scale_y(); + CATview.draw_names_axis(); CATview.refresh_content(); } else @@ -835,6 +991,8 @@ const CATview = new function() { let new_scale = d3.event.transform.k; let new_translate = CATview.vertical == true ? (d3.event.transform.y/new_scale) : (d3.event.transform.x/new_scale); + if(CATview.x_inverted) + new_translate = -new_translate; if(CATview.content){ @@ -870,7 +1028,6 @@ const CATview = new function() { new_to_pixel = current_size; new_from_pixel -= offset; } - //console.log(current_size + ": " + CATview.from_pixel + " -> " + new_from_pixel + "\t\t" + CATview.to_pixel + " -> " + new_to_pixel); // return when one of the new interval borders is not legit (e.g. by double clicking a rectangle) if(isNaN(new_from_pixel) || isNaN(new_to_pixel)) @@ -894,16 +1051,16 @@ const CATview = new function() { // refresh the brush if(CATview.brush) { // remember the current extent - let extent = CATview.brush.extent(); + //let extent = CATview.brush.extent(); // update the scale // if(CATview.vertical == true) // todo CATview.brush.y(CATview.scale_edges); // else // todo CATview.brush.x(CATview.scale_edges); // restore the extent - CATview.brush.extent(extent); + //CATview.brush.extent(extent); // redraw the brush - CATview.content.select(".brush").call(CATview.brush); + //CATview.content.select(".brush").call(CATview.brush); } } else @@ -922,7 +1079,6 @@ const CATview = new function() { if(CATview.debug) console.log('CATview.enable_brush'); - if(CATview.display_brush == false){ CATview.display_brush = true; // add the brush to CATview @@ -959,7 +1115,7 @@ const CATview = new function() { }; // add the brush element to the svg - this.draw_brush = function(extent){ + this.draw_brush = function(){ if(CATview.debug) console.log('CATview.draw_brush'); @@ -968,21 +1124,28 @@ const CATview = new function() { // remove previous brush CATview.content.select(".brush").remove(); // add the brush to CATview + if(CATview.vertical == true) { - console.log('jup0'); CATview.brush = d3.brushY() - .extent([[CATview.scale_names.range()[0], CATview.scale_edges.range()[0]], [CATview.scale_names.range()[1], CATview.scale_edges.range()[1]]]) + .on("brush", CATview.brushing); + + if(CATview.x_inverted) + CATview.brush.extent([[CATview.scale_names.range()[0], CATview.scale_edges.range()[1]], [CATview.scale_names.range()[1], CATview.scale_edges.range()[0]]]) + else + CATview.brush.extent([[CATview.scale_names.range()[0], CATview.scale_edges.range()[0]], [CATview.scale_names.range()[1], CATview.scale_edges.range()[1]]]) + } else { + CATview.brush = d3.brushX() .on("brush", CATview.brushing); + + if(CATview.x_inverted) + CATview.brush.extent([[CATview.scale_edges.range()[1], CATview.scale_names.range()[0]], [CATview.scale_edges.range()[0], CATview.scale_names.range()[1]]]) + else + CATview.brush.extent([[CATview.scale_edges.range()[0], CATview.scale_names.range()[0]], [CATview.scale_edges.range()[1], CATview.scale_names.range()[1]]]) } - else - CATview.brush = d3.brushX() - .extent([[CATview.scale_edges.range()[0], CATview.scale_names.range()[0]], [CATview.scale_edges.range()[1], CATview.scale_names.range()[1]]]) - .on("brush", CATview.brushing); - CATview.content.append("g") + let brush = CATview.content.append("g") .attr("class", "brush") .call(CATview.brush); - //.selectAll("rect").attr(CATview.vertical == true ? "width" : "height", CATview.vertical == true ? CATview.width_content : CATview.height_content); } return true; } @@ -1016,6 +1179,13 @@ const CATview = new function() { to_edge = CATview.edges.length - 1; let from_name = null; // Math.ceil(CATview.brush.extent()[0][names_index]); let to_name = null; // Math.floor(CATview.brush.extent()[1][names_index]); + + if(CATview.x_inverted){ + let swap = from_edge; + from_edge = to_edge; + to_edge = swap; + } + if(to_edge - from_edge >= 0) { // check whether the interval has changed if (from_edge != CATview.brush_from_edge || to_edge != CATview.brush_to_edge || from_name != CATview.brush_from_name || to_name != CATview.brush_to_name) { @@ -1036,12 +1206,14 @@ const CATview = new function() { }; // add a new tool icon and its behavior - this.add_tool = function(icon, callback, index){ - index = parseInt(index); + this.add_tool = function(_icon, _callback, _index, _rotation){ + let index = parseInt(_index); if (isNaN(index) || index < 0 || index > CATview.tools.length ) index = CATview.tools.length; - CATview.tools.splice(index, 0, [icon, callback]); + let rotation = (typeof _rotation === 'undefined') ? 0 : parseInt(_rotation); + + CATview.tools.splice(index, 0, [_icon, _callback, rotation]); return true; }; @@ -1055,11 +1227,19 @@ const CATview = new function() { return true; }; + // add the invert-x-axis tool + this.add_tool_invert_edges_axis = function(index){ + return CATview.add_tool('f0dc', + function(){CATview.invert_edges_axis();}, + index, + CATview.vertical ? 0 : 90); + }; // add the invert-y-axis tool this.add_tool_invert_names_axis = function(index){ return CATview.add_tool('f0dc', function(){CATview.invert_names_axis();}, - index); + index, + CATview.vertical ? 90 : 0); }; // add the display-remaining-edges tool this.add_tool_display_remaining_edges = function(index){ @@ -1067,7 +1247,8 @@ const CATview = new function() { function(){ CATview.display_remaining_edges = !CATview.display_remaining_edges; CATview.draw_remaining_edges();}, - index); + index, + 0); }; // add the switch-highlight-mode-of-search-results tool this.add_tool_toggle_search_mode = function(index){ @@ -1075,17 +1256,19 @@ const CATview = new function() { function(){ CATview.search_mode = (CATview.search_mode == 'seg' ? 'col' : 'seg'); CATview.draw_search_results();}, - index); + index, + 0); }; // add the enable/disable-brush tool this.add_tool_toggle_brush = function(index){ - return CATview.add_tool('f1fc', + return CATview.add_tool('f1fc', // f096 function(){ if(CATview.display_brush) CATview.disable_brush(); else CATview.enable_brush();}, - index); + index, + 0); }; //todo remove and set the identifiers of the witnesses diff --git a/demo/demo_bottom.html b/demo/demo_bottom.html index 459b4a6..1c1e418 100644 --- a/demo/demo_bottom.html +++ b/demo/demo_bottom.html @@ -82,6 +82,7 @@ "Aliquam sagittis…", "Nunc ut…", "Curabitur placerat…", "Aenean molestie…", "Donec quis…", "Aliquam sagittis…", "Duis nunc…", "Pellentesque habitant…", "Tincidunt dignissim…", "Nullam non…" ]); CATview.add_tool_invert_names_axis(); // invert-names-axis tool + CATview.add_tool_invert_edges_axis(); // invert-edges-axis tool CATview.add_tool_toggle_search_mode(); // switch-highlight-mode-of-search-results tool CATview.add_tool_toggle_brush(); // enable/disable-brush tool CATview.draw_svg(); diff --git a/demo/demo_left.html b/demo/demo_left.html index 1e9e736..ba1e875 100644 --- a/demo/demo_left.html +++ b/demo/demo_left.html @@ -83,6 +83,7 @@ "Aliquam sagittis…", "Nunc ut…", "Curabitur placerat…", "Aenean molestie…", "Donec quis…", "Aliquam sagittis…", "Duis nunc…", "Pellentesque habitant…", "Tincidunt dignissim…", "Nullam non…" ]); CATview.add_tool_invert_names_axis(); // invert-names-axis tool + CATview.add_tool_invert_edges_axis(); // invert-edges-axis tool CATview.add_tool_toggle_search_mode(); // switch-highlight-mode-of-search-results tool CATview.add_tool_toggle_brush(); // enable/disable-brush tool CATview.draw_svg(); diff --git a/demo/demo_right.html b/demo/demo_right.html index e6058e8..5502515 100644 --- a/demo/demo_right.html +++ b/demo/demo_right.html @@ -83,6 +83,7 @@ "Aliquam sagittis…", "Nunc ut…", "Curabitur placerat…", "Aenean molestie…", "Donec quis…", "Aliquam sagittis…", "Duis nunc…", "Pellentesque habitant…", "Tincidunt dignissim…", "Nullam non…" ]); CATview.add_tool_invert_names_axis(); // invert-names-axis tool + CATview.add_tool_invert_edges_axis(); // invert-edges-axis tool CATview.add_tool_toggle_search_mode(); // switch-highlight-mode-of-search-results tool CATview.add_tool_toggle_brush(); // enable/disable-brush tool CATview.draw_svg(); diff --git a/demo/demo_top.html b/demo/demo_top.html index b9dc518..2252784 100644 --- a/demo/demo_top.html +++ b/demo/demo_top.html @@ -83,6 +83,7 @@ "Aliquam sagittis…", "Nunc ut…", "Curabitur placerat…", "Aenean molestie…", "Donec quis…", "Aliquam sagittis…", "Duis nunc…", "Pellentesque habitant…", "Tincidunt dignissim…", "Nullam non…" ]); CATview.add_tool_invert_names_axis(); // invert-names-axis tool + CATview.add_tool_invert_edges_axis(); // invert-edges-axis tool CATview.add_tool_toggle_search_mode(); // switch-highlight-mode-of-search-results tool CATview.add_tool_toggle_brush(); // enable/disable-brush tool CATview.draw_svg(); -- GitLab