AWV-3: Creating mixin for form button components

This commit is contained in:
Bruno Alves de Faria 2016-09-04 22:03:36 -03:00
parent e1da28ca88
commit b1a786071e
7 changed files with 157 additions and 63 deletions

View File

@ -8,6 +8,7 @@ import './section/section.html';
import './section/section.js';
// Mixins
import './mixins/button.js';
import './mixins/component.js';
import './mixins/form.js';
import './mixins/formItem.js';

View File

@ -28,6 +28,11 @@ class Mixin {
// Get the dependent mixin to be initizalized
const mixin = Mixin.getMixin(dependency);
// Throw an error if a cyclic dependency was found on this mixin
if (mixin === this) {
throw new Error(`Mixin ${dependency} has a cyclic dependency.`);
}
// Initizalize the mixin dependencies recursively
mixin.init(template, data, applied, behaviors);
});

View File

@ -0,0 +1,38 @@
import { OHIF } from 'meteor/ohif:core';
import { Template } from 'meteor/templating';
/*
* input: controls a button
*/
OHIF.mixins.button = new OHIF.Mixin({
dependencies: 'formItem',
composition: {
onRendered() {
const instance = Template.instance();
const component = instance.component;
// Set the element to be controlled
component.$element = instance.$('button:first');
},
events: {
'click button'(event, instance) {
const component = instance.component;
// Extract the action and the params
const { action, params } = instance.data;
// Get the current component's API
const api = component.getApi();
// Stop here if no API or action was defined
if (!api || !action || typeof api[action] !== 'function') {
return;
}
// Call the defined action function
api[action].call(this, params);
}
}
}
});

View File

@ -140,6 +140,32 @@ OHIF.mixins.formItem = new OHIF.Mixin({
}
};
// Get the current component API
component.getApi = () => {
const api = instance.data.api;
// Check if the API was not given
if (!api) {
// Stop here if the component is form and API was not given
if (component.isForm) {
return;
}
// Get the current component's form
const form = component.getForm();
// Stop here if the component has no form
if (!form) {
return;
}
return form.getApi();
}
// Return the given API
return api;
};
// Check if the component value is valid in its form's schema
component.validate = () => {
// Get the component's form

View File

@ -2,7 +2,7 @@
{{#baseComponent (extend this
base='baseButton'
class=(concat 'btn ' this.class)
mixins=(concat 'formItem ' this.mixins)
mixins=(concat 'button ' this.mixins)
)}}
{{>UI.contentBlock}}
{{/baseComponent}}

View File

@ -1,51 +1,52 @@
<template name="cineDialog">
{{#form id='cineDialog' class='noselect' schema=instance.schema}}
{{#form id='cineDialog' class='noselect' schema=instance.schema api=instance.api}}
{{>inputHidden key='intervalId'}}
<h5>CINE Controls</h5>
<div class="cine-navigation">
<div class="btn-group">
{{#button id='cineDisplaySetPrevious' title='Previous display set'}}
{{#button action='displaySetPrevious' title='Previous display set'}}
<i class="fa fa-toggle-up"></i>
{{/button}}
{{#button id='cineDisplaySetNext' title='Next display set'}}
{{#button action='displaySetNext' title='Next display set'}}
<i class="fa fa-toggle-down"></i>
{{/button}}
</div>
</div>
<div class="cine-controls">
<div class="btn-group">
{{#button id='cineFirstButton' title='Skip to first image'}}
{{#button action='cineFirst' title='Skip to first image'}}
<i class="fa fa-fast-backward"></i>
{{/button}}
{{#button id='cineBackButton' title='Previous image'}}
{{#button action='cinePrevious' title='Previous image'}}
<i class="fa fa-step-backward"></i>
{{/button}}
{{#button id='cineSlowPlaybackButton' title='Slow playback'}}
{{#button action='cineSlowDown' title='Slow playback'}}
<i class="fa fa-backward"></i>
{{/button}}
{{#button id='cinePlayButton' title='Play / Stop' class=(valueIf isPlaying 'active' '')}}
{{#button action='cineToggle' title='Play / Stop' class=(valueIf isPlaying 'active' '')}}
{{#if isPlaying}}
<i class="fa fa-fw fa-stop"></i>
{{else}}
<i class="fa fa-fw fa-play"></i>
{{/if}}
{{/button}}
{{#button id='cineFastForwardButton' title='Increase playback speed'}}
{{#button action='cineSpeedUp' title='Increase playback speed'}}
<i class="fa fa-forward"></i>
{{/button}}
{{#button id='cineNextButton' title='Next image'}}
{{#button action='cineNext' title='Next image'}}
<i class="fa fa-step-forward"></i>
{{/button}}
{{#button id='cineLastButton' title='Skip to last image'}}
{{#button action='cineLast' title='Skip to last image'}}
<i class="fa fa-fast-forward"></i>
{{/button}}
</div>
</div>
<div class="cine-options">
{{>inputCheckbox key='loop' labelClass='pull-right m-a-0'}}
<div class="fps-section">
{{#inputRange id='cineSlider' key='speed' class='p-a-0' labelClass='form-group m-a-0' labelAsDiv=true}}
{{#inputRange key='framesPerSecond' class='p-a-0' labelClass='form-group m-a-0' labelAsDiv=true}}
{{#section 'labelAfterText'}}:
<span id="fps">{{framerate}}</span>
{{>inputCheckbox id='cineLoopCheckbox' key='loop' labelClass='pull-right m-a-0'}}
{{/section}}
{{/inputRange}}
</div>

View File

@ -1,24 +1,35 @@
import { OHIF } from 'meteor/ohif:core';
import { Template } from 'meteor/templating';
import { SimpleSchema } from 'meteor/aldeed:simple-schema';
import { OHIF } from 'meteor/ohif:core';
import { Session } from 'meteor/session';
import { _ } from 'meteor/underscore';
import { $ } from 'meteor/jquery';
Template.cineDialog.onCreated(() => {
const instance = Template.instance();
// Create the data schema for CINE controls
instance.schema = new SimpleSchema({
intervalId: {
type: Number,
optional: true
},
loop: {
type: Boolean,
label: 'Loop',
defaultValue: true
},
speed: {
framesPerSecond: {
type: Number,
label: 'Cine Speed',
defaultValue: 24,
min: 1,
max: 90
max: 90,
optional: true
}
});
// Update the current viewport frame rate
instance.updateFramerate = rate => {
OHIF.viewer.cine.framesPerSecond = rate;
@ -33,66 +44,78 @@ Template.cineDialog.onCreated(() => {
cornerstoneTools.playClip(element);
}
Session.set('UpdateCine', Random.id());
Session.set('UpdateCINE', Random.id());
};
// Define the actions API
instance.api = {
displaySetPrevious: () => OHIF.viewer.moveDisplaySets(false),
displaySetNext: () => OHIF.viewer.moveDisplaySets(true),
cineToggle: () => toggleCinePlay(),
cineFirst: () => switchToImageByIndex(0),
cineLast: () => switchToImageByIndex(-1),
cinePrevious: () => switchToImageRelative(-1),
cineNext: () => switchToImageRelative(1),
cineSlowDown: () => {
const newValue = OHIF.viewer.cine.framesPerSecond - 1;
if (newValue > 0) {
instance.updateFramerate(newValue);
}
},
cineSpeedUp: () => {
const newValue = OHIF.viewer.cine.framesPerSecond + 1;
if (newValue <= 90) {
instance.updateFramerate(newValue);
}
}
};
// Run this computation every time the active viewport is changed
instance.autorun(() => {
Session.get('activeViewport');
Tracker.afterFlush(() => {
// Get the active viewportElement
const element = getActiveViewportElement();
// Get the cornerstone playClip tool data
const toolData = cornerstoneTools.getToolState(element, 'playClip').data[0];
// Get the cine object
const cine = OHIF.viewer.cine;
// replace the cine values with the tool data
_.extend(cine, toolData);
// Set the defaults
cine.framesPerSecond = cine.framesPerSecond || 24;
cine.loop = _.isUndefined(cine.loop) ? true : cine.loop;
// Set the updated data on the form inputs
instance.$('form:first').data('component').value(cine);
// Update the session to refresh the framerate text
Session.set('UpdateCINE', Random.id());
});
});
});
Template.cineDialog.onRendered(() => {
const instance = Template.instance();
// Make the CINE dialog bounded and draggable
Template.instance().$('#cineDialog').bounded().draggable();
instance.$('#cineDialog').bounded().draggable();
});
Template.cineDialog.events({
'click #cineDisplaySetPrevious'(event, instance) {
OHIF.viewer.moveDisplaySets(false);
},
'click #cineDisplaySetNext'(event, instance) {
OHIF.viewer.moveDisplaySets(true);
},
'click #cineFirstButton'(event, instance) {
switchToImageByIndex(0);
},
'click #cineBackButton'(event, instance) {
switchToImageRelative(-1);
},
'click #cineSlowPlaybackButton'(event, instance) {
const newValue = OHIF.viewer.cine.framesPerSecond - 1;
if (newValue > 0) {
instance.updateFramerate(newValue);
}
},
'click #cinePlayButton'(event, instance) {
toggleCinePlay();
},
'click #cineNextButton'(event, instance) {
switchToImageRelative(1);
},
'click #cineFastForwardButton'(event, instance) {
const newValue = OHIF.viewer.cine.framesPerSecond + 1;
if (newValue <= 90) {
instance.updateFramerate(newValue);
}
},
'click #cineLastButton'(event, instance) {
switchToImageByIndex(-1);
},
'change #cineLoopCheckbox'(event, instance) {
'change [data-key=loop] input'(event, instance) {
const element = getActiveViewportElement();
const playClipToolData = cornerstoneTools.getToolState(element, 'playClip');
playClipToolData.data[0].loop = $(event.currentTarget).is(':checked');
OHIF.viewer.cine.loop = playClipToolData.data[0].loop;
},
'input #cineSlider'(event, instance) {
'input [data-key=framesPerSecond] input'(event, instance) {
// Update the FPS text onscreen
const rate = parseFloat($(event.currentTarget).val());
instance.updateFramerate(rate);
@ -109,7 +132,7 @@ Template.cineDialog.helpers({
},
framerate() {
Session.get('UpdateCine');
Session.get('UpdateCINE');
return OHIF.viewer.cine.framesPerSecond.toFixed(1);
}
});