Hide top row buttons in bitmap mode (#423)
93
src/components/fixed-tools/fixed-tools.css
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
@import "../../css/colors.css";
|
||||||
|
@import "../../css/units.css";
|
||||||
|
|
||||||
|
.row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.costume-input {
|
||||||
|
width: 8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod-dashed-border {
|
||||||
|
border-right: 1px dashed $ui-pane-border;
|
||||||
|
padding-right: calc(2 * $grid-unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod-unselect {
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
$border-radius: 0.25rem;
|
||||||
|
|
||||||
|
.button-group-button {
|
||||||
|
display: inline-block;
|
||||||
|
border: 1px solid $ui-pane-border;
|
||||||
|
border-radius: 0;
|
||||||
|
border-left: none;
|
||||||
|
padding: .35rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group-button:last-of-type {
|
||||||
|
border-top-right-radius: $border-radius;
|
||||||
|
border-bottom-right-radius: $border-radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group-button:first-of-type {
|
||||||
|
border-left: 1px solid $ui-pane-border;
|
||||||
|
border-top-left-radius: $border-radius;
|
||||||
|
border-bottom-left-radius: $border-radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group-button.mod-left-border {
|
||||||
|
border-left: 1px solid $ui-pane-border;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group-button.mod-no-right-border {
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group-button-icon {
|
||||||
|
width: 1.25rem;
|
||||||
|
height: 1.25rem;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod-context-menu {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod-top-divider {
|
||||||
|
border-top: 1px solid $ui-pane-border;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod-menu-item {
|
||||||
|
display: flex;
|
||||||
|
margin: 0 -$grid-unit;
|
||||||
|
min-width: 6.25rem;
|
||||||
|
padding: calc(3 * $grid-unit);
|
||||||
|
white-space: nowrap;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: 0.1s ease;
|
||||||
|
align-items: center;
|
||||||
|
font-family: "Helvetica Neue", Helvetica, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod-disabled {
|
||||||
|
cursor: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod-menu-item:hover {
|
||||||
|
background: $motion-transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mod-disabled:hover {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-item-icon {
|
||||||
|
margin-right: calc(2 * $grid-unit);
|
||||||
|
}
|
309
src/components/fixed-tools/fixed-tools.jsx
Normal file
|
@ -0,0 +1,309 @@
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import {connect} from 'react-redux';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React from 'react';
|
||||||
|
import MediaQuery from 'react-responsive';
|
||||||
|
|
||||||
|
import {shouldShowGroup, shouldShowUngroup} from '../../helper/group';
|
||||||
|
import {shouldShowBringForward, shouldShowSendBackward} from '../../helper/order';
|
||||||
|
|
||||||
|
import BufferedInputHOC from '../forms/buffered-input-hoc.jsx';
|
||||||
|
import Button from '../button/button.jsx';
|
||||||
|
import ButtonGroup from '../button-group/button-group.jsx';
|
||||||
|
import Dropdown from '../dropdown/dropdown.jsx';
|
||||||
|
import {defineMessages, injectIntl, intlShape} from 'react-intl';
|
||||||
|
import Formats from '../../lib/format';
|
||||||
|
import Input from '../forms/input.jsx';
|
||||||
|
import InputGroup from '../input-group/input-group.jsx';
|
||||||
|
import Label from '../forms/label.jsx';
|
||||||
|
import LabeledIconButton from '../labeled-icon-button/labeled-icon-button.jsx';
|
||||||
|
import {isVector} from '../../lib/format';
|
||||||
|
import layout from '../../lib/layout-constants';
|
||||||
|
import styles from './fixed-tools.css';
|
||||||
|
|
||||||
|
import groupIcon from './icons/group.svg';
|
||||||
|
import redoIcon from './icons/redo.svg';
|
||||||
|
import sendBackIcon from './icons/send-back.svg';
|
||||||
|
import sendBackwardIcon from './icons/send-backward.svg';
|
||||||
|
import sendForwardIcon from './icons/send-forward.svg';
|
||||||
|
import sendFrontIcon from './icons/send-front.svg';
|
||||||
|
import undoIcon from './icons/undo.svg';
|
||||||
|
import ungroupIcon from './icons/ungroup.svg';
|
||||||
|
|
||||||
|
const BufferedInput = BufferedInputHOC(Input);
|
||||||
|
const messages = defineMessages({
|
||||||
|
costume: {
|
||||||
|
id: 'paint.paintEditor.costume',
|
||||||
|
description: 'Label for the name of a costume',
|
||||||
|
defaultMessage: 'Costume'
|
||||||
|
},
|
||||||
|
group: {
|
||||||
|
defaultMessage: 'Group',
|
||||||
|
description: 'Label for the button to group shapes',
|
||||||
|
id: 'paint.paintEditor.group'
|
||||||
|
},
|
||||||
|
ungroup: {
|
||||||
|
defaultMessage: 'Ungroup',
|
||||||
|
description: 'Label for the button to ungroup shapes',
|
||||||
|
id: 'paint.paintEditor.ungroup'
|
||||||
|
},
|
||||||
|
undo: {
|
||||||
|
defaultMessage: 'Undo',
|
||||||
|
description: 'Alt to image for the button to undo an action',
|
||||||
|
id: 'paint.paintEditor.undo'
|
||||||
|
},
|
||||||
|
redo: {
|
||||||
|
defaultMessage: 'Redo',
|
||||||
|
description: 'Alt to image for the button to redo an action',
|
||||||
|
id: 'paint.paintEditor.redo'
|
||||||
|
},
|
||||||
|
forward: {
|
||||||
|
defaultMessage: 'Forward',
|
||||||
|
description: 'Label for the `Send forward on canvas` button',
|
||||||
|
id: 'paint.paintEditor.forward'
|
||||||
|
},
|
||||||
|
backward: {
|
||||||
|
defaultMessage: 'Backward',
|
||||||
|
description: 'Label for the `Send backward on canvas` button',
|
||||||
|
id: 'paint.paintEditor.backward'
|
||||||
|
},
|
||||||
|
front: {
|
||||||
|
defaultMessage: 'Front',
|
||||||
|
description: 'Label for the `Send to front of canvas` button',
|
||||||
|
id: 'paint.paintEditor.front'
|
||||||
|
},
|
||||||
|
back: {
|
||||||
|
defaultMessage: 'Back',
|
||||||
|
description: 'Label for the `Send to back of canvas` button',
|
||||||
|
id: 'paint.paintEditor.back'
|
||||||
|
},
|
||||||
|
more: {
|
||||||
|
defaultMessage: 'More',
|
||||||
|
description: 'Label for dropdown to access more action buttons',
|
||||||
|
id: 'paint.paintEditor.more'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const FixedToolsComponent = props => {
|
||||||
|
const redoDisabled = !props.canRedo();
|
||||||
|
const undoDisabled = !props.canUndo();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.row}>
|
||||||
|
{/* Name field */}
|
||||||
|
<InputGroup>
|
||||||
|
<MediaQuery minWidth={layout.fullSizeEditorMinWidth}>
|
||||||
|
<Label text={props.intl.formatMessage(messages.costume)}>
|
||||||
|
<BufferedInput
|
||||||
|
className={styles.costumeInput}
|
||||||
|
type="text"
|
||||||
|
value={props.name}
|
||||||
|
onSubmit={props.onUpdateName}
|
||||||
|
/>
|
||||||
|
</Label>
|
||||||
|
</MediaQuery>
|
||||||
|
<MediaQuery maxWidth={layout.fullSizeEditorMinWidth - 1}>
|
||||||
|
<BufferedInput
|
||||||
|
className={styles.costumeInput}
|
||||||
|
type="text"
|
||||||
|
value={props.name}
|
||||||
|
onSubmit={props.onUpdateName}
|
||||||
|
/>
|
||||||
|
</MediaQuery>
|
||||||
|
</InputGroup>
|
||||||
|
|
||||||
|
{/* Undo/Redo */}
|
||||||
|
<InputGroup>
|
||||||
|
<ButtonGroup>
|
||||||
|
<Button
|
||||||
|
className={
|
||||||
|
classNames(
|
||||||
|
styles.buttonGroupButton,
|
||||||
|
{
|
||||||
|
[styles.modNoRightBorder]: !redoDisabled
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
disabled={undoDisabled}
|
||||||
|
onClick={props.onUndo}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
alt={props.intl.formatMessage(messages.undo)}
|
||||||
|
className={styles.buttonGroupButtonIcon}
|
||||||
|
draggable={false}
|
||||||
|
src={undoIcon}
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
className={
|
||||||
|
classNames(
|
||||||
|
styles.buttonGroupButton,
|
||||||
|
{
|
||||||
|
[styles.modLeftBorder]: !redoDisabled
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
disabled={redoDisabled}
|
||||||
|
onClick={props.onRedo}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
alt={props.intl.formatMessage(messages.redo)}
|
||||||
|
className={styles.buttonGroupButtonIcon}
|
||||||
|
draggable={false}
|
||||||
|
src={redoIcon}
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
</ButtonGroup>
|
||||||
|
</InputGroup>
|
||||||
|
|
||||||
|
{/* Group/Ungroup */}
|
||||||
|
{isVector(props.format) ?
|
||||||
|
<InputGroup className={styles.modDashedBorder}>
|
||||||
|
<LabeledIconButton
|
||||||
|
disabled={!shouldShowGroup()}
|
||||||
|
imgSrc={groupIcon}
|
||||||
|
title={props.intl.formatMessage(messages.group)}
|
||||||
|
onClick={props.onGroup}
|
||||||
|
/>
|
||||||
|
<LabeledIconButton
|
||||||
|
disabled={!shouldShowUngroup()}
|
||||||
|
imgSrc={ungroupIcon}
|
||||||
|
title={props.intl.formatMessage(messages.ungroup)}
|
||||||
|
onClick={props.onUngroup}
|
||||||
|
/>
|
||||||
|
</InputGroup> : null
|
||||||
|
}
|
||||||
|
|
||||||
|
{/* Forward/Backward */}
|
||||||
|
{isVector(props.format) ?
|
||||||
|
<InputGroup className={styles.modDashedBorder}>
|
||||||
|
<LabeledIconButton
|
||||||
|
disabled={!shouldShowBringForward()}
|
||||||
|
imgSrc={sendForwardIcon}
|
||||||
|
title={props.intl.formatMessage(messages.forward)}
|
||||||
|
onClick={props.onSendForward}
|
||||||
|
/>
|
||||||
|
<LabeledIconButton
|
||||||
|
disabled={!shouldShowSendBackward()}
|
||||||
|
imgSrc={sendBackwardIcon}
|
||||||
|
title={props.intl.formatMessage(messages.backward)}
|
||||||
|
onClick={props.onSendBackward}
|
||||||
|
/>
|
||||||
|
</InputGroup> : null
|
||||||
|
}
|
||||||
|
|
||||||
|
{isVector(props.format) ?
|
||||||
|
<MediaQuery minWidth={layout.fullSizeEditorMinWidth}>
|
||||||
|
<InputGroup className={styles.row}>
|
||||||
|
<LabeledIconButton
|
||||||
|
disabled={!shouldShowBringForward()}
|
||||||
|
imgSrc={sendFrontIcon}
|
||||||
|
title={props.intl.formatMessage(messages.front)}
|
||||||
|
onClick={props.onSendToFront}
|
||||||
|
/>
|
||||||
|
<LabeledIconButton
|
||||||
|
disabled={!shouldShowSendBackward()}
|
||||||
|
imgSrc={sendBackIcon}
|
||||||
|
title={props.intl.formatMessage(messages.back)}
|
||||||
|
onClick={props.onSendToBack}
|
||||||
|
/>
|
||||||
|
</InputGroup>
|
||||||
|
|
||||||
|
{/* To be rotation point */}
|
||||||
|
{/* <InputGroup>
|
||||||
|
<LabeledIconButton
|
||||||
|
imgAlt="Rotation Point"
|
||||||
|
imgSrc={rotationPointIcon}
|
||||||
|
title="Rotation Point"
|
||||||
|
onClick={function () {}}
|
||||||
|
/>
|
||||||
|
</InputGroup> */}
|
||||||
|
</MediaQuery> : null
|
||||||
|
}
|
||||||
|
{isVector(props.format) ?
|
||||||
|
<MediaQuery maxWidth={layout.fullSizeEditorMinWidth - 1}>
|
||||||
|
<InputGroup>
|
||||||
|
<Dropdown
|
||||||
|
className={styles.modUnselect}
|
||||||
|
enterExitTransitionDurationMs={20}
|
||||||
|
popoverContent={
|
||||||
|
<InputGroup className={styles.modContextMenu}>
|
||||||
|
<Button
|
||||||
|
className={classNames(styles.modMenuItem, {
|
||||||
|
[styles.modDisabled]: !shouldShowBringForward()
|
||||||
|
})}
|
||||||
|
disabled={!shouldShowBringForward()}
|
||||||
|
onClick={props.onSendToFront}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
className={styles.menuItemIcon}
|
||||||
|
draggable={false}
|
||||||
|
src={sendFrontIcon}
|
||||||
|
/>
|
||||||
|
<span>{props.intl.formatMessage(messages.front)}</span>
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
className={classNames(styles.modMenuItem, {
|
||||||
|
[styles.modDisabled]: !shouldShowSendBackward()
|
||||||
|
})}
|
||||||
|
disabled={!shouldShowSendBackward()}
|
||||||
|
onClick={props.onSendToBack}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
className={styles.menuItemIcon}
|
||||||
|
draggable={false}
|
||||||
|
src={sendBackIcon}
|
||||||
|
/>
|
||||||
|
<span>{props.intl.formatMessage(messages.back)}</span>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
{/* To be rotation point */}
|
||||||
|
{/* <Button
|
||||||
|
className={classNames(styles.modMenuItem, styles.modTopDivider)}
|
||||||
|
onClick={function () {}}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
className={styles.menuItemIcon}
|
||||||
|
draggable={false}
|
||||||
|
src={rotationPointIcon}
|
||||||
|
/>
|
||||||
|
<span>{'Rotation Point'}</span>
|
||||||
|
</Button> */}
|
||||||
|
</InputGroup>
|
||||||
|
}
|
||||||
|
tipSize={.01}
|
||||||
|
>
|
||||||
|
{props.intl.formatMessage(messages.more)}
|
||||||
|
</Dropdown>
|
||||||
|
</InputGroup>
|
||||||
|
</MediaQuery> : null
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
FixedToolsComponent.propTypes = {
|
||||||
|
canRedo: PropTypes.func.isRequired,
|
||||||
|
canUndo: PropTypes.func.isRequired,
|
||||||
|
format: PropTypes.oneOf(Object.keys(Formats)),
|
||||||
|
intl: intlShape,
|
||||||
|
name: PropTypes.string,
|
||||||
|
onGroup: PropTypes.func.isRequired,
|
||||||
|
onRedo: PropTypes.func.isRequired,
|
||||||
|
onSendBackward: PropTypes.func.isRequired,
|
||||||
|
onSendForward: PropTypes.func.isRequired,
|
||||||
|
onSendToBack: PropTypes.func.isRequired,
|
||||||
|
onSendToFront: PropTypes.func.isRequired,
|
||||||
|
onUndo: PropTypes.func.isRequired,
|
||||||
|
onUngroup: PropTypes.func.isRequired,
|
||||||
|
onUpdateName: PropTypes.func.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapStateToProps = state => ({
|
||||||
|
format: state.scratchPaint.format,
|
||||||
|
selectedItems: state.scratchPaint.selectedItems
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(
|
||||||
|
mapStateToProps
|
||||||
|
)(injectIntl(FixedToolsComponent));
|
0
src/components/paint-editor/icons/group.svg → src/components/fixed-tools/icons/group.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
0
src/components/paint-editor/icons/redo.svg → src/components/fixed-tools/icons/redo.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
0
src/components/paint-editor/icons/send-back.svg → src/components/fixed-tools/icons/send-back.svg
Executable file → Normal file
Before Width: | Height: | Size: 2 KiB After Width: | Height: | Size: 2 KiB |
0
src/components/paint-editor/icons/send-backward.svg → src/components/fixed-tools/icons/send-backward.svg
Executable file → Normal file
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
0
src/components/paint-editor/icons/send-forward.svg → src/components/fixed-tools/icons/send-forward.svg
Executable file → Normal file
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
0
src/components/paint-editor/icons/send-front.svg → src/components/fixed-tools/icons/send-front.svg
Executable file → Normal file
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
0
src/components/paint-editor/icons/undo.svg → src/components/fixed-tools/icons/undo.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
0
src/components/paint-editor/icons/ungroup.svg → src/components/fixed-tools/icons/ungroup.svg
Executable file → Normal file
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
@ -28,19 +28,11 @@
|
||||||
margin-top: calc(2 * $grid-unit);
|
margin-top: calc(2 * $grid-unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
.costume-input {
|
|
||||||
width: 8rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mod-dashed-border {
|
.mod-dashed-border {
|
||||||
border-right: 1px dashed $ui-pane-border;
|
border-right: 1px dashed $ui-pane-border;
|
||||||
padding-right: calc(2 * $grid-unit);
|
padding-right: calc(2 * $grid-unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
.mod-unselect {
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mod-labeled-icon-height {
|
.mod-labeled-icon-height {
|
||||||
height: 2.85rem; /* for the second row so the dashed borders are equal in size */
|
height: 2.85rem; /* for the second row so the dashed borders are equal in size */
|
||||||
}
|
}
|
||||||
|
@ -80,43 +72,6 @@ $border-radius: 0.25rem;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mod-context-menu {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mod-top-divider {
|
|
||||||
border-top: 1px solid $ui-pane-border;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mod-menu-item {
|
|
||||||
display: flex;
|
|
||||||
margin: 0 -$grid-unit;
|
|
||||||
min-width: 6.25rem;
|
|
||||||
padding: calc(3 * $grid-unit);
|
|
||||||
white-space: nowrap;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: 0.1s ease;
|
|
||||||
align-items: center;
|
|
||||||
font-family: "Helvetica Neue", Helvetica, sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mod-disabled {
|
|
||||||
cursor: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mod-menu-item:hover {
|
|
||||||
background: $motion-transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mod-disabled:hover {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu-item-icon {
|
|
||||||
margin-right: calc(2 * $grid-unit);
|
|
||||||
}
|
|
||||||
|
|
||||||
.mod-mode-tools {
|
.mod-mode-tools {
|
||||||
margin-left: calc(2 * $grid-unit);
|
margin-left: calc(2 * $grid-unit);
|
||||||
}
|
}
|
||||||
|
@ -175,11 +130,6 @@ $border-radius: 0.25rem;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bitmap-tooltip {
|
|
||||||
margin-left: $grid-unit;
|
|
||||||
max-width: 10rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bitmap-button {
|
.bitmap-button {
|
||||||
display: flex;
|
display: flex;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
|
|
|
@ -1,15 +1,11 @@
|
||||||
import paper from '@scratch/paper';
|
import paper from '@scratch/paper';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import {defineMessages, injectIntl, intlShape} from 'react-intl';
|
import {defineMessages, injectIntl, intlShape} from 'react-intl';
|
||||||
import MediaQuery from 'react-responsive';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import PaperCanvas from '../../containers/paper-canvas.jsx';
|
import PaperCanvas from '../../containers/paper-canvas.jsx';
|
||||||
|
|
||||||
import {shouldShowGroup, shouldShowUngroup} from '../../helper/group';
|
|
||||||
import {shouldShowBringForward, shouldShowSendBackward} from '../../helper/order';
|
|
||||||
|
|
||||||
import BitBrushMode from '../../containers/bit-brush-mode.jsx';
|
import BitBrushMode from '../../containers/bit-brush-mode.jsx';
|
||||||
import BitLineMode from '../../containers/bit-line-mode.jsx';
|
import BitLineMode from '../../containers/bit-line-mode.jsx';
|
||||||
import BitOvalMode from '../../components/bit-oval-mode/bit-oval-mode.jsx';
|
import BitOvalMode from '../../components/bit-oval-mode/bit-oval-mode.jsx';
|
||||||
|
@ -22,17 +18,13 @@ import Box from '../box/box.jsx';
|
||||||
import Button from '../button/button.jsx';
|
import Button from '../button/button.jsx';
|
||||||
import ButtonGroup from '../button-group/button-group.jsx';
|
import ButtonGroup from '../button-group/button-group.jsx';
|
||||||
import BrushMode from '../../containers/brush-mode.jsx';
|
import BrushMode from '../../containers/brush-mode.jsx';
|
||||||
import BufferedInputHOC from '../forms/buffered-input-hoc.jsx';
|
|
||||||
import Dropdown from '../dropdown/dropdown.jsx';
|
|
||||||
import EraserMode from '../../containers/eraser-mode.jsx';
|
import EraserMode from '../../containers/eraser-mode.jsx';
|
||||||
import FillColorIndicatorComponent from '../../containers/fill-color-indicator.jsx';
|
import FillColorIndicatorComponent from '../../containers/fill-color-indicator.jsx';
|
||||||
import FillMode from '../../containers/fill-mode.jsx';
|
import FillMode from '../../containers/fill-mode.jsx';
|
||||||
import Input from '../forms/input.jsx';
|
|
||||||
import InputGroup from '../input-group/input-group.jsx';
|
import InputGroup from '../input-group/input-group.jsx';
|
||||||
import Label from '../forms/label.jsx';
|
|
||||||
import LabeledIconButton from '../labeled-icon-button/labeled-icon-button.jsx';
|
|
||||||
import LineMode from '../../containers/line-mode.jsx';
|
import LineMode from '../../containers/line-mode.jsx';
|
||||||
import Loupe from '../loupe/loupe.jsx';
|
import Loupe from '../loupe/loupe.jsx';
|
||||||
|
import FixedToolsComponent from '../fixed-tools/fixed-tools.jsx';
|
||||||
import ModeToolsContainer from '../../containers/mode-tools.jsx';
|
import ModeToolsContainer from '../../containers/mode-tools.jsx';
|
||||||
import OvalMode from '../../containers/oval-mode.jsx';
|
import OvalMode from '../../containers/oval-mode.jsx';
|
||||||
import RectMode from '../../containers/rect-mode.jsx';
|
import RectMode from '../../containers/rect-mode.jsx';
|
||||||
|
@ -44,74 +36,14 @@ import TextMode from '../../containers/text-mode.jsx';
|
||||||
|
|
||||||
import Formats from '../../lib/format';
|
import Formats from '../../lib/format';
|
||||||
import {isBitmap, isVector} from '../../lib/format';
|
import {isBitmap, isVector} from '../../lib/format';
|
||||||
import layout from '../../lib/layout-constants';
|
|
||||||
import styles from './paint-editor.css';
|
import styles from './paint-editor.css';
|
||||||
|
|
||||||
import bitmapIcon from './icons/bitmap.svg';
|
import bitmapIcon from './icons/bitmap.svg';
|
||||||
import groupIcon from './icons/group.svg';
|
|
||||||
import redoIcon from './icons/redo.svg';
|
|
||||||
import sendBackIcon from './icons/send-back.svg';
|
|
||||||
import sendBackwardIcon from './icons/send-backward.svg';
|
|
||||||
import sendForwardIcon from './icons/send-forward.svg';
|
|
||||||
import sendFrontIcon from './icons/send-front.svg';
|
|
||||||
import undoIcon from './icons/undo.svg';
|
|
||||||
import ungroupIcon from './icons/ungroup.svg';
|
|
||||||
import zoomInIcon from './icons/zoom-in.svg';
|
import zoomInIcon from './icons/zoom-in.svg';
|
||||||
import zoomOutIcon from './icons/zoom-out.svg';
|
import zoomOutIcon from './icons/zoom-out.svg';
|
||||||
import zoomResetIcon from './icons/zoom-reset.svg';
|
import zoomResetIcon from './icons/zoom-reset.svg';
|
||||||
|
|
||||||
const BufferedInput = BufferedInputHOC(Input);
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
costume: {
|
|
||||||
id: 'paint.paintEditor.costume',
|
|
||||||
description: 'Label for the name of a costume',
|
|
||||||
defaultMessage: 'Costume'
|
|
||||||
},
|
|
||||||
group: {
|
|
||||||
defaultMessage: 'Group',
|
|
||||||
description: 'Label for the button to group shapes',
|
|
||||||
id: 'paint.paintEditor.group'
|
|
||||||
},
|
|
||||||
ungroup: {
|
|
||||||
defaultMessage: 'Ungroup',
|
|
||||||
description: 'Label for the button to ungroup shapes',
|
|
||||||
id: 'paint.paintEditor.ungroup'
|
|
||||||
},
|
|
||||||
undo: {
|
|
||||||
defaultMessage: 'Undo',
|
|
||||||
description: 'Alt to image for the button to undo an action',
|
|
||||||
id: 'paint.paintEditor.undo'
|
|
||||||
},
|
|
||||||
redo: {
|
|
||||||
defaultMessage: 'Redo',
|
|
||||||
description: 'Alt to image for the button to redo an action',
|
|
||||||
id: 'paint.paintEditor.redo'
|
|
||||||
},
|
|
||||||
forward: {
|
|
||||||
defaultMessage: 'Forward',
|
|
||||||
description: 'Label for the `Send forward on canvas` button',
|
|
||||||
id: 'paint.paintEditor.forward'
|
|
||||||
},
|
|
||||||
backward: {
|
|
||||||
defaultMessage: 'Backward',
|
|
||||||
description: 'Label for the `Send backward on canvas` button',
|
|
||||||
id: 'paint.paintEditor.backward'
|
|
||||||
},
|
|
||||||
front: {
|
|
||||||
defaultMessage: 'Front',
|
|
||||||
description: 'Label for the `Send to front of canvas` button',
|
|
||||||
id: 'paint.paintEditor.front'
|
|
||||||
},
|
|
||||||
back: {
|
|
||||||
defaultMessage: 'Back',
|
|
||||||
description: 'Label for the `Send to back of canvas` button',
|
|
||||||
id: 'paint.paintEditor.back'
|
|
||||||
},
|
|
||||||
more: {
|
|
||||||
defaultMessage: 'More',
|
|
||||||
description: 'Label for dropdown to access more action buttons',
|
|
||||||
id: 'paint.paintEditor.more'
|
|
||||||
},
|
|
||||||
bitmap: {
|
bitmap: {
|
||||||
defaultMessage: 'Convert to Bitmap',
|
defaultMessage: 'Convert to Bitmap',
|
||||||
description: 'Label for button that converts the paint editor to bitmap mode',
|
description: 'Label for button that converts the paint editor to bitmap mode',
|
||||||
|
@ -124,200 +56,59 @@ const messages = defineMessages({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const PaintEditorComponent = props => {
|
const PaintEditorComponent = props => (
|
||||||
const redoDisabled = !props.canRedo();
|
<div className={styles.editorContainer}>
|
||||||
const undoDisabled = !props.canUndo();
|
{props.canvas !== null ? ( // eslint-disable-line no-negated-condition
|
||||||
|
<div className={styles.editorContainerTop}>
|
||||||
return (
|
{/* First row */}
|
||||||
<div className={styles.editorContainer}>
|
<div className={styles.row}>
|
||||||
{props.canvas !== null ? ( // eslint-disable-line no-negated-condition
|
<FixedToolsComponent
|
||||||
<div className={styles.editorContainerTop}>
|
canRedo={props.canRedo}
|
||||||
{/* First row */}
|
canUndo={props.canUndo}
|
||||||
|
name={props.name}
|
||||||
|
onGroup={props.onGroup}
|
||||||
|
onRedo={props.onRedo}
|
||||||
|
onSendBackward={props.onSendBackward}
|
||||||
|
onSendForward={props.onSendForward}
|
||||||
|
onSendToBack={props.onSendToBack}
|
||||||
|
onSendToFront={props.onSendToFront}
|
||||||
|
onUndo={props.onUndo}
|
||||||
|
onUngroup={props.onUngroup}
|
||||||
|
onUpdateImage={props.onUpdateImage}
|
||||||
|
onUpdateName={props.onUpdateName}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/* Second Row */}
|
||||||
|
{isVector(props.format) ?
|
||||||
<div className={styles.row}>
|
<div className={styles.row}>
|
||||||
{/* Name field */}
|
<InputGroup
|
||||||
<InputGroup>
|
className={classNames(
|
||||||
<MediaQuery minWidth={layout.fullSizeEditorMinWidth}>
|
styles.row,
|
||||||
<Label text={props.intl.formatMessage(messages.costume)}>
|
styles.modDashedBorder,
|
||||||
<BufferedInput
|
styles.modLabeledIconHeight
|
||||||
className={styles.costumeInput}
|
)}
|
||||||
type="text"
|
>
|
||||||
value={props.name}
|
{/* fill */}
|
||||||
onSubmit={props.onUpdateName}
|
<FillColorIndicatorComponent
|
||||||
/>
|
className={styles.modMarginRight}
|
||||||
</Label>
|
onUpdateImage={props.onUpdateImage}
|
||||||
</MediaQuery>
|
|
||||||
<MediaQuery maxWidth={layout.fullSizeEditorMinWidth - 1}>
|
|
||||||
<BufferedInput
|
|
||||||
className={styles.costumeInput}
|
|
||||||
type="text"
|
|
||||||
value={props.name}
|
|
||||||
onSubmit={props.onUpdateName}
|
|
||||||
/>
|
|
||||||
</MediaQuery>
|
|
||||||
</InputGroup>
|
|
||||||
|
|
||||||
{/* Undo/Redo */}
|
|
||||||
<InputGroup>
|
|
||||||
<ButtonGroup>
|
|
||||||
<Button
|
|
||||||
className={
|
|
||||||
classNames(
|
|
||||||
styles.buttonGroupButton,
|
|
||||||
{
|
|
||||||
[styles.modNoRightBorder]: !redoDisabled
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
disabled={undoDisabled}
|
|
||||||
onClick={props.onUndo}
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
alt={props.intl.formatMessage(messages.undo)}
|
|
||||||
className={styles.buttonGroupButtonIcon}
|
|
||||||
draggable={false}
|
|
||||||
src={undoIcon}
|
|
||||||
/>
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
className={
|
|
||||||
classNames(
|
|
||||||
styles.buttonGroupButton,
|
|
||||||
{
|
|
||||||
[styles.modLeftBorder]: !redoDisabled
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
disabled={redoDisabled}
|
|
||||||
onClick={props.onRedo}
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
alt={props.intl.formatMessage(messages.redo)}
|
|
||||||
className={styles.buttonGroupButtonIcon}
|
|
||||||
draggable={false}
|
|
||||||
src={redoIcon}
|
|
||||||
/>
|
|
||||||
</Button>
|
|
||||||
</ButtonGroup>
|
|
||||||
</InputGroup>
|
|
||||||
|
|
||||||
{/* Group/Ungroup */}
|
|
||||||
<InputGroup className={styles.modDashedBorder}>
|
|
||||||
<LabeledIconButton
|
|
||||||
disabled={!shouldShowGroup()}
|
|
||||||
imgSrc={groupIcon}
|
|
||||||
title={props.intl.formatMessage(messages.group)}
|
|
||||||
onClick={props.onGroup}
|
|
||||||
/>
|
/>
|
||||||
<LabeledIconButton
|
{/* stroke */}
|
||||||
disabled={!shouldShowUngroup()}
|
<StrokeColorIndicatorComponent
|
||||||
imgSrc={ungroupIcon}
|
onUpdateImage={props.onUpdateImage}
|
||||||
title={props.intl.formatMessage(messages.ungroup)}
|
/>
|
||||||
onClick={props.onUngroup}
|
{/* stroke width */}
|
||||||
|
<StrokeWidthIndicatorComponent
|
||||||
|
onUpdateImage={props.onUpdateImage}
|
||||||
/>
|
/>
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
|
<InputGroup className={styles.modModeTools}>
|
||||||
{/* Forward/Backward */}
|
<ModeToolsContainer
|
||||||
<InputGroup className={styles.modDashedBorder}>
|
onUpdateImage={props.onUpdateImage}
|
||||||
<LabeledIconButton
|
|
||||||
disabled={!shouldShowBringForward()}
|
|
||||||
imgSrc={sendForwardIcon}
|
|
||||||
title={props.intl.formatMessage(messages.forward)}
|
|
||||||
onClick={props.onSendForward}
|
|
||||||
/>
|
|
||||||
<LabeledIconButton
|
|
||||||
disabled={!shouldShowSendBackward()}
|
|
||||||
imgSrc={sendBackwardIcon}
|
|
||||||
title={props.intl.formatMessage(messages.backward)}
|
|
||||||
onClick={props.onSendBackward}
|
|
||||||
/>
|
/>
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
|
</div> :
|
||||||
<MediaQuery minWidth={layout.fullSizeEditorMinWidth}>
|
isBitmap(props.format) ?
|
||||||
<InputGroup className={styles.row}>
|
|
||||||
<LabeledIconButton
|
|
||||||
disabled={!shouldShowBringForward()}
|
|
||||||
imgSrc={sendFrontIcon}
|
|
||||||
title={props.intl.formatMessage(messages.front)}
|
|
||||||
onClick={props.onSendToFront}
|
|
||||||
/>
|
|
||||||
<LabeledIconButton
|
|
||||||
disabled={!shouldShowSendBackward()}
|
|
||||||
imgSrc={sendBackIcon}
|
|
||||||
title={props.intl.formatMessage(messages.back)}
|
|
||||||
onClick={props.onSendToBack}
|
|
||||||
/>
|
|
||||||
</InputGroup>
|
|
||||||
|
|
||||||
{/* To be rotation point */}
|
|
||||||
{/* <InputGroup>
|
|
||||||
<LabeledIconButton
|
|
||||||
imgAlt="Rotation Point"
|
|
||||||
imgSrc={rotationPointIcon}
|
|
||||||
title="Rotation Point"
|
|
||||||
onClick={function () {}}
|
|
||||||
/>
|
|
||||||
</InputGroup> */}
|
|
||||||
</MediaQuery>
|
|
||||||
<MediaQuery maxWidth={layout.fullSizeEditorMinWidth - 1}>
|
|
||||||
<InputGroup>
|
|
||||||
<Dropdown
|
|
||||||
className={styles.modUnselect}
|
|
||||||
enterExitTransitionDurationMs={20}
|
|
||||||
popoverContent={
|
|
||||||
<InputGroup className={styles.modContextMenu}>
|
|
||||||
<Button
|
|
||||||
className={classNames(styles.modMenuItem, {
|
|
||||||
[styles.modDisabled]: !shouldShowBringForward()
|
|
||||||
})}
|
|
||||||
disabled={!shouldShowBringForward()}
|
|
||||||
onClick={props.onSendToFront}
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
className={styles.menuItemIcon}
|
|
||||||
draggable={false}
|
|
||||||
src={sendFrontIcon}
|
|
||||||
/>
|
|
||||||
<span>{props.intl.formatMessage(messages.front)}</span>
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
className={classNames(styles.modMenuItem, {
|
|
||||||
[styles.modDisabled]: !shouldShowSendBackward()
|
|
||||||
})}
|
|
||||||
disabled={!shouldShowSendBackward()}
|
|
||||||
onClick={props.onSendToBack}
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
className={styles.menuItemIcon}
|
|
||||||
draggable={false}
|
|
||||||
src={sendBackIcon}
|
|
||||||
/>
|
|
||||||
<span>{props.intl.formatMessage(messages.back)}</span>
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
{/* To be rotation point */}
|
|
||||||
{/* <Button
|
|
||||||
className={classNames(styles.modMenuItem, styles.modTopDivider)}
|
|
||||||
onClick={function () {}}
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
className={styles.menuItemIcon}
|
|
||||||
draggable={false}
|
|
||||||
src={rotationPointIcon}
|
|
||||||
/>
|
|
||||||
<span>{'Rotation Point'}</span>
|
|
||||||
</Button> */}
|
|
||||||
</InputGroup>
|
|
||||||
}
|
|
||||||
tipSize={.01}
|
|
||||||
>
|
|
||||||
{props.intl.formatMessage(messages.more)}
|
|
||||||
</Dropdown>
|
|
||||||
</InputGroup>
|
|
||||||
</MediaQuery>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Second Row */}
|
|
||||||
{isVector(props.format) ?
|
|
||||||
<div className={styles.row}>
|
<div className={styles.row}>
|
||||||
<InputGroup
|
<InputGroup
|
||||||
className={classNames(
|
className={classNames(
|
||||||
|
@ -331,137 +122,122 @@ const PaintEditorComponent = props => {
|
||||||
className={styles.modMarginRight}
|
className={styles.modMarginRight}
|
||||||
onUpdateImage={props.onUpdateImage}
|
onUpdateImage={props.onUpdateImage}
|
||||||
/>
|
/>
|
||||||
{/* stroke */}
|
|
||||||
<StrokeColorIndicatorComponent
|
|
||||||
onUpdateImage={props.onUpdateImage}
|
|
||||||
/>
|
|
||||||
{/* stroke width */}
|
|
||||||
<StrokeWidthIndicatorComponent
|
|
||||||
onUpdateImage={props.onUpdateImage}
|
|
||||||
/>
|
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
<InputGroup className={styles.modModeTools}>
|
<InputGroup className={styles.modModeTools}>
|
||||||
<ModeToolsContainer
|
<ModeToolsContainer
|
||||||
onUpdateImage={props.onUpdateImage}
|
onUpdateImage={props.onUpdateImage}
|
||||||
/>
|
/>
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
</div> :
|
</div> : null
|
||||||
isBitmap(props.format) ?
|
}
|
||||||
<div className={styles.row}>
|
</div>
|
||||||
<InputGroup
|
) : null}
|
||||||
className={classNames(
|
|
||||||
styles.row,
|
<div className={styles.topAlignRow}>
|
||||||
styles.modDashedBorder,
|
{/* Modes */}
|
||||||
styles.modLabeledIconHeight
|
{props.canvas !== null ? ( // eslint-disable-line no-negated-condition
|
||||||
)}
|
<div className={isVector(props.format) ? styles.modeSelector : styles.hidden}>
|
||||||
>
|
<SelectMode
|
||||||
{/* fill */}
|
onUpdateImage={props.onUpdateImage}
|
||||||
<FillColorIndicatorComponent
|
/>
|
||||||
className={styles.modMarginRight}
|
<ReshapeMode
|
||||||
onUpdateImage={props.onUpdateImage}
|
onUpdateImage={props.onUpdateImage}
|
||||||
/>
|
/>
|
||||||
</InputGroup>
|
<BrushMode
|
||||||
<InputGroup className={styles.modModeTools}>
|
onUpdateImage={props.onUpdateImage}
|
||||||
<ModeToolsContainer
|
/>
|
||||||
onUpdateImage={props.onUpdateImage}
|
<EraserMode
|
||||||
/>
|
onUpdateImage={props.onUpdateImage}
|
||||||
</InputGroup>
|
/>
|
||||||
</div> : null
|
<FillMode
|
||||||
}
|
onUpdateImage={props.onUpdateImage}
|
||||||
|
/>
|
||||||
|
<TextMode
|
||||||
|
textArea={props.textArea}
|
||||||
|
onUpdateImage={props.onUpdateImage}
|
||||||
|
/>
|
||||||
|
<LineMode
|
||||||
|
onUpdateImage={props.onUpdateImage}
|
||||||
|
/>
|
||||||
|
<OvalMode
|
||||||
|
onUpdateImage={props.onUpdateImage}
|
||||||
|
/>
|
||||||
|
<RectMode
|
||||||
|
onUpdateImage={props.onUpdateImage}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
<div className={styles.topAlignRow}>
|
{props.canvas !== null ? ( // eslint-disable-line no-negated-condition
|
||||||
{/* Modes */}
|
<div className={isBitmap(props.format) ? styles.modeSelector : styles.hidden}>
|
||||||
{props.canvas !== null ? ( // eslint-disable-line no-negated-condition
|
<BitBrushMode
|
||||||
<div className={isVector(props.format) ? styles.modeSelector : styles.hidden}>
|
onUpdateImage={props.onUpdateImage}
|
||||||
<SelectMode
|
/>
|
||||||
onUpdateImage={props.onUpdateImage}
|
<BitLineMode
|
||||||
/>
|
onUpdateImage={props.onUpdateImage}
|
||||||
<ReshapeMode
|
/>
|
||||||
onUpdateImage={props.onUpdateImage}
|
<BitOvalMode />
|
||||||
/>
|
<BitRectMode />
|
||||||
<BrushMode
|
<BitTextMode />
|
||||||
onUpdateImage={props.onUpdateImage}
|
<BitFillMode />
|
||||||
/>
|
<BitEraserMode />
|
||||||
<EraserMode
|
<BitSelectMode />
|
||||||
onUpdateImage={props.onUpdateImage}
|
</div>
|
||||||
/>
|
) : null}
|
||||||
<FillMode
|
|
||||||
onUpdateImage={props.onUpdateImage}
|
<div>
|
||||||
/>
|
{/* Canvas */}
|
||||||
<TextMode
|
<div
|
||||||
textArea={props.textArea}
|
className={classNames(
|
||||||
onUpdateImage={props.onUpdateImage}
|
styles.canvasContainer,
|
||||||
/>
|
{[styles.withEyeDropper]: props.isEyeDropping}
|
||||||
<LineMode
|
)}
|
||||||
onUpdateImage={props.onUpdateImage}
|
>
|
||||||
/>
|
<PaperCanvas
|
||||||
<OvalMode
|
canvasRef={props.setCanvas}
|
||||||
onUpdateImage={props.onUpdateImage}
|
image={props.image}
|
||||||
/>
|
imageFormat={props.imageFormat}
|
||||||
<RectMode
|
imageId={props.imageId}
|
||||||
onUpdateImage={props.onUpdateImage}
|
rotationCenterX={props.rotationCenterX}
|
||||||
/>
|
rotationCenterY={props.rotationCenterY}
|
||||||
</div>
|
onUpdateImage={props.onUpdateImage}
|
||||||
) : null}
|
/>
|
||||||
|
<textarea
|
||||||
{props.canvas !== null ? ( // eslint-disable-line no-negated-condition
|
className={styles.textArea}
|
||||||
<div className={isBitmap(props.format) ? styles.modeSelector : styles.hidden}>
|
ref={props.setTextArea}
|
||||||
<BitBrushMode
|
spellCheck={false}
|
||||||
onUpdateImage={props.onUpdateImage}
|
/>
|
||||||
/>
|
{props.isEyeDropping &&
|
||||||
<BitLineMode
|
props.colorInfo !== null &&
|
||||||
onUpdateImage={props.onUpdateImage}
|
!props.colorInfo.hideLoupe ? (
|
||||||
/>
|
<Box className={styles.colorPickerWrapper}>
|
||||||
<BitOvalMode />
|
<Loupe
|
||||||
<BitRectMode />
|
colorInfo={props.colorInfo}
|
||||||
<BitTextMode />
|
pixelRatio={paper.project.view.pixelRatio}
|
||||||
<BitFillMode />
|
/>
|
||||||
<BitEraserMode />
|
</Box>
|
||||||
<BitSelectMode />
|
) : null
|
||||||
</div>
|
}
|
||||||
) : null}
|
</div>
|
||||||
|
<div className={styles.canvasControls}>
|
||||||
<div>
|
{isVector(props.format) ?
|
||||||
{/* Canvas */}
|
<Button
|
||||||
<div
|
className={styles.bitmapButton}
|
||||||
className={classNames(
|
onClick={props.onSwitchToBitmap}
|
||||||
styles.canvasContainer,
|
>
|
||||||
{[styles.withEyeDropper]: props.isEyeDropping}
|
<img
|
||||||
)}
|
className={styles.bitmapButtonIcon}
|
||||||
>
|
draggable={false}
|
||||||
<PaperCanvas
|
src={bitmapIcon}
|
||||||
canvasRef={props.setCanvas}
|
/>
|
||||||
image={props.image}
|
<span className={styles.buttonText}>
|
||||||
imageFormat={props.imageFormat}
|
{props.intl.formatMessage(messages.bitmap)}
|
||||||
imageId={props.imageId}
|
</span>
|
||||||
rotationCenterX={props.rotationCenterX}
|
</Button> :
|
||||||
rotationCenterY={props.rotationCenterY}
|
isBitmap(props.format) ?
|
||||||
onUpdateImage={props.onUpdateImage}
|
|
||||||
/>
|
|
||||||
<textarea
|
|
||||||
className={styles.textArea}
|
|
||||||
ref={props.setTextArea}
|
|
||||||
spellCheck={false}
|
|
||||||
/>
|
|
||||||
{props.isEyeDropping &&
|
|
||||||
props.colorInfo !== null &&
|
|
||||||
!props.colorInfo.hideLoupe ? (
|
|
||||||
<Box className={styles.colorPickerWrapper}>
|
|
||||||
<Loupe
|
|
||||||
colorInfo={props.colorInfo}
|
|
||||||
pixelRatio={paper.project.view.pixelRatio}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
) : null
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<div className={styles.canvasControls}>
|
|
||||||
{isVector(props.format) ?
|
|
||||||
<Button
|
<Button
|
||||||
className={styles.bitmapButton}
|
className={styles.bitmapButton}
|
||||||
onClick={props.onSwitchToBitmap}
|
onClick={props.onSwitchToVector}
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
className={styles.bitmapButtonIcon}
|
className={styles.bitmapButtonIcon}
|
||||||
|
@ -469,68 +245,53 @@ const PaintEditorComponent = props => {
|
||||||
src={bitmapIcon}
|
src={bitmapIcon}
|
||||||
/>
|
/>
|
||||||
<span className={styles.buttonText}>
|
<span className={styles.buttonText}>
|
||||||
{props.intl.formatMessage(messages.bitmap)}
|
{props.intl.formatMessage(messages.vector)}
|
||||||
</span>
|
</span>
|
||||||
</Button> :
|
</Button> : null
|
||||||
isBitmap(props.format) ?
|
}
|
||||||
<Button
|
{/* Zoom controls */}
|
||||||
className={styles.bitmapButton}
|
<InputGroup className={styles.zoomControls}>
|
||||||
onClick={props.onSwitchToVector}
|
<ButtonGroup>
|
||||||
>
|
<Button
|
||||||
<img
|
className={styles.buttonGroupButton}
|
||||||
className={styles.bitmapButtonIcon}
|
onClick={props.onZoomOut}
|
||||||
draggable={false}
|
>
|
||||||
src={bitmapIcon}
|
<img
|
||||||
/>
|
alt="Zoom Out"
|
||||||
<span className={styles.buttonText}>
|
className={styles.buttonGroupButtonIcon}
|
||||||
{props.intl.formatMessage(messages.vector)}
|
draggable={false}
|
||||||
</span>
|
src={zoomOutIcon}
|
||||||
</Button> : null
|
/>
|
||||||
}
|
</Button>
|
||||||
{/* Zoom controls */}
|
<Button
|
||||||
<InputGroup className={styles.zoomControls}>
|
className={styles.buttonGroupButton}
|
||||||
<ButtonGroup>
|
onClick={props.onZoomReset}
|
||||||
<Button
|
>
|
||||||
className={styles.buttonGroupButton}
|
<img
|
||||||
onClick={props.onZoomOut}
|
alt="Zoom Reset"
|
||||||
>
|
className={styles.buttonGroupButtonIcon}
|
||||||
<img
|
draggable={false}
|
||||||
alt="Zoom Out"
|
src={zoomResetIcon}
|
||||||
className={styles.buttonGroupButtonIcon}
|
/>
|
||||||
draggable={false}
|
</Button>
|
||||||
src={zoomOutIcon}
|
<Button
|
||||||
/>
|
className={styles.buttonGroupButton}
|
||||||
</Button>
|
onClick={props.onZoomIn}
|
||||||
<Button
|
>
|
||||||
className={styles.buttonGroupButton}
|
<img
|
||||||
onClick={props.onZoomReset}
|
alt="Zoom In"
|
||||||
>
|
className={styles.buttonGroupButtonIcon}
|
||||||
<img
|
draggable={false}
|
||||||
alt="Zoom Reset"
|
src={zoomInIcon}
|
||||||
className={styles.buttonGroupButtonIcon}
|
/>
|
||||||
draggable={false}
|
</Button>
|
||||||
src={zoomResetIcon}
|
</ButtonGroup>
|
||||||
/>
|
</InputGroup>
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
className={styles.buttonGroupButton}
|
|
||||||
onClick={props.onZoomIn}
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
alt="Zoom In"
|
|
||||||
className={styles.buttonGroupButtonIcon}
|
|
||||||
draggable={false}
|
|
||||||
src={zoomInIcon}
|
|
||||||
/>
|
|
||||||
</Button>
|
|
||||||
</ButtonGroup>
|
|
||||||
</InputGroup>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
</div>
|
||||||
};
|
);
|
||||||
|
|
||||||
PaintEditorComponent.propTypes = {
|
PaintEditorComponent.propTypes = {
|
||||||
canRedo: PropTypes.func.isRequired,
|
canRedo: PropTypes.func.isRequired,
|
||||||
|
|