Skip to content

Commit

Permalink
Allow for setting whether dragging from an element causes panning #1905
Browse files Browse the repository at this point in the history
- Implement `ele.pannable()`, `eles.panify()`, and `eles.unpanify()`.  If `ele.pannable() === true` then `ele.grabbable() === false`.  Previous checks in the renderer for passthrough panning that used `ele.isEdge()` now use `ele.pannable()`.
- Implement JSON import/export for the `pannable` property.
- Basic tests for JSON import/export.
- Document `ele.pannable()`, `eles.panify()`, and `eles.unpanify()`.
- Add panify and unpanify test UI to the debug page.
  • Loading branch information
maxkfranz committed May 23, 2019
1 parent 812a17e commit bd4f56a
Show file tree
Hide file tree
Showing 11 changed files with 89 additions and 11 deletions.
7 changes: 6 additions & 1 deletion debug/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ <h2>Element events</h2>
<option value="dragfreeon">dragfreeon</option>
<option value="grabify">grabify</option>
<option value="ungrabify">ungrabify</option>
<option value="panify">panify</option>
<option value="unpanify">unpanify</option>
<option value="selectify">selectify</option>
<option value="unselectify">unselectify</option>
<option value="box">box</option>
Expand Down Expand Up @@ -235,6 +237,8 @@ <h2>Core events</h2>
<option value="dragfreeon">dragfreeon</option>
<option value="grabify">grabify</option>
<option value="ungrabify">ungrabify</option>
<option value="panify">panify</option>
<option value="unpanify">unpanify</option>
<option value="selectify">selectify</option>
<option value="unselectify">unselectify</option>
<option value="box">box</option>
Expand All @@ -261,7 +265,8 @@ <h2>Core events</h2>
<h2>Toggles on selected</h2>
<button class="toggler">selectify</button> <button class="toggler">unselectify</button><br />
<button class="toggler">lock</button> <button class="toggler">unlock</button><br />
<button class="toggler">grabify</button> <button class="toggler">ungrabify</button>
<button class="toggler">grabify</button> <button class="toggler">ungrabify</button><br />
<button class="toggler">panify</button> <button class="toggler">unpanify</button>

<h2>String stylesheets</h2>
<label for="string-stylesheet"></label> <textarea id="string-stylesheet"></textarea>
Expand Down
18 changes: 18 additions & 0 deletions documentation/docmaker.json
Original file line number Diff line number Diff line change
Expand Up @@ -1791,6 +1791,24 @@
{
"name": "ele.active",
"descr": "Gets whether the element is active (e.g. on user tap, grab, etc)."
},

{
"name": "ele.pannable",
"descr": "Gets whether the element allows passthrough panning.",
"md": "collection/pannable"
},

{
"name": "eles.panify",
"descr": "Enables passthrough panning on the elements.",
"md": "collection/panify"
},

{
"name": "eles.unpanify",
"descr": "Disables passthrough panning on the elements.",
"md": "collection/unpanify"
}

]
Expand Down
5 changes: 5 additions & 0 deletions documentation/md/collection/panify.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## Examples

```js
cy.$('#j').panify();
```
5 changes: 5 additions & 0 deletions documentation/md/collection/pannable.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## Description

A pannable element allows passthrough panning: The user can pan the graph when dragging on the element. Thus, a pannable element is necessarily ungrabbable.

By default, an edge is pannable and a node is not pannable.
5 changes: 5 additions & 0 deletions documentation/md/collection/unpanify.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## Examples

```js
cy.$('#j').unpanify();
```
6 changes: 5 additions & 1 deletion documentation/md/notation.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ cytoscape({

grabbable: true, // whether the node can be grabbed and moved by the user

pannable: false, // whether dragging the node causes panning instead of grabbing

classes: ['foo', 'bar'] // an array (or a space separated string) of class names that the element has
},

Expand All @@ -140,7 +142,9 @@ cytoscape({
source: 'n1', // the source node id (edge comes from this node)
target: 'n2' // the target node id (edge goes to this node)
// (`source` and `target` can be effectively changed by `eles.move()`)
}
},

pannable: true // whether dragging on the edge causes panning
}
],

Expand Down
1 change: 1 addition & 0 deletions src/collection/element.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ let Element = function( cy, params, restore ){
locked: params.locked ? true : false, // whether the element is locked (cannot be moved)
grabbed: false, // whether the element is grabbed by the mouse; renderer sets this privately
grabbable: params.grabbable === undefined ? true : ( params.grabbable ? true : false ), // whether the element can be grabbed
pannable: params.pannable === undefined ? (group === 'edges' ? true : false) : ( params.pannable ? true : false ), // whether the element has passthrough panning enabled
active: false, // whether the element is active from user interaction
classes: new Set(), // map ( className => true )
animation: { // object for currently-running animations
Expand Down
3 changes: 3 additions & 0 deletions src/collection/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,8 @@ elesfn.json = function( obj ){

checkSwitch( 'grabbable', 'grabify', 'ungrabify' );

checkSwitch( 'pannable', 'panify', 'unpanify' );

if( obj.classes != null ){
ele.classes( obj.classes );
}
Expand All @@ -295,6 +297,7 @@ elesfn.json = function( obj ){
selectable: p.selectable,
locked: p.locked,
grabbable: p.grabbable,
pannable: p.pannable,
classes: null
};

Expand Down
8 changes: 7 additions & 1 deletion src/collection/switch-functions.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ defineSwitchSet( {
defineSwitchSet( {
field: 'grabbable',
overrideField: function( ele ){
return ele.cy().autoungrabify() ? false : undefined;
return ele.cy().autoungrabify() || ele.pannable() ? false : undefined;
},
on: 'grabify',
off: 'ungrabify'
Expand Down Expand Up @@ -148,6 +148,12 @@ defineSwitchSet( {
off: 'unactivate'
} );

defineSwitchSet( {
field: 'pannable',
on: 'panify',
off: 'unpanify'
} );

elesfn.inactive = function(){
let ele = this[0];
if( ele ){
Expand Down
14 changes: 7 additions & 7 deletions src/extensions/renderer/base/load-listeners.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ BRp.load = function(){
var allowPanningPassthrough = function( down, downs ){
var allowPassthrough = true;

if( r.cy.hasCompoundNodes() && down && down.isEdge() ){
// a compound node below the edge => no passthrough panning
if( r.cy.hasCompoundNodes() && down && down.pannable() ){
// a grabbable compound node below the ele => no passthrough panning
for( var i = 0; downs && i < downs.length; i++ ){
var down = downs[i];

Expand Down Expand Up @@ -532,7 +532,7 @@ BRp.load = function(){
r.redrawHint( 'select', true );

r.redraw();
} else if( near.isEdge() ){
} else if( near.pannable() ){
select[4] = 1; // for future pan
}

Expand Down Expand Up @@ -700,7 +700,7 @@ BRp.load = function(){

// Checks primary button down & out of time & mouse not moved much
} else if(
select[4] == 1 && (down == null || down.isEdge())
select[4] == 1 && (down == null || down.pannable())
){

if( isOverThresholdDrag ){
Expand All @@ -723,12 +723,12 @@ BRp.load = function(){
}
}

if( down && down.isEdge() && down.active() ){ down.unactivate(); }
if( down && down.pannable() && down.active() ){ down.unactivate(); }

}

} else {
if( down && down.isEdge() && down.active() ){ down.unactivate(); }
if( down && down.pannable() && down.active() ){ down.unactivate(); }

if( ( !down || !down.grabbed() ) && near != last ){

Expand Down Expand Up @@ -1681,7 +1681,7 @@ BRp.load = function(){
// panning
if(
capture
&& ( start == null || start.isEdge() )
&& ( start == null || start.pannable() )
&& cy.panningEnabled() && cy.userPanningEnabled()
){

Expand Down
28 changes: 27 additions & 1 deletion test/collection-data.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ var cytoscape = require('../src/test.js', cytoscape);
describe('Collection data', function(){

var cy;
var n1;
var n1, n1n2;

// test setup
beforeEach(function(){
Expand All @@ -31,6 +31,7 @@ describe('Collection data', function(){
});

n1 = cy.$('#n1');
n1n2 = cy.$('#n1n2');
});


Expand Down Expand Up @@ -125,6 +126,7 @@ describe('Collection data', function(){
expect( json ).to.have.property('selectable', n1.selectable());
expect( json ).to.have.property('locked', n1.locked());
expect( json ).to.have.property('grabbable', n1.grabbable());
expect( json ).to.have.property('pannable', n1.pannable());
expect( json ).to.have.property('classes');
expect( json.classes === 'odd one' || json.classes === 'one odd' ).to.be.true;

Expand Down Expand Up @@ -235,6 +237,30 @@ describe('Collection data', function(){
expect( evts ).to.equal(1);
});

it('sets pannable', function(){
n1n2.unpanify();

var evts = 0;
n1n2.on('panify', function(){ evts++; });

n1n2.json({ pannable: true });

expect( n1n2.pannable() ).to.be.true;

expect( evts ).to.equal(1);
});

it('sets unpannable', function(){
var evts = 0;
n1n2.on('unpanify', function(){ evts++; });

n1n2.json({ pannable: false });

expect( n1n2.pannable() ).to.be.false;

expect( evts ).to.equal(1);
});

it('moves edge source', function(){
var n1n2 = cy.$('#n1n2');

Expand Down

0 comments on commit bd4f56a

Please sign in to comment.