Commit bddfbdb0 authored by Markus Scheidgen's avatar Markus Scheidgen
Browse files

Merge branch 'webglfix' into 'v0.10.0'

Added new HOC that can check for WebGL-support.

See merge request !281
parents 215a1934 efa9b45c
Pipeline #96013 canceled with stages
in 10 minutes and 50 seconds
......@@ -15,9 +15,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react'
import React, { useState } from 'react'
import PropTypes from 'prop-types'
import Alert from '@material-ui/lab/Alert'
import { hasWebGLSupport } from '../utils'
export class ErrorHandler extends React.Component {
state = {
......@@ -63,3 +64,22 @@ export const withErrorHandler = (WrappedComponent, message) => props => (
withErrorHandler.propTypes = ({
message: PropTypes.oneOfType([PropTypes.string, PropTypes.func]) // Provide either a fixed error message or a callback that will receive the error details.
})
export const withWebGLErrorHandler = WrappedComponent => props => {
const hasWebGL = useState(hasWebGLSupport())[0]
// If WebGL is not available, the content cannot be shown.
if (hasWebGL) {
return WrappedComponent({...props})
} else {
return <Alert
severity="info"
>
Could not display the visualization as your browser does not support WebGL content.
</Alert>
}
}
withErrorHandler.propTypes = ({
message: PropTypes.oneOfType([PropTypes.string, PropTypes.func]) // Provide either a fixed error message or a callback that will receive the error details.
})
......@@ -25,12 +25,11 @@ import Browser, { Item, Content, Compartment, List, Adaptor } from './Browser'
import { resolveRef, rootSections } from './metainfo'
import { Title, metainfoAdaptorFactory, DefinitionLabel } from './MetainfoBrowser'
import { Matrix, Number } from './visualizations'
import { Structure } from '../visualization/Structure'
import Structure from '../visualization/Structure'
import BrillouinZone from '../visualization/BrillouinZone'
import BandStructure from '../visualization/BandStructure'
import { ErrorHandler } from '../ErrorHandler'
import DOS from '../visualization/DOS'
import { StructureViewer, BrillouinZoneViewer } from '@lauri-codes/materia'
import Markdown from '../Markdown'
import { UnitSelector } from './UnitSelector'
import { convertSI } from '../../utils'
......@@ -63,10 +62,6 @@ export const unitsState = atom({
default: defaults
})
// Shared instance of the StructureViewer
const viewer = new StructureViewer(undefined, {view: {autoResize: false}})
const bzViewer = new BrillouinZoneViewer(undefined, {view: {autoResize: false}})
// Contains details about the currently visualized system. Used to detect if a
// reload is needed for the StructureViewer.
const visualizedSystem = {}
......@@ -439,7 +434,6 @@ function Overview({section, def}) {
return <Structure
aspectRatio={1}
className={style.structure}
viewer={viewer}
system={system}
></Structure>
// Structure visualization for idealized_structure
......@@ -458,7 +452,6 @@ function Overview({section, def}) {
return <Structure
system={system}
className={style.structure}
viewer={viewer}
aspectRatio={1}>
</Structure>
// Band structure plot for section_k_band
......@@ -476,7 +469,6 @@ function Overview({section, def}) {
></BandStructure>
</Box>
: <BrillouinZone
viewer={bzViewer}
className={style.bands}
data={section}
aspectRatio={1}
......
......@@ -22,7 +22,7 @@ import { apiContext } from '../api'
import ElectronicStructureOverview from '../visualization/ElectronicStructureOverview'
import VibrationalOverview from '../visualization/VibrationalOverview'
import { ApiDialog } from '../ApiDialogButton'
import { Structure } from '../visualization/Structure'
import Structure from '../visualization/Structure'
import NoData from '../visualization/NoData'
import Actions from '../Actions'
import Quantity from '../Quantity'
......
......@@ -32,7 +32,7 @@ import { BrillouinZoneViewer } from '@lauri-codes/materia'
import Floatable from './Floatable'
import Placeholder from '../visualization/Placeholder'
import { scale, distance } from '../../utils'
import { withErrorHandler } from '../ErrorHandler'
import { withErrorHandler, withWebGLErrorHandler } from '../ErrorHandler'
import Actions from '../Actions'
import clsx from 'clsx'
......@@ -273,4 +273,4 @@ BrillouinZone.defaultProps = {
captureName: 'brillouin_zone'
}
export default withErrorHandler(BrillouinZone, 'Could not load Brillouin zone.')
export default withWebGLErrorHandler(withErrorHandler(BrillouinZone, 'Could not load Brillouin zone.'))
......@@ -25,7 +25,7 @@ import {
} from '@material-ui/core'
import { makeStyles } from '@material-ui/core/styles'
import Plot from '../visualization/Plot'
import { Structure } from '../visualization/Structure'
import Structure from '../visualization/Structure'
import { ErrorHandler, withErrorHandler } from '../ErrorHandler'
const useStyles = makeStyles((theme) => {
......
......@@ -41,7 +41,7 @@ import Floatable from './Floatable'
import Placeholder from '../visualization/Placeholder'
import Actions from '../Actions'
import { mergeObjects } from '../../utils'
import { withErrorHandler } from '../ErrorHandler'
import { withErrorHandler, withWebGLErrorHandler } from '../ErrorHandler'
import { useHistory } from 'react-router-dom'
import _ from 'lodash'
import clsx from 'clsx'
......@@ -50,7 +50,7 @@ import clsx from 'clsx'
* Used to show atomistic systems in an interactive 3D viewer based on the
* 'materia'-library.
*/
export const Structure = withErrorHandler(({
function Structure({
className,
classes,
system,
......@@ -63,7 +63,7 @@ export const Structure = withErrorHandler(({
positionsOnly,
sizeLimit,
positionsSubject}
) => {
) {
// States
const [anchorEl, setAnchorEl] = React.useState(null)
const [fullscreen, setFullscreen] = useState(false)
......@@ -378,6 +378,61 @@ export const Structure = withErrorHandler(({
}
actions.push({tooltip: 'Options', onClick: openMenu, content: <MoreVert/>})
const menuItems = [
<MenuItem key='show-bonds'>
<FormControlLabel
control={
<Checkbox
checked={showBonds}
onChange={(event) => { setShowBonds(!showBonds) }}
color='primary'
/>
}
label='Show bonds'
/>
</MenuItem>
]
if (finalSystem?.cell) {
menuItems.push(...[
<MenuItem key='show-axis'>
<FormControlLabel
control={
<Checkbox
checked={showLatticeConstants}
onChange={(event) => { setShowLatticeConstants(!showLatticeConstants) }}
color='primary'
/>
}
label='Show lattice constants'
/>
</MenuItem>,
<MenuItem key='show-cell'>
<FormControlLabel
control={
<Checkbox
checked={showCell}
onChange={(event) => { setShowCell(!showCell) }}
color='primary'
/>
}
label='Show simulation cell'
/>
</MenuItem>,
<MenuItem key='wrap'>
<FormControlLabel
control={
<Checkbox
checked={wrap}
onChange={(event) => { setWrap(!wrap) }}
color='primary'
/>
}
label='Wrap positions'
/>
</MenuItem>
])
}
const content = <Box className={styles.container}>
{fullscreen && <Typography className={styles.title} variant="h6">Structure</Typography>}
{systems && <ToggleButtonGroup
......@@ -403,58 +458,7 @@ export const Structure = withErrorHandler(({
open={open}
onClose={closeMenu}
>
<MenuItem key='show-bonds'>
<FormControlLabel
control={
<Checkbox
checked={showBonds}
onChange={(event) => { setShowBonds(!showBonds) }}
color='primary'
/>
}
label='Show bonds'
/>
</MenuItem>
{finalSystem?.cell &&
<>
<MenuItem key='show-axis'>
<FormControlLabel
control={
<Checkbox
checked={showLatticeConstants}
onChange={(event) => { setShowLatticeConstants(!showLatticeConstants) }}
color='primary'
/>
}
label='Show lattice constants'
/>
</MenuItem>
<MenuItem key='show-cell'>
<FormControlLabel
control={
<Checkbox
checked={showCell}
onChange={(event) => { setShowCell(!showCell) }}
color='primary'
/>
}
label='Show simulation cell'
/>
</MenuItem>
<MenuItem key='wrap'>
<FormControlLabel
control={
<Checkbox
checked={wrap}
onChange={(event) => { setWrap(!wrap) }}
color='primary'
/>
}
label='Wrap positions'
/>
</MenuItem>
</>
}
{menuItems}
</Menu>
</div>
</Box>
......@@ -463,7 +467,7 @@ export const Structure = withErrorHandler(({
{content}
</Floatable>
</Box>
}, 'Could not load structure.')
}
Structure.propTypes = {
className: PropTypes.string,
......@@ -490,3 +494,5 @@ Structure.defaultProps = {
captureName: 'structure',
sizeLimit: 300
}
export default withWebGLErrorHandler(withErrorHandler(Structure, 'Could not load structure.'))
......@@ -335,3 +335,20 @@ export function authorList(entry, expanded) {
return nameList(entry.authors || [], expanded)
}
}
/**
* Returns whether the used browser supports WebGL.
* @return {boolean} Is WebGL supported.
*/
export function hasWebGLSupport() {
let w = window
try {
let canvas = document.createElement('canvas')
return !!(w.WebGLRenderingContext && (
canvas.getContext('webgl') ||
canvas.getContext('experimental-webgl'))
)
} catch (e) {
return false
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment