/**************************************************************************** * Copyright 2017 EPAM Systems * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ***************************************************************************/ import { range } from 'lodash/fp'; import { h, Component } from 'preact'; import { connect } from 'preact-redux'; /** @jsx h */ import element from '../../chem/element'; import Dialog from '../component/dialog'; import Atom from '../component/atom'; import Tabs from '../component/tabs'; import GenericGroups from './generic-groups'; import { fromElement, toElement } from '../structconv'; import { onAction } from '../state'; import { addAtoms } from '../state/toolbar'; const typeSchema = [ { title: 'Single', value: 'atom' }, { title: 'List', value: 'list'}, { title: 'Not List', value: 'not-list'} ]; const beforeSpan = { 'He': 16, 'B': 10, 'Al': 10, 'Hf': 1, 'Rf': 1 }; const main = rowPartition(element.filter(el => el && el.type !== 'actinide' && el.type !== 'lanthanide')); const lanthanides = element.filter(el => el && el.type === 'lanthanide'); const actinides = element.filter(el => el && el.type === 'actinide'); function Header() { return ( { range(0, 19).map(i => ( {i || ''} )) } ); } function TypeChoise({value, onChange, ...props}) { return (
{ typeSchema.map(sc => ( )) }
); } function MainRow({row, caption, refer, selected, onSelect, curEvents}) { return ( {caption} { row.map(el => (typeof el !== 'number') ? ( onSelect(el.label)} {...curEvents(el)}/> ) : ( refer(el) ? ( {refer(el)} ) : ( ) )) } ); } function OutinerRow({row, caption, selected, onSelect, curEvents}) { return ( {caption} { row.map(el => ( onSelect(el.label)} {...curEvents(el)}/> )) } ); } function AtomInfo({el, isInfo}) { const numberStyle = { color: el.color || 'black', 'font-size': '1.2em' }; const elemStyle = { color: el.color || 'black', 'font-weight': 'bold', 'font-size': '2em' }; return (
{element.map[el.label]}
{el.label}
{el.title}
{el.atomic_mass}
); } class PeriodTable extends Component { constructor(props) { super(props); let genType = !!this.props.pseudo ? 'gen' : null; this.state = { type: props.type || genType || 'atom', value: props.values || props.label || null, cur: element[2], isInfo: false }; this.firstType = true; } changeType(type) { if (this.firstType) return this.firstType = false; let pl = this.state.type === 'list' || this.state.type === 'not-list'; let l = type === 'list' || type === 'not-list'; if (l && pl) this.setState({type}); else this.setState({ type, value: type === 'atom' || type === 'gen' ? null : [] }); } selected(label) { let {type, value} = this.state; return (type === 'atom' || type === 'gen') ? value === label : value.includes(label); } onSelect(label) { let {type, value} = this.state; if (type === 'atom' || type === 'gen') this.setState({ value: label }); else { let i = value.indexOf(label); if (i < 0) value.push(label); else value.splice(i, 1); this.setState({ value }); } } result() { let {type, value} = this.state; if (type === 'atom') return value ? { label: value, pseudo: null } : null; else if (type === 'gen') return value ? { type, label: value, pseudo: value} : null; else return value.length ? { type, values: value } : null; } curEvents = (el) => { return { onMouseEnter: () => this.setState({ cur: el, isInfo: true }), onMouseLeave: () => this.setState({ isInfo: false }) }; }; render () { const tabs = ['Table', 'Extended']; let { type } = this.state; return ( this.result()}> this.changeType(i === 0 ? 'atom' : 'gen')}>
{ main.map((row, i) => ( o === 1 && (i === 5 ? '*' : '**')} curEvents={this.curEvents} selected={l => this.selected(l)} onSelect={l => this.onSelect(l)}/> )) } this.selected(l)} onSelect={l => this.onSelect(l)}/> this.selected(l)} onSelect={l => this.onSelect(l)}/>
this.changeType(t) }/>
); } } function rowPartition(elements) { return elements.reduce(function (res, el) { let row = res[el.period - 1]; if (!row) res.push([el]); else { if (beforeSpan[el.label]) row.push(beforeSpan[el.label]); row.push(el); } return res; }, []); } function mapSelectionToProps(editor) { const selection = editor.selection(); if (selection && Object.keys(selection).length === 1 && selection.atoms && Object.keys(selection.atoms).length === 1) { let struct = editor.struct(); let atom = struct.atoms.get(selection.atoms[0]); return { ...fromElement(atom) } } return {}; } export default connect( (store, props) => { if (props.values || props.label) return {}; return mapSelectionToProps(store.editor); }, (dispatch, props) => ({ onOk: (res) => { if (!res.type || res.type === 'atom') dispatch(addAtoms(res.label)); dispatch(onAction({ tool: 'atom', opts: toElement(res) })); props.onOk(res); } }) )(PeriodTable);