Skip to content

Commit

Permalink
add viewerReady event
Browse files Browse the repository at this point in the history
Initial Patch by @andreasprlic!
  • Loading branch information
biasmv committed Jan 18, 2015
1 parent 33d96a9 commit 368b68b
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 13 deletions.
47 changes: 42 additions & 5 deletions doc/viewer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ The following code defines a new viewer. This can be done during page load time,
// insert the viewer under the Dom element with id 'gl'.
var viewer = pv.Viewer(document.getElementById('gl'), options);
viewer.on('viewerReady', function() {
// add structure here
});
.. function:: pv.Viewer.quality([value])

Gets (or sets) the default level of detail for the render geometry. This property sets the default parameters for constructing render geometry, for example the number of arcs that are used for tubes, or the number of triangles for one sphere. Accepted values are
Expand Down Expand Up @@ -243,16 +247,49 @@ Proteins come in all sizes and shapes. For optimal viewing, some camera paramete
Viewer Events
---------------------------------------------------------------------------------
Mouse selection events are fired when the user clicks or double clicks a residue/atom.
Custom viewer event handlers can be registered by calling :func:`pv.Viewer.addListener`. These callbacks have the following form.
.. function:: pv.Viewer.addListener(type, callback)
pv.Viewer.on(type, callback)
:param type: The type of event to listen to. Must be either 'atomClicked', 'atomDoubleClicked', or 'viewerReady'.
When an event fires, callbacks registered for that event type are invoked with type-specific arguments. See documentation for the individual events for more details
.. _pv.viewer.events.init:
Initialization Event (viewerReady)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Invoked when the viewer is completely initialized and is ready for displaying of structures. It's recommended to put calls to any of the functions :ref:`described here <pv.viewer.rendering>` into a viewerReady callback as they expect a completely constructed viewer. It's however possible to start loading the structure data before 'viewerReady', as long as they are not added to the viewer.
Callbacks receive the initialized viewer as the first argument.
When the 'viewerReady' callback is registered *after* the page has finished loading, the event callback is directly invoked from :func:`addListener/on<pv.Viewer.addListener>`.
Add a new listener for *atomClicked* or *atomDoubleClicked* events.
The following code example shows how to add a yellow sphere to the center of the scene:
:param type: The type of event to listen to. Must be either 'atomClicked' or 'atomDoubleClicked'
:param callback: The function to receive the callback. If the special value 'center' is passed to the callback, a event handler is installed that centers the viewer on the clicked atom/residue.
.. code-block:: javascript
// insert the viewer under the Dom element with id 'gl'.
var viewer = pv.Viewer(document.getElementById('gl'), options);
viewer.on('viewerReady', function(viewer) {
var customMesh = viewer.customMesh('yellowSphere');
customMesh.addSphere([0,0,0], 5, { color : 'yellow' });
});
.. _pv.viewer.events.mouse:
Mouse Interaction Events (atomClicked, atomDoubleClicked)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Mouse selection events are fired when the user clicks or double clicks a residue/atom.
The arguments of the callback function are *picked*, and *originalEvent* which is the original mouse event. Picked contains information about the scene nodes that was clicked/doubleClicked as well as the actual clicked atom. It also contains a transformation matrix, that if set needs to be applied to the atom's position to get the correct position in global coordinates. This is illustrated in the second example below.
The arguments of the callback function are *picked*, and *originalEvent* which is the original mouse event. Picked contains information about the scene nodes that was clicked/doubleClicked as well as the actual clicked atom. It also contains a transformation matrix, that if set needs to be applied to the atom's position to get the correct position in global coordinates. This is illustrated in the second example below.
The following code simply logs the clicked residue to the console when an atom is clicked.
Expand Down
3 changes: 1 addition & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -153,12 +153,11 @@ <h1><a href="#">PV</a></h1>
outline : true, quality : 'medium',
background : '#333'
});
document.addEventListener('DOMContentLoaded', longHelices);
viewer.addListener('viewerReady', longHelices);

window.addEventListener('resize', function() {
viewer.fitParent();
});

</script>
</body>
</html>
Expand Down
39 changes: 33 additions & 6 deletions src/viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,10 @@ function PV(domElement, opts) {
slabMode : slabModeToStrategy(opts.slabMode),
atomClick: opts.atomClick || null,
fog : true,
atomDoubleClick : 'center', // option is handled below
atomDoubleClick : 'center' // option is handled below
};

this._initialized = true;
this._objects = [];
this._domElement = domElement;
this._redrawRequested = false;
Expand Down Expand Up @@ -432,6 +434,9 @@ PV.prototype = {
},

_initPV : function() {



if (!this._initGL()) {
this._domElement.removeChild(this._canvas);
this._domElement.innerHTML = WEBGL_NOT_SUPPORTED;
Expand Down Expand Up @@ -474,6 +479,11 @@ PV.prototype = {
addListener('mousedown', bind(this, this._mouseDown), false);
this._touchHandler = new TouchHandler(this._canvas, this, this._cam);

if ( this._initialized){
this._initialized = false;
this._dispatchEvent({'name':'viewerReadyEvent'},
'viewerReady',this);
}
return true;
},

Expand Down Expand Up @@ -581,6 +591,8 @@ PV.prototype = {
this._gl.cullFace(this._gl.FRONT);
this._gl.enable(this._gl.BLEND);
this._drawWithPass('normal');


},

setCenter : function(center, ms) {
Expand Down Expand Up @@ -623,7 +635,7 @@ PV.prototype = {
var rect = this._canvas.getBoundingClientRect();
var picked = this.pick(
{ x : event.clientX - rect.left, y : event.clientY - rect.top });
this._dispatchPickedEvent(event, 'atomDoubleClicked', picked);
this._dispatchEvent(event, 'atomDoubleClicked', picked);
this.requestRedraw();
};
})(),
Expand All @@ -640,14 +652,26 @@ PV.prototype = {
} else {
callbacks.push(callback);
}
// in case viewer is already initialized, fire viewerReady immediately.
// Otherwise, the callback would never be invoked in this case:
//
// document.addEventListener('DOMContentLoaded', function() {
// viewer = pv.Viewer(...);
// viewer.on('viewerReady', function(viewer) {
// });
// });
if (eventName === 'viewerReady') {
// don't use dispatch here, we only want this very callback to be
// invoked.
callback(this, null);
}
},

_dispatchPickedEvent : function(event, newEventName, picked) {
_dispatchEvent : function(event, newEventName, arg) {
var callbacks = this.listenerMap[newEventName];
if (callbacks) {

callbacks.forEach(function (callback) {
callback(picked, event);
callback(arg, event);
});
}
},
Expand All @@ -664,7 +688,7 @@ PV.prototype = {
var rect = this._canvas.getBoundingClientRect();
var picked = this.pick(
{ x : event.clientX - rect.left, y : event.clientY - rect.top });
this._dispatchPickedEvent(event, 'atomClicked', picked);
this._dispatchEvent(event, 'atomClicked', picked);
}
event.preventDefault();
if (event.shiftKey === true) {
Expand Down Expand Up @@ -726,6 +750,7 @@ PV.prototype = {
console.error('render mode', mode, 'not supported');
return;
}

return this[mode](name, structure, opts);
},

Expand Down Expand Up @@ -1091,6 +1116,8 @@ PV.prototype = {
}
};

PV.prototype.on = PV.prototype.addListener;

return {
Viewer : function(elem, options) {
return new PV(elem, options);
Expand Down

0 comments on commit 368b68b

Please sign in to comment.