Skip to content

Commit

Permalink
Merge pull request #208 from will-moore/cache_image_settings
Browse files Browse the repository at this point in the history
Cache image settings
  • Loading branch information
jburel authored Sep 28, 2018
2 parents 464da4a + 8661270 commit 4dc3295
Show file tree
Hide file tree
Showing 11 changed files with 359 additions and 149 deletions.
11 changes: 11 additions & 0 deletions css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,17 @@ thumbnail-slider img {
flex-grow: 1;
}

/* We don't want channel mode buttons to appear focussed */
.channel-mode button.btn:focus,
.channel-mode button.btn,
.channel-mode button.btn.focus {
outline: none;
}
.channel-mode button.focus {
background: #ffffff;
border-color: #ccc;
}

.comment-checkbox {
margin: 5px 0px 0px 10px;
}
Expand Down
49 changes: 32 additions & 17 deletions ol3-viewer/src/ome/ol3/Viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -267,13 +267,13 @@ ome.ol3.Viewer = function(id, options) {
* @param {?function} initHook an optional initialization handler
* @private
*/
this.initialize_ = function(scope, postSuccessHook, initHook) {
this.initialize_ = function(postSuccessHook, initHook) {
// can happen if we instantitate the viewer without id
if (scope.id_ < 0) return;
if (this.id_ < 0) return;

// use handed in image info instead of requesting it
if (scope.image_info_ !== null) {
scope.bootstrapOpenLayers(postSuccessHook, initHook);
if (this.image_info_ !== null) {
this.bootstrapOpenLayers(postSuccessHook, initHook);
return;
}

Expand All @@ -291,24 +291,24 @@ ome.ol3.Viewer = function(id, options) {
return;
}
// store response internally to be able to work with it later
scope.image_info_ = data;
this.image_info_ = data;

// delegate
scope.bootstrapOpenLayers(postSuccessHook, initHook);
};
this.bootstrapOpenLayers(postSuccessHook, initHook);
}.bind(this);

// define request settings
var reqParams = {
"server" : scope.getServer(),
"uri" : scope.getPrefixedURI(ome.ol3.WEBGATEWAY) +
'/imgData/' + scope.id_,
"server" : this.getServer(),
"uri" : this.getPrefixedURI(ome.ol3.WEBGATEWAY) +
'/imgData/' + this.id_,
"jsonp" : true, // this will only count if we are cross-domain
"success" : success,
"error" : function(error) {
console.error("Error retrieving image info for id: " +
scope.id_ +
this.id_ +
((error && error.length > 0) ? (" => " + error) : ""));
}
}.bind(this)
};

// send request
Expand All @@ -319,7 +319,7 @@ ome.ol3.Viewer = function(id, options) {
// for cross domain we check whether we need to have a login made, otherwise
// we redirect to there ...
if (ome.ol3.utils.Net.isSameOrigin(this.server_) || this.haveMadeCrossOriginLogin_) {
this.initialize_(this);
this.initialize_();
} else ome.ol3.utils.Net.makeCrossDomainLoginRedirect(this.server_);
};
goog.inherits(ome.ol3.Viewer, ol.Object);
Expand Down Expand Up @@ -357,7 +357,7 @@ ome.ol3.Viewer.prototype.bootstrapOpenLayers = function(postSuccessHook, initHoo
tmp.push(1 / this.image_info_['zoomLevelScaling'][r]);
zoomLevelScaling = tmp.reverse();
}
var zoom= zoomLevelScaling ? zoomLevelScaling.length : -1;
var zoom = zoomLevelScaling ? zoomLevelScaling.length : -1;

// get the initial projection
var initialProjection =
Expand Down Expand Up @@ -437,8 +437,7 @@ ome.ol3.Viewer.prototype.bootstrapOpenLayers = function(postSuccessHook, initHoo

// copy needed channels info
var channels = [];
for (var c in this.image_info_['channels']) {
var oldC = this.image_info_['channels'][c];
this.image_info_['channels'].forEach(function(oldC, c) {
var newC = {
"active" : oldC['active'],
"label" : typeof oldC['label'] === 'string' ? oldC['label'] : c,
Expand All @@ -459,7 +458,7 @@ ome.ol3.Viewer.prototype.bootstrapOpenLayers = function(postSuccessHook, initHoo
newC['coefficient'] = oldC['coefficient'];
}
channels.push(newC);
}
});

var isTiled =
typeof this.image_info_['tiles'] === 'boolean' &&
Expand Down Expand Up @@ -583,6 +582,17 @@ ome.ol3.Viewer.prototype.bootstrapOpenLayers = function(postSuccessHook, initHoo
viewer, "IMAGE_VIEWER_INTERACTION", viewer.getViewParameters());
};

// get cached initial viewer center etc.
if (this.image_info_['center'] || this.image_info_['resolution'] || this.image_info_['rotation']) {
let center = this.image_info_['center'];
let resolution = this.image_info_['resolution'];
let rotation = this.image_info_['rotation'];
// Need to wait for viewer to be built before this works:
setTimeout(function() {
this.setViewParameters(center, resolution, rotation);
}.bind(this), 100)
}

// listens to resolution changes
this.onViewResolutionListener =
ol.events.listen( // register a resolution handler for zoom display
Expand Down Expand Up @@ -2263,6 +2273,11 @@ goog.exportSymbol(
ome.ol3.Viewer,
OME);

goog.exportProperty(
ome.ol3.Viewer.prototype,
'getId',
ome.ol3.Viewer.prototype.getId);

goog.exportProperty(
ome.ol3.Viewer.prototype,
'show',
Expand Down
38 changes: 38 additions & 0 deletions src/app/context.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,14 @@ export default class Context {
*/
image_configs = new Map();

/**
* a map for unsaved image settings
*
* @memberof Context
* @type {Map}
*/
cached_image_settings = {};

/**
* the initial type the viewer was opened with
*
Expand Down Expand Up @@ -655,6 +663,7 @@ export default class Context {
// store the image config in the map and make it the selected one
this.image_configs.set(image_config.id, image_config);
this.selectConfig(image_config.id);
// Call bind() to initialize image data loading
image_config.bind();
}

Expand Down Expand Up @@ -782,6 +791,35 @@ export default class Context {
return configs;
}

/**
* Sets a cache of image settings.
* Settings object contains 'channels' (same as imgData JSON)
* 'projection', 'model', 'time', 'plane'
*
* @memberof Context
* @param {number} id the Image ID
* @param {settings} Object
*/
setCachedImageSettings(image_id, settings) {
const old = this.cached_image_settings[image_id] || {};
this.cached_image_settings[image_id] = Object.assign({}, old, settings);
}

/**
* Retrieves last viewed (unsaved) settings for an image by ID.
* Object returned contains 'channels' (same as imgData JSON)
* 'projection', 'model', 'time', 'plane'
*
* @memberof Context
* @param {number} id the Image ID
* @return {Object} similar to imgData JSON
*/
getCachedImageSettings(image_id) {
if (this.cached_image_settings[image_id]) {
return this.cached_image_settings[image_id];
}
}

/**
* Convenience or short hand way of publishing via the internal eventbus.
* It will just delegate whatever you hand it as arguments
Expand Down
1 change: 1 addition & 0 deletions src/app/right-hand-panel.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export class RightHandPanel {
this.context = context;
this.bindingEngine = bindingEngine;
// set initial image config
// NB: This will likely be null initially
this.image_config = this.context.getSelectedImageConfig();
}

Expand Down
3 changes: 2 additions & 1 deletion src/controls/dimension-slider.js
Original file line number Diff line number Diff line change
Expand Up @@ -411,13 +411,14 @@ export default class DimensionSlider {
conf.addHistory(entries);
this.add_projection_history = false;
};
if (!conf.image_info.projection_opts.synced)
if (!conf.image_info.projection_opts.synced) {
this.context.publish(IMAGE_SETTINGS_CHANGE, {
config_id: conf.id,
sync_group: conf.sync_group,
projection: conf.image_info.projection,
projection_opts: Object.assign({}, conf.image_info.projection_opts)
});
}
}

/**
Expand Down
124 changes: 124 additions & 0 deletions src/model/image_config.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import Misc from '../utils/misc';
import History from './history';
import {WEBGATEWAY} from '../utils/constants';
import {VIEWER_SET_SYNC_GROUP} from '../events/events';
import {CHANNEL_SETTINGS_MODE} from '../utils/constants';

/**
* Holds the combined data/model that is relevant to working with an image:
Expand Down Expand Up @@ -150,6 +151,129 @@ export default class ImageConfig extends History {
this.revision++;
}

/**
* Applies the rendering settings, keeping a history of the old settings
*
* @param {Object} rdef the rendering definition
* @param {boolean} for_pasting true if rdef supplied is for pasting of settings, false otherwise
* @memberof Settings
*/
applyRenderingSettings(rdef, for_pasting=true) {
if (rdef === null) return;

if (typeof for_pasting !== 'boolean') for_pasting = true;
let imgInfo = this.image_info;
let history = [];

// model (color/greyscale)
let model =
(for_pasting && typeof rdef.m === 'string' && rdef.m.length > 0) ?
rdef.m.toLowerCase() :
(!for_pasting && typeof rdef.model === 'string' &&
rdef.model.length > 0) ?
(rdef.model.toLowerCase() === 'greyscale') ?
"greyscale" : "color" : null;
if (model && (model[0] === 'g' || model[0] === 'c')) {
let oldValue = imgInfo.model;
imgInfo.model = model[0] === 'g' ? "greyscale" : "color";
if (oldValue !== imgInfo.model)
history.push({ // add to history if different
prop: ['image_info', 'model'],
old_val : oldValue,
new_val: imgInfo.model,
type: 'string'});
}

// copy channel values and add change to history
let channels = for_pasting ?
Misc.parseChannelParameters(rdef.c, rdef.maps) : rdef.c;
let mode = CHANNEL_SETTINGS_MODE.MIN_MAX;
if (channels)
for (let i=0;i<channels.length;i++) {
if (typeof imgInfo.channels[i] !== 'object') continue;
let actChannel = imgInfo.channels[i];
let copiedChannel = channels[i];
if (actChannel.active !== copiedChannel.active) {
history.push({
prop: ['image_info', 'channels', '' + i, 'active'],
old_val : actChannel.active,
new_val: copiedChannel.active,
type: 'boolean'});
actChannel.active = copiedChannel.active;
}
if (actChannel.window.start !== copiedChannel.start) {
history.push({
prop: ['image_info', 'channels',
'' + i, 'window', 'start'],
old_val : actChannel.window.start,
new_val: copiedChannel.start,
type: 'number'});
actChannel.window.start = copiedChannel.start;
}
if (actChannel.window.end !== copiedChannel.end) {
history.push({
prop: ['image_info', 'channels',
'' + i, 'window', 'end'],
old_val : actChannel.window.end,
new_val: copiedChannel.end,
type: 'number'});
actChannel.window.end = copiedChannel.end;
}
let newColor =
typeof copiedChannel.lut === 'string' &&
copiedChannel.lut.length > 0 ?
copiedChannel.lut : copiedChannel.color;
if (actChannel.color !== newColor) {
history.push({
prop: ['image_info', 'channels', '' + i, 'color'],
old_val : actChannel.color,
new_val: newColor,
type: 'string'});
actChannel.color = copiedChannel.color;
}
if (typeof copiedChannel.inverted === 'undefined')
copiedChannel.inverted = null;
if (actChannel.inverted !==
copiedChannel.inverted) {
history.push({
prop: ['image_info',
'channels', '' + i, 'inverted'],
old_val : actChannel.inverted,
new_val: copiedChannel.inverted,
type: 'boolean'});
actChannel.inverted =
copiedChannel.inverted;
}
if (typeof copiedChannel['family'] === 'string' &&
copiedChannel['family'] !== "" &&
typeof copiedChannel['coefficient'] === 'number' &&
!isNaN(copiedChannel['coefficient'])) {
history.push({
prop: ['image_info', 'channels', '' + i, 'family'],
old_val : actChannel.family,
new_val: copiedChannel.family,
type: 'string'});
actChannel.family = copiedChannel.family;
history.push({
prop: ['image_info', 'channels', '' + i, 'coefficient'],
old_val : actChannel.coefficient,
new_val: copiedChannel.coefficient,
type: 'string'});
actChannel.coefficient = copiedChannel.coefficient;
}
};
if (history.length > 0) {
history.splice(0, 0,
{ prop: ['image_info','initial_values'],
old_val : true,
new_val: true,
type : "boolean"});
this.addHistory(history);
}

this.changed();
}

/**
* Adds/removes the image config from the sync group
* @param {string|null} sync_group the new sync group or null
Expand Down
Loading

0 comments on commit 4dc3295

Please sign in to comment.