Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add toggle color layer visibility button #3943

Merged
merged 12 commits into from
Mar 29, 2019
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.md).
- The HTML template now includes SEO tags for demo instances and hides internal instances from search engines.
- A maximize-button was added to the viewports in the annotation view. Maximization can also be toggled with the `.` shortcut. [#3876](https://github.com/scalableminds/webknossos/pull/3876)
- [webknossos-connect](https://github.com/scalableminds/webknossos-connect) now starts with webKnossos on local and development instances by default. [#3913](https://github.com/scalableminds/webknossos/pull/3913)
- Added a button for each color layer that toggles its visibility. [#3943](https://github.com/scalableminds/webknossos/pull/3943)
- Added a button for each color layer to enable/disable the layer. [#3943](https://github.com/scalableminds/webknossos/pull/3943)

### Changed
- Improved the flight mode performance for tracings with very large trees (>80.000 nodes). [#3880](https://github.com/scalableminds/webknossos/pull/3880)
Expand Down
4 changes: 2 additions & 2 deletions docs/tracing_ui.md
Original file line number Diff line number Diff line change
Expand Up @@ -275,9 +275,9 @@ For multi-layer datasets, each layer can be adjusted separately.
#### Colors
- `Brightness`: Increase / Decrease the brightness of the data layer.
- `Contrast`: Increase / Decrease the contrast of the data layer.
- `Opacity`: Increase / Decrease the opacityof the data layer.
- `Opacity`: Increase / Decrease the opacity of the data layer.
- `Color`: Every data layer can be colored to make them easily identifiable. By default, all layers have a white overlay, showing the true, raw black & white data.
- `Visibility`: Use the eye icon on the right side of the name of the data layer to toggle its visibility.
- `Visibility`: Use the eye icon on the right side of the name of the data layer to enable/disable this layer.

#### Segmentation
- `Segmentation Opacity`: Increases / Decreases the opacity of the segmentation layer. A low value will make the segmentation almost transparent letting you see the underlying data layers more clearly. A high value will make the segmentation opaque which is useful for adjusting and reviewing the exact fit of the segmentation layer. Only possible if your dataset has a segmentation layer.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ class DatasetImportView extends React.PureComponent<Props, State> {
brightness: 0,
contrast: 1,
color: [255, 255, 255],
isVisible: true,
isDisabled: false,
};
const datasetDefaultConfiguration = (await getDatasetDefaultConfiguration(
this.props.datasetId,
Expand Down
18 changes: 3 additions & 15 deletions frontend/javascripts/libs/datasource.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,19 +69,7 @@
"name": { "type": "string" },
"category": { "enum": ["color", "segmentation"] },
"elementClass": {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my ide beautifies code again 🤔
As this is accepted by prettier I suggest to keep it this way.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, in the long run, this can be quite cumbersome. This is especially prone to merge conflicts. Can you please disable any IDE auto-formatting which differs from prettiers behavior?

"enum": [
"uint8",
"uint16",
"uint24",
"uint32",
"uint64",
"float,",
"double",
"int8",
"int16",
"int32",
"int64"
]
"enum": ["uint8", "uint16", "uint24", "uint32", "uint64", "float,", "double", "int8", "int16", "int32", "int64"]
}
},
"required": ["name", "category", "elementClass"]
Expand Down Expand Up @@ -143,9 +131,9 @@
"brightness": { "type": "number" },
"contrast": { "type": "number" },
"color": { "$ref": "#/definitions/types::Vector3" },
"isVisible": { "type": "boolean" }
"isDisabled": { "type": "boolean" }
},
"required": ["brightness", "contrast", "color", "isVisible"]
"required": ["brightness", "contrast", "color", "isDisabled"]
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion frontend/javascripts/libs/datasource.types.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,6 @@ export type LayerUserConfiguration = {
brightness: number,
contrast: number,
color: Vector3,
isVisible: boolean,
isDisabled: boolean,
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,7 @@ class PlaneMaterialFactory {
updateUniformsForLayer(settings: DatasetLayerConfiguration, name: string): void {
this.uniforms[`${name}_brightness`].value = settings.brightness / 255;
this.uniforms[`${name}_contrast`].value = settings.contrast;
this.uniforms[`${name}_alpha`].value = settings.isVisible ? settings.alpha / 100 : 0;
this.uniforms[`${name}_alpha`].value = !settings.isDisabled ? settings.alpha / 100 : 0;
MichaelBuessemeyer marked this conversation as resolved.
Show resolved Hide resolved

if (settings.color != null) {
const color = this.convertColor(settings.color);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ function SettingsReducer(state: OxalisState, action: Action): OxalisState {
contrast: 1,
color: [255, 255, 255],
alpha: 100,
isVisible: true,
isDisabled: false,
},
initialLayerSettings[layer.name],
);
Expand All @@ -123,7 +123,7 @@ function SettingsReducer(state: OxalisState, action: Action): OxalisState {
};
}
case "SET_VIEW_MODE": {
const allowedModes = state.tracing.restrictions.allowedModes;
const { allowedModes } = state.tracing.restrictions;
if (allowedModes.includes(action.viewMode)) {
return updateTemporaryConfig(state, { viewMode: action.viewMode });
} else {
Expand Down
2 changes: 1 addition & 1 deletion frontend/javascripts/oxalis/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ export type DatasetLayerConfiguration = {|
+brightness: number,
+contrast: number,
+alpha: number,
+isVisible: boolean,
+isDisabled: boolean,
|};

export type LoadingStrategy = "BEST_QUALITY_FIRST" | "PROGRESSIVE_QUALITY";
Expand Down
56 changes: 34 additions & 22 deletions frontend/javascripts/oxalis/view/settings/dataset_settings_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class DatasetSettings extends React.PureComponent<DatasetSettingsProps> {
isLastLayer: boolean,
) => {
const isRGB = isRgb(this.props.dataset, layerName);
const { brightness, contrast, alpha, color, isVisible } = layer;
const { brightness, contrast, alpha, color, isDisabled } = layer;
return (
<div key={layerName}>
<Row>
Expand All @@ -74,28 +74,23 @@ class DatasetSettings extends React.PureComponent<DatasetSettingsProps> {
<Tag style={{ cursor: "default", marginLeft: 8 }} color={isRGB && "#1890ff"}>
{isRGB ? "24-bit" : "8-bit"} Layer
</Tag>
{alpha > 0 && isVisible ? (
<Tooltip title="Make this color layer invisible.">
<Icon
type="eye"
onClick={() => this.props.onChangeLayer(layerName, "isVisible", false)}
style={{ marginTop: 4, marginLeft: 8, cursor: "pointer" }}
/>
</Tooltip>
) : (
<Tooltip title="Make this color layer visible.">
<Icon
type="eye-o"
onClick={() => this.props.onChangeLayer(layerName, "isVisible", true)}
style={{ marginTop: 4, marginLeft: 8, cursor: "pointer" }}
/>
</Tooltip>
)}
{/* TODO adjust types of the icons when upgrading antd. */}
<Tooltip title={isDisabled ? "Enable" : "Disable"}>
<Icon
MichaelBuessemeyer marked this conversation as resolved.
Show resolved Hide resolved
type={isDisabled ? "eye-o" : "eye"}
onClick={() => this.props.onChangeLayer(layerName, "isDisabled", !isDisabled)}
style={{ marginTop: 4, marginLeft: 8, cursor: "pointer" }}
/>
</Tooltip>
<Tooltip title="If you are having trouble finding your data, webKnossos can try to find a position which contains data.">
<Icon
type="scan"
onClick={() => this.handleFindData(layerName)}
style={{ float: "right", marginTop: 4, cursor: "pointer" }}
onClick={!isDisabled ? () => this.handleFindData(layerName) : () => {}}
style={{
float: "right",
marginTop: 4,
cursor: !isDisabled ? "pointer" : "not-allowed",
}}
/>
</Tooltip>
</Col>
Expand All @@ -107,6 +102,7 @@ class DatasetSettings extends React.PureComponent<DatasetSettingsProps> {
step={5}
value={brightness}
onChange={_.partial(this.props.onChangeLayer, layerName, "brightness")}
disabled={isDisabled}
/>
<NumberSliderSetting
label="Contrast"
Expand All @@ -115,19 +111,22 @@ class DatasetSettings extends React.PureComponent<DatasetSettingsProps> {
step={0.1}
value={contrast}
onChange={_.partial(this.props.onChangeLayer, layerName, "contrast")}
disabled={isDisabled}
/>
<NumberSliderSetting
label="Opacity"
min={0}
max={100}
value={alpha}
onChange={_.partial(this.props.onChangeLayer, layerName, "alpha")}
disabled={isDisabled}
/>
<ColorSetting
label="Color"
value={Utils.rgbToHex(color)}
onChange={_.partial(this.props.onChangeLayer, layerName, "color")}
className="ant-btn"
disabled={isDisabled}
/>
{!isLastLayer && <Divider />}
</div>
Expand Down Expand Up @@ -193,16 +192,29 @@ class DatasetSettings extends React.PureComponent<DatasetSettingsProps> {
);
}

renderPanelHeader = (hasDisabledLayers: boolean) =>
hasDisabledLayers ? (
<span>
Color Layers
<Tooltip title="Not all layers are currently visible.">
<Icon type="exclamation-circle-o" style={{ marginLeft: 16, color: "coral" }} />
</Tooltip>
</span>
) : (
"Color Layers"
);

render() {
const { layers } = this.props.datasetConfiguration;
const colorSettings = Object.entries(layers).map((entry, index) =>
// $FlowFixMe Object.entries returns mixed for Flow
this.getColorSettings(entry, index, index === _.size(layers) - 1),
);

const hasDisabledLayers =
Object.keys(layers).find(layerName => layers[layerName].isDisabled) != null;
MichaelBuessemeyer marked this conversation as resolved.
Show resolved Hide resolved
return (
<Collapse bordered={false} defaultActiveKey={["1", "2", "3", "4"]}>
<Panel header="Color Layers" key="1">
<Panel header={this.renderPanelHeader(hasDisabledLayers)} key="1">
{colorSettings}
</Panel>
{this.props.hasSegmentation ? this.getSegmentationPanel() : null}
Expand Down
34 changes: 28 additions & 6 deletions frontend/javascripts/oxalis/view/settings/setting_input_views.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ type NumberSliderSettingProps = {
max: number,
min: number,
step: number,
disabled: boolean,
};

export class NumberSliderSetting extends React.PureComponent<NumberSliderSettingProps> {
static defaultProps = {
min: 1,
step: 1,
disabled: false,
};

_onChange = (_value: number) => {
Expand All @@ -27,15 +29,22 @@ export class NumberSliderSetting extends React.PureComponent<NumberSliderSetting
};

render() {
const { value, label, max, min, step, onChange } = this.props;
const { value, label, max, min, step, onChange, disabled } = this.props;

return (
<Row type="flex" align="middle">
<Col span={9}>
<label className="setting-label">{label}</label>
</Col>
<Col span={8}>
<Slider min={min} max={max} onChange={onChange} value={value} step={step} />
<Slider
min={min}
max={max}
onChange={onChange}
value={value}
step={step}
disabled={disabled}
/>
</Col>
<Col span={5}>
<InputNumber
Expand All @@ -45,6 +54,7 @@ export class NumberSliderSetting extends React.PureComponent<NumberSliderSetting
value={value}
onChange={this._onChange}
size="small"
disabled={disabled}
/>
</Col>
</Row>
Expand Down Expand Up @@ -337,24 +347,30 @@ type ColorSettingPropTypes = {
value: string,
label: string,
onChange: (value: Vector3) => void,
disabled: boolean,
};

export class ColorSetting extends React.PureComponent<ColorSettingPropTypes> {
static defaultProps = {
disabled: false,
};

onColorChange = (evt: SyntheticInputEvent<>) => {
this.props.onChange(Utils.hexToRgb(evt.target.value));
};

render() {
const { label, value, disabled } = this.props;
return (
<Row className="margin-bottom" align="top">
<Col span={9}>
<label className="setting-label">{this.props.label}</label>
<label className="setting-label">{label}</label>
</Col>
<Col span={15}>
<div
id="color-picker-wrapper"
style={{
backgroundColor: this.props.value,
backgroundColor: value,
display: "block",
width: 16,
height: 16,
Expand All @@ -364,9 +380,15 @@ export class ColorSetting extends React.PureComponent<ColorSettingPropTypes> {
>
<input
type="color"
style={{ opacity: 0, display: "block", border: "none", cursor: "pointer" }}
style={{
opacity: 0,
display: "block",
border: "none",
cursor: !disabled ? "pointer" : "not-allowed",
MichaelBuessemeyer marked this conversation as resolved.
Show resolved Hide resolved
}}
onChange={this.onColorChange}
value={this.props.value}
value={value}
disabled={disabled}
/>
</div>
</Col>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ const datasetConfigOverrides: { [key: string]: DatasetConfiguration } = {
fourBit: false,
interpolation: true,
layers: {
color: { color: [255, 255, 255], contrast: 1, brightness: 0, alpha: 100, isVisible: true },
color: { color: [255, 255, 255], contrast: 1, brightness: 0, alpha: 100, isDisabled: true },
},
quality: 0,
segmentationOpacity: 0,
Expand Down