mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Extract SummaryTree painter, abstract canvas creation into CanvasManager class
This commit is contained in:
+82
-46
@@ -372,6 +372,7 @@ var View = function( container, title, vis_id, dbkey, callback ) {
|
||||
this.min_separation = 30;
|
||||
this.has_changes = false;
|
||||
this.init( callback );
|
||||
this.canvas_manager = new CanvasManager( container.get(0).ownerDocument );
|
||||
this.reset();
|
||||
};
|
||||
$.extend( View.prototype, {
|
||||
@@ -1949,20 +1950,17 @@ $.extend(ReferenceTrack.prototype, TiledTrack.prototype, {
|
||||
track.content_div.css("height", "0px");
|
||||
return;
|
||||
}
|
||||
var canvas = document.createElement("canvas");
|
||||
if (window.G_vmlCanvasManager) { G_vmlCanvasManager.initElement(canvas); } // EXCANVAS HACK
|
||||
canvas = $(canvas);
|
||||
|
||||
var ctx = canvas.get(0).getContext("2d");
|
||||
canvas.get(0).width = Math.ceil( tile_length * w_scale + track.left_offset);
|
||||
canvas.get(0).height = track.height_px;
|
||||
var canvas = this.view.canvas_manager.new_canvas();
|
||||
var ctx = canvas.getContext("2d");
|
||||
canvas.width = Math.ceil( tile_length * w_scale + track.left_offset);
|
||||
canvas.height = track.height_px;
|
||||
ctx.font = DEFAULT_FONT;
|
||||
ctx.textAlign = "center";
|
||||
for (var c = 0, str_len = seq.length; c < str_len; c++) {
|
||||
var c_start = Math.round(c * w_scale);
|
||||
ctx.fillText(seq[c], c_start + track.left_offset, 10);
|
||||
}
|
||||
return canvas;
|
||||
return $(canvas);
|
||||
}
|
||||
this.content_div.css("height", "0px");
|
||||
}
|
||||
@@ -2253,38 +2251,17 @@ $.extend(FeatureTrack.prototype, TiledTrack.prototype, {
|
||||
* Draw summary tree on canvas.
|
||||
*/
|
||||
draw_summary_tree: function(canvas, points, delta, max, w_scale, required_height, tile_low, left_offset) {
|
||||
var
|
||||
// Set base Y so that max label and data do not overlap. Base Y is where rectangle bases
|
||||
// start. However, height of each rectangle is relative to required_height; hence, the
|
||||
// max rectangle is required_height.
|
||||
base_y = required_height + LABEL_SPACING + CHAR_HEIGHT_PX;
|
||||
delta_x_px = Math.ceil(delta * w_scale);
|
||||
|
||||
// Add label to container div when displaying summary tree mode
|
||||
var max_label = $("<div />").addClass('yaxislabel');
|
||||
max_label.text(max);
|
||||
|
||||
max_label.css({ position: "absolute", top: "22px", left: "10px" });
|
||||
max_label.prependTo(this.container_div);
|
||||
|
||||
var ctx = canvas.get(0).getContext("2d");
|
||||
for (var i = 0, len = points.length; i < len; i++) {
|
||||
var x = Math.floor( (points[i][0] - tile_low) * w_scale );
|
||||
var y = points[i][1];
|
||||
|
||||
if (!y) { continue; }
|
||||
var y_px = y / max * required_height;
|
||||
|
||||
ctx.fillStyle = "black";
|
||||
ctx.fillRect(x + left_offset, base_y - y_px, delta_x_px, y_px);
|
||||
|
||||
// Draw number count if it can fit the number with some padding, otherwise things clump up
|
||||
var text_padding_req_x = 4;
|
||||
if (this.prefs.show_counts && (ctx.measureText(y).width + text_padding_req_x) < delta_x_px) {
|
||||
ctx.fillStyle = "#666";
|
||||
ctx.textAlign = "center";
|
||||
ctx.fillText(y, x + left_offset + (delta_x_px/2), 10);
|
||||
}
|
||||
}
|
||||
// Paint summary tree into canvas
|
||||
var ctx = canvas.getContext("2d");
|
||||
var painter = new SummaryTreePainter( points, delta, max, this.prefs.show_counts );
|
||||
painter.draw( ctx, w_scale, required_height, tile_low, left_offset );
|
||||
},
|
||||
/**
|
||||
* Draw feature.
|
||||
@@ -2463,10 +2440,6 @@ $.extend(FeatureTrack.prototype, TiledTrack.prototype, {
|
||||
left_offset = this.left_offset,
|
||||
slots, required_height;
|
||||
|
||||
var canvas = document.createElement("canvas");
|
||||
if (window.G_vmlCanvasManager) { G_vmlCanvasManager.initElement(canvas); } // EXCANVAS HACK
|
||||
canvas = $(canvas);
|
||||
|
||||
//
|
||||
// Set mode if Auto.
|
||||
//
|
||||
@@ -2515,15 +2488,17 @@ $.extend(FeatureTrack.prototype, TiledTrack.prototype, {
|
||||
//
|
||||
// Set up for drawing.
|
||||
//
|
||||
canvas.get(0).width = width + left_offset;
|
||||
canvas.get(0).height = required_height;
|
||||
var canvas = this.view.canvas_manager.new_canvas();
|
||||
|
||||
canvas.width = width + left_offset;
|
||||
canvas.height = required_height;
|
||||
if (result.dataset_type === "summary_tree") {
|
||||
// Increase canvas height in order to display max label.
|
||||
canvas.get(0).height += LABEL_SPACING + CHAR_HEIGHT_PX;
|
||||
canvas.height += LABEL_SPACING + CHAR_HEIGHT_PX;
|
||||
}
|
||||
parent_element.parent().css("height", Math.max(this.height_px, required_height) + "px");
|
||||
// console.log(( tile_low - this.view.low ) * w_scale, tile_index, w_scale);
|
||||
var ctx = canvas.get(0).getContext("2d");
|
||||
var ctx = canvas.getContext("2d");
|
||||
ctx.fillStyle = this.prefs.block_color;
|
||||
ctx.font = this.default_font;
|
||||
ctx.textAlign = "right";
|
||||
@@ -2535,14 +2510,14 @@ $.extend(FeatureTrack.prototype, TiledTrack.prototype, {
|
||||
if (mode === "summary_tree") {
|
||||
this.draw_summary_tree(canvas, result.data, result.delta, result.max, w_scale, required_height,
|
||||
tile_low, left_offset);
|
||||
return canvas;
|
||||
return $(canvas);
|
||||
}
|
||||
|
||||
//
|
||||
// If there is a message, draw it on canvas so that it moves around with canvas, and make the border red
|
||||
// to indicate region where message is applicable
|
||||
if (result.message) {
|
||||
canvas.css({
|
||||
$(canvas).css({
|
||||
"border-top": "1px solid red"
|
||||
});
|
||||
|
||||
@@ -2555,7 +2530,7 @@ $.extend(FeatureTrack.prototype, TiledTrack.prototype, {
|
||||
|
||||
// If there's no data, return.
|
||||
if (!result.data) {
|
||||
return canvas;
|
||||
return $(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2598,7 +2573,7 @@ $.extend(FeatureTrack.prototype, TiledTrack.prototype, {
|
||||
width, left_offset, ref_seq);
|
||||
}
|
||||
}
|
||||
return canvas;
|
||||
return $(canvas);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -3001,6 +2976,20 @@ $.extend(ToolDataFeatureTrack.prototype, TiledTrack.prototype, FeatureTrack.prot
|
||||
|
||||
// ---- To be extracted ------------------------------------------------------
|
||||
|
||||
// ---- Canvas management ----
|
||||
|
||||
var CanvasManager = function( document ) {
|
||||
this.document = document;
|
||||
}
|
||||
|
||||
CanvasManager.prototype.new_canvas = function() {
|
||||
var canvas = this.document.createElement("canvas");
|
||||
if (window.G_vmlCanvasManager) { G_vmlCanvasManager.initElement(canvas); } // EXCANVAS HACK
|
||||
return canvas;
|
||||
}
|
||||
|
||||
// ---- Feature Packing ----
|
||||
|
||||
/**
|
||||
* FeatureSlotter determines slots in which to draw features for vertical
|
||||
* packing.
|
||||
@@ -3150,3 +3139,50 @@ FeatureSlotter.prototype.slot_features = function( features ) {
|
||||
*/
|
||||
return highest_slot + 1;
|
||||
}
|
||||
|
||||
// ---- Painters ----
|
||||
|
||||
/**
|
||||
* SummaryTreePainter, a histogram showing number of intervals in a region
|
||||
*/
|
||||
var SummaryTreePainter = function( data, delta, max, show_counts ) {
|
||||
this.data = data;
|
||||
this.delta = delta;
|
||||
this.max = max;
|
||||
this.show_counts = show_counts;
|
||||
}
|
||||
|
||||
SummaryTreePainter.prototype.draw = function( ctx, w_scale, required_height, tile_low, left_offset ) {
|
||||
|
||||
var
|
||||
points = this.data, delta = this.delta, max = this.max,
|
||||
// Set base Y so that max label and data do not overlap. Base Y is where rectangle bases
|
||||
// start. However, height of each rectangle is relative to required_height; hence, the
|
||||
// max rectangle is required_height.
|
||||
base_y = required_height + LABEL_SPACING + CHAR_HEIGHT_PX;
|
||||
delta_x_px = Math.ceil(delta * w_scale);
|
||||
|
||||
ctx.save();
|
||||
|
||||
for (var i = 0, len = points.length; i < len; i++) {
|
||||
var x = Math.floor( (points[i][0] - tile_low) * w_scale );
|
||||
var y = points[i][1];
|
||||
|
||||
if (!y) { continue; }
|
||||
var y_px = y / max * required_height;
|
||||
|
||||
ctx.fillStyle = "black";
|
||||
ctx.fillRect(x + left_offset, base_y - y_px, delta_x_px, y_px);
|
||||
|
||||
// Draw number count if it can fit the number with some padding, otherwise things clump up
|
||||
var text_padding_req_x = 4;
|
||||
if (this.show_counts && (ctx.measureText(y).width + text_padding_req_x) < delta_x_px) {
|
||||
ctx.fillStyle = "#666";
|
||||
ctx.textAlign = "center";
|
||||
ctx.fillText(y, x + left_offset + (delta_x_px/2), 10);
|
||||
}
|
||||
}
|
||||
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user