Skip to content
This repository was archived by the owner on Dec 17, 2024. It is now read-only.

Commit 62246d5

Browse files
Kerry Changstarpit
authored andcommitted
implement zoom-to-fit with viewBox instead of container width and height
add a test
1 parent 8fa893f commit 62246d5

File tree

4 files changed

+108
-52
lines changed

4 files changed

+108
-52
lines changed

app/plugins/modules/wskflow/lib/fsm2graph.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -459,8 +459,8 @@ function ir2graph(ir, gm, id, prevId){ // ir and graph model
459459
}
460460

461461

462-
function fsm2graph(ir, containerId, w, h, acts){
463-
//console.log(ir, containerId, w, h, act);
462+
function fsm2graph(ir, containerId, acts){
463+
//console.log(ir, containerId, act);
464464
taskIndex = 0;
465465
activations = acts;
466466
visited = undefined; // see shell issue #602
@@ -551,7 +551,7 @@ function fsm2graph(ir, containerId, w, h, acts){
551551

552552
console.log('[wskflow] inserting DOM, calling graph2doms');
553553

554-
return graph2doms(graphData, containerId, w, h, activations);
554+
return graph2doms(graphData, containerId, activations);
555555

556556
}
557557

app/plugins/modules/wskflow/lib/graph2doms.js

Lines changed: 41 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ const wfColorAct = {
7878
}
7979

8080
// need to fix center
81-
function graph2doms(JSONgraph, containerId, width, height, activations){
81+
function graph2doms(JSONgraph, containerId, activations){
8282

8383
let zoom = d3.behavior.zoom()
8484
.on("zoom", redraw);
@@ -263,10 +263,7 @@ function graph2doms(JSONgraph, containerId, width, height, activations){
263263
elkData = data;
264264

265265
// by default, the graph resizes to fit the size of the container i.e. zoom-to-fit, showing the entire graph. This solves #582.
266-
resizeToFit(width, height);
267-
268-
console.log(`[wskflow] svg canvas width=${width}, height=${height}`);
269-
266+
resizeToFit();
270267

271268
let getNodes = function(graph) {
272269
var queue = [graph],
@@ -1148,27 +1145,25 @@ function graph2doms(JSONgraph, containerId, width, height, activations){
11481145
*/
11491146

11501147
let applyAutoScale = true, // if resizing the window will resize the graph. true by default.
1151-
customZoom = false
1148+
customZoom = false;
11521149

1153-
function resizeToFit(w, h){ // resizeToFit implements a zoom-to-fit behavior.
1154-
width = w;
1155-
height = h;
1156-
let initScale = Math.min(width/elkData.width, height/elkData.height, 4),
1157-
initTransX = Math.max(width/2 - elkData.width*initScale/2, 0),
1158-
initTransY = 0;
1159-
zoom.translate([initTransX, initTransY]);
1160-
zoom.scale(initScale);
1161-
container.attr('transform', `matrix(${initScale}, 0, 0, ${initScale}, ${initTransX}, ${initTransY})`);
1150+
function resizeToFit(){
1151+
// resizeToFit implements a zoom-to-fit behavior using viewBox.
1152+
// it no longer requires knowing the size of the container
1153+
// disadventage is we cannot decide the max zoom level: it will always zoom to fit the entire container
1154+
ssvg.attr('viewBox', `0 0 ${elkData.width} ${elkData.height}`);
1155+
container.attr('transform', '');
1156+
zoom.translate([0, 0]);
1157+
zoom.scale(1);
11621158
}
11631159

1164-
function pan(w, h){ // pan implements a behavior that zooms in the graph by 2x.
1165-
width = w;
1166-
height = h;
1160+
function pan(){ // pan implements a behavior that zooms in the graph by 2x.
11671161
let initScale = 2,
1168-
initTransX = width/2 - elkData.width*initScale/2,
1162+
initTransX = $('#wskflowSVG').width()/2 - elkData.width*initScale/2,
11691163
initTransY = 0;
11701164
zoom.translate([initTransX, initTransY]);
11711165
zoom.scale(initScale);
1166+
$('#wskflowSVG').removeAttr('viewBox');
11721167
container.attr('transform', `matrix(${initScale}, 0, 0, ${initScale}, ${initTransX}, ${initTransY})`);
11731168
}
11741169

@@ -1185,40 +1180,50 @@ function graph2doms(JSONgraph, containerId, width, height, activations){
11851180
*/
11861181
const zoomToFit = useThisValue => {
11871182
applyAutoScale = useThisValue !== undefined ? useThisValue : !applyAutoScale; // toggle applyAutoScale
1188-
customZoom = false
1183+
customZoom = false
11891184
notify()
11901185
//console.error('ZTF', applyAutoScale, customZoom)
11911186
if(applyAutoScale){
11921187
// when clicking to switch from inactive to active, it resizes the graph to fit the window. #422
1193-
resizeToFit($('#wskflowSVG').width(), $('#wskflowSVG').height());
1188+
resizeToFit();
11941189
}
11951190
else{
11961191
// when clicking to switch from active to inactive, it resizes the graph to zoom in at graph entry by 2x.
1197-
pan($('#wskflowSVG').width(), $('#wskflowSVG').height());
1192+
pan();
11981193
}
11991194
}
12001195

12011196
/*
12021197
from https://github.com/OpenKieler/klayjs-d3/blob/master/examples/interactive/index.js
12031198
redraw is called by d3. d3.event.translate and d3.event.scale handle moving the graph and zooming. Note that when zooming, both event.translate and event.scale change to let the zoom center be the mouse cursor. Adding ohter values to event.translate and event.scale is likely to cause unwanted behaviors.
12041199
*/
1205-
function redraw() {
1206-
if(applyAutoScale || !customZoom){ // exit zoom-to-fit mode when the user uses the mouse to move or zoom the graph
1207-
applyAutoScale = false;
1208-
customZoom = true
1209-
notify()
1200+
function redraw() { // redraw is called when there's mouse scrolling
1201+
if(applyAutoScale || !customZoom){ // exit zoom-to-fit mode when the user uses the mouse to move or zoom the graph
1202+
applyAutoScale = false;
1203+
customZoom = true
1204+
notify()
12101205
}
1211-
$("#qtip").removeClass("visible")
1212-
container.attr('transform', `translate(${d3.event.translate}) scale(${d3.event.scale})`);
1206+
container.attr('transform', `translate(${d3.event.translate}) scale(${d3.event.scale})`);
1207+
$("#qtip").removeClass("visible")
12131208
}
1214-
12151209
// when zoom-to-fit is active, the graph resizes as the window resizes. #422
1216-
$(window).unbind('resize').resize(() => {
1217-
// auto-resize with window size works when the user haven't adjusted the zooming manually with scrolling.
1218-
if(applyAutoScale){
1219-
resizeToFit($('#wskflowSVG').width(), $('#wskflowSVG').height());
1220-
}
1221-
1210+
$(window).unbind('resize').resize(e => {
1211+
1212+
if(customZoom && $('#wskflowSVG').attr('viewBox') !== undefined){
1213+
// this code is called when the user is in custom zoom mode but the viewbox still exists
1214+
// remove viewbox here to stop auto-resizing,
1215+
$('#wskflowSVG').removeAttr('viewBox');
1216+
// adjust transform to let the graph be in the same size and location
1217+
let width = $('#wskflowSVG').width(),
1218+
height = $('#wskflowSVG').height(),
1219+
scale = Math.min(width/elkData.width, height/elkData.height),
1220+
initScale = scale * zoom.scale(),
1221+
initTransX = width/2 - elkData.width*scale/2 + zoom.translate()[0]*scale,
1222+
initTransY = height/2 - elkData.height*scale/2 + zoom.translate()[1]*scale;
1223+
zoom.translate([initTransX, initTransY]);
1224+
zoom.scale(initScale);
1225+
container.attr('transform', `matrix(${initScale}, 0, 0, ${initScale}, ${initTransX}, ${initTransY})`);
1226+
}
12221227
});
12231228

12241229

app/plugins/modules/wskflow/lib/visualize.js

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,17 +35,6 @@ module.exports = (passedFsm, container, w, h, activations) => {
3535
}
3636

3737
// create a copy - all annotations make by wskflow will not affect the original object.
38-
let ir = JSON.parse(JSON.stringify(passedFsm)),
39-
width,
40-
height;
41-
42-
if($('body').hasClass('sidecar-full-screen')){
43-
width = $(window).width()-2;
44-
}
45-
else{ // not full screen
46-
width = $(window).width()*0.6-2;
47-
}
48-
height = $('#sidecar').height()-$('.sidecar-header').height()-$('.sidecar-bottom-stripe').height()-2;
49-
50-
return fsm2graph(ir, container, width, height, activations);
38+
let ir = JSON.parse(JSON.stringify(passedFsm));
39+
return fsm2graph(ir, container, activations);
5140
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright 2017 IBM Corporation
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
const fs = require('fs'),
18+
common = require('../../../lib/common'),
19+
openwhisk = require('../../../lib/openwhisk'),
20+
ui = require('../../../lib/ui'),
21+
cli = ui.cli,
22+
sidecar = ui.sidecar,
23+
keys = ui.keys,
24+
assert = require('assert'),
25+
//sharedURL = process.env.REDIS_URL || 'redis://127.0.0.1:6379',
26+
{
27+
input,
28+
composerInput,
29+
verifyNodeExists,
30+
verifyNodeExistsById,
31+
verifyEdgeExists,
32+
verifyOutgoingEdgeExists,
33+
verifyNodeLabelsAreSane,
34+
verifyTheBasicStuff
35+
} = require('../../../lib/composer-viz-util')
36+
37+
/**
38+
* Here starts the test
39+
*
40+
*/
41+
describe('bring up the composer visualization when the sidecar is minimized', function() {
42+
before(common.before(this))
43+
after(common.after(this))
44+
45+
it('should have an active repl', () => this.app.client.waitForText('#openwhisk-api-host', 60000))
46+
47+
it('should show the if composition graph', () => cli.do('preview data/composer-source/if.js', this.app)
48+
.then(verifyTheBasicStuff('if.js', 'composerLib')) // verify basic things
49+
.catch(common.oops(this)))
50+
51+
it('should minimize the sidecar', () => this.app.client.keys(keys.ESCAPE)
52+
.then(() => sidecar.expectClosed(this.app))
53+
.catch(common.oops(this)))
54+
55+
it('should show the if composition graph again', () => cli.do('app preview data/composer-source/if.js', this.app)
56+
.then(() => sidecar.expectOpen(this.app))
57+
.catch(common.oops(this)))
58+
59+
it('should use viewBox to let the graph fit the container', () => this.app.client.waitForExist('#wskflowSVG[viewBox]', 3000))
60+
61+
62+
});

0 commit comments

Comments
 (0)