[PE mobile] Make Text Settings

This commit is contained in:
SergeyEzhin 2021-01-18 21:03:39 +03:00
parent 3dad63735f
commit 79da854961
9 changed files with 532 additions and 7 deletions

View file

@ -31,6 +31,11 @@
}
}
.disabled, [disabled] {
opacity: .55;
pointer-events: none;
}
.shapes {
li {
width: 70px;

View file

@ -132,7 +132,28 @@
"textFill": "Fill",
"textCustomColor": "Custom Color",
"textDuplicateSlide": "Duplicate Slide",
"textDeleteSlide": "Delete Slide"
"textDeleteSlide": "Delete Slide",
"textFontColor": "Font Color",
"textHighlightColor": "Highlight Color",
"textAdditionalFormatting": "Additional Formatting",
"textAdditional": "Additional",
"textBullets": "Bullets",
"textNumbers": "Numbers",
"textLineSpacing": "Line Spacing",
"textFonts": "Fonts",
"textAuto": "Auto",
"textPt": "pt",
"textSize": "Size",
"textStrikethrough": "Strikethrough",
"textDoubleStrikethrough": "Double Strikethrough",
"textSuperscript": "Superscript",
"textSubscript": "Subscript",
"textSmallCaps": "Small Caps",
"textAllCaps": "All Caps",
"textLetterSpacing": "Letter Spacing",
"textDistanceFromText": "Distance From Text",
"textBefore": "Before",
"textAfter": "After"
}
},
"Common": {

View file

@ -5,7 +5,7 @@ import { f7 } from "framework7-react";
import { withTranslation } from 'react-i18next';
import CollaborationController from '../../../../common/mobile/lib/controller/Collaboration.jsx'
@inject("storeFocusObjects", "storeAppOptions", "storePresentationInfo", "storePresentationSettings", "storeSlideSettings")
@inject("storeFocusObjects", "storeAppOptions", "storePresentationInfo", "storePresentationSettings", "storeSlideSettings", "storeTextSettings")
class MainController extends Component {
constructor(props) {
super(props)
@ -220,6 +220,79 @@ class MainController extends Component {
Common.Utils.ThemeColor.setColors(colors, standart_colors);
});
// Text settings
const storeTextSettings = this.props.storeTextSettings;
this.api.asc_registerCallback('asc_onInitEditorFonts', (fonts, select) => {
storeTextSettings.initEditorFonts(fonts, select);
});
this.api.asc_registerCallback('asc_onFontFamily', (font) => {
storeTextSettings.resetFontName(font);
});
this.api.asc_registerCallback('asc_onFontSize', (size) => {
storeTextSettings.resetFontSize(size);
});
this.api.asc_registerCallback('asc_onBold', (isBold) => {
storeTextSettings.resetIsBold(isBold);
});
this.api.asc_registerCallback('asc_onItalic', (isItalic) => {
storeTextSettings.resetIsItalic(isItalic);
});
this.api.asc_registerCallback('asc_onUnderline', (isUnderline) => {
storeTextSettings.resetIsUnderline(isUnderline);
});
this.api.asc_registerCallback('asc_onStrikeout', (isStrikeout) => {
storeTextSettings.resetIsStrikeout(isStrikeout);
});
this.api.asc_registerCallback('asc_onVerticalAlign', (typeBaseline) => {
storeTextSettings.resetTypeBaseline(typeBaseline);
});
this.api.asc_registerCallback('asc_onListType', (data) => {
let type = data.get_ListType();
let subtype = data.get_ListSubType();
storeTextSettings.resetListType(type);
switch (type) {
case 0:
storeTextSettings.resetBullets(subtype);
break;
case 1:
storeTextSettings.resetNumbers(subtype);
break;
}
});
this.api.asc_registerCallback('asc_onPrAlign', (align) => {
storeTextSettings.resetParagraphAlign(align);
});
this.api.asc_registerCallback('asc_onVerticalTextAlign', valign => {
storeTextSettings.resetParagraphValign(valign);
});
this.api.asc_registerCallback('asc_canIncreaseIndent', value => {
storeTextSettings.resetIncreaseIndent(value);
});
this.api.asc_registerCallback('asc_canDecreaseIndent', value => {
storeTextSettings.resetDecreaseIndent(value);
});
this.api.asc_registerCallback('asc_onTextColor', (color) => {
storeTextSettings.resetTextColor(color);
});
this.api.asc_registerCallback('asc_onParaSpacingLine', (vc) => {
storeTextSettings.resetLineSpacing(vc);
});
}
_onDocumentContentReady() {

View file

@ -9,9 +9,88 @@ class EditTextController extends Component {
constructor (props) {
super(props);
}
toggleBold(value) {
const api = Common.EditorApi.get();
api.put_TextPrBold(value);
};
toggleItalic(value) {
const api = Common.EditorApi.get();
api.put_TextPrItalic(value);
};
toggleUnderline(value) {
const api = Common.EditorApi.get();
api.put_TextPrUnderline(value);
};
toggleStrikethrough(value) {
const api = Common.EditorApi.get();
api.put_TextPrStrikeout(value);
};
onParagraphAlign(type) {
const api = Common.EditorApi.get();
let value;
switch (type) {
case 'just':
value = 3;
break;
case 'right':
value = 0;
break;
case 'center':
value = 2;
break;
default:
value = 1;
break;
}
api.put_PrAlign(value);
};
onParagraphValign(type) {
const api = Common.EditorApi.get();
let value;
switch(type) {
case 'top':
value = Asc.c_oAscVAlign.Top;
break;
case 'center':
value = Asc.c_oAscVAlign.Center;
break;
case 'bottom':
value = Asc.c_oAscVAlign.Bottom;
break;
}
api.setVerticalAlign(value);
};
onParagraphMove(type) {
const api = Common.EditorApi.get();
if(type === 'left') {
api.DecreaseIndent();
} else {
api.IncreaseIndent();
}
};
render () {
return (
<EditText
toggleBold={this.toggleBold}
toggleItalic={this.toggleItalic}
toggleUnderline={this.toggleUnderline}
toggleStrikethrough={this.toggleStrikethrough}
onParagraphAlign={this.onParagraphAlign}
onParagraphValign={this.onParagraphValign}
onParagraphMove={this.onParagraphMove}
/>
)
}

View file

@ -157,7 +157,7 @@
.encoded-svg-mask('<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 22 22" fill="@{themeColor}"><g><path d="M1,3v1h21V3H1z M4,7v1h14V7H4z M1,12h21v-1H1V12z M4,15v1h14v-1H4z M1,20h21v-1H1V20z"/></g></svg>');
}
&.icon-text-align-jast {
&.icon-text-align-just {
width: 22px;
height: 22px;
.encoded-svg-mask('<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 22 22" fill="@{themeColor}"><g><path d="M1,3v1h21V3H1z M1,8h21V7H1V8z M1,12h21v-1H1V12z M1,16h21v-1H1V16z M1,20h21v-1H1V20z"/></g></svg>');

View file

@ -67,4 +67,19 @@ export class storeFocusObjects {
return undefined;
}
}
@computed get paragraphObject() {
const paragraphs = [];
for (let object of this._focusObjects) {
if (object.get_ObjectType() === Asc.c_oAscTypeSelectElement.Paragraph) {
paragraphs.push(object);
}
}
if (paragraphs.length > 0) {
const object = paragraphs[paragraphs.length - 1]; // get top
return object.get_ObjectValue();
} else {
return undefined;
}
}
}

View file

@ -8,6 +8,7 @@ import {storePresentationInfo} from './presentationInfo';
import {storePresentationSettings} from './presentationSettings';
import { storePalette } from './palette';
import { storeSlideSettings } from './slideSettings';
import { storeTextSettings } from './textSettings';
// import {storeTextSettings} from "./textSettings";
// import {storeParagraphSettings} from "./paragraphSettings";
// import {storeShapeSettings} from "./shapeSettings";
@ -24,7 +25,8 @@ export const stores = {
storePresentationInfo: new storePresentationInfo(),
storePresentationSettings: new storePresentationSettings(),
storeSlideSettings: new storeSlideSettings(),
storePalette: new storePalette()
storePalette: new storePalette(),
storeTextSettings: new storeTextSettings()
// storeTextSettings: new storeTextSettings(),
// storeParagraphSettings: new storeParagraphSettings(),
// storeShapeSettings: new storeShapeSettings(),

View file

@ -0,0 +1,168 @@
import {action, observable, computed} from 'mobx';
export class storeTextSettings {
@observable fontsArray = [];
@observable fontName = '';
@observable fontSize = undefined;
@observable isBold = false;
@observable isItalic = false;
@observable isUnderline = false;
@observable isStrikethrough = false;
@observable typeBaseline = undefined;
@observable listType = undefined;
@observable typeBullets = undefined;
@observable typeNumbers = undefined;
@observable paragraphAlign = undefined;
@observable paragraphValign = undefined;
@observable canIncreaseIndent = undefined;
@observable canDecreaseIndent = undefined;
@observable textColor = undefined;
@observable customTextColors = [];
@observable lineSpacing = undefined;
// @observable backgroundColor = undefined;
@action initEditorFonts (fonts, select) {
let array = [];
for (let font of fonts) {
let fontId = font.asc_getFontId();
array.push({
id : fontId,
name : font.asc_getFontName(),
//displayValue: font.asc_getFontName(),
imgidx : font.asc_getFontThumbnail(),
type : font.asc_getFontType()
});
}
this.fontsArray = array;
}
@action resetFontName (font) {
let name = (typeof font.get_Name) === "function" ? font.get_Name() : font.asc_getName();
this.fontName = name;
}
@action resetFontSize (size) {
this.fontSize = size;
}
@action resetIsBold (isBold) {
this.isBold = isBold;
}
@action resetIsItalic (isItalic) {
this.isItalic = isItalic;
}
@action resetIsUnderline (isUnderline) {
this.isUnderline = isUnderline;
}
@action resetIsStrikeout (isStrikethrough) {
this.isStrikethrough = isStrikethrough;
}
// Indent
@action resetIncreaseIndent(value) {
this.canIncreaseIndent = value;
}
@action resetDecreaseIndent(value) {
this.canDecreaseIndent = value;
}
// vertical align
@action resetTypeBaseline (typeBaseline) {
this.typeBaseline = typeBaseline;
}
@computed get isSuperscript() {
return (this.typeBaseline === 1);
}
@computed get isSubscript() {
return (this.typeBaseline === 2);
}
// bullets
@action resetListType (type) {
this.listType = type;
}
@action resetBullets (type) {
this.typeBullets = type;
}
@action resetNumbers (type) {
this.typeNumbers = type;
}
@action resetParagraphAlign (align) {
let value;
switch (align) {
case 0:
value = 'right';
break;
case 1:
value = 'left';
break;
case 2:
value = 'center';
break;
case 3:
value = 'just';
break;
}
this.paragraphAlign = value;
}
@action resetParagraphValign (align) {
let value;
switch (align) {
case 0:
value = 'bottom';
break;
case 4:
value = 'top';
break;
case 1:
value = 'center';
break;
}
this.paragraphValign = value;
}
@action resetTextColor (color) {
let value;
if (color) {
if (color.get_auto()) {
value = 'auto';
} else {
if (color.get_type() == Asc.c_oAscColor.COLOR_TYPE_SCHEME) {
value = {
color: Common.Utils.ThemeColor.getHexColor(color.get_r(), color.get_g(), color.get_b()),
effectValue: color.get_value()
}
} else {
value = Common.Utils.ThemeColor.getHexColor(color.get_r(), color.get_g(), color.get_b());
}
}
}
this.textColor = value;
}
@action changeCustomTextColors (colors) {
this.customTextColors = colors;
}
@action resetLineSpacing (vc) {
let line = (vc.get_Line() === null || vc.get_LineRule() === null || vc.get_LineRule() != 1) ? -1 : vc.get_Line();
this.lineSpacing = line;
}
// @action resetBackgroundColor (color) {
// let value;
// if (color.get_type() == Asc.c_oAscColor.COLOR_TYPE_SCHEME) {
// value = {
// color: Common.Utils.ThemeColor.getHexColor(color.get_r(), color.get_g(), color.get_b()),
// effectValue: color.get_value()
// }
// } else {
// value = Common.Utils.ThemeColor.getHexColor(color.get_r(), color.get_g(), color.get_b());
// }
// this.backgroundColor = value;
// }
}

View file

@ -1,15 +1,177 @@
import React, {Fragment, useState} from 'react';
import {observer, inject} from "mobx-react";
import {Page, Navbar, List, ListItem, ListButton, Row, BlockTitle, Range, Toggle, Icon} from 'framework7-react';
import {f7, List, ListItem, Icon, Row, Button, Page, Navbar, Segmented, BlockTitle} from 'framework7-react';
import { useTranslation } from 'react-i18next';
import {Device} from '../../../../../common/mobile/utils/device';
import { ThemeColorPalette, CustomColorPicker } from '../../../../../common/mobile/lib/component/ThemeColorPalette.jsx';
const EditText = props => {
const isAndroid = Device.android;
const { t } = useTranslation();
const _t = t('View.Edit', {returnObjects: true});
const metricText = Common.Utils.Metric.getCurrentMetricName();
const storeTextSettings = props.storeTextSettings;
const storeFocusObjects = props.storeFocusObjects;
const fontName = storeTextSettings.fontName || _t.textFonts;
const fontSize = storeTextSettings.fontSize;
const fontColor = storeTextSettings.textColor;
const displaySize = typeof fontSize === 'undefined' ? _t.textAuto : fontSize + ' ' + _t.textPt;
const isBold = storeTextSettings.isBold;
const isItalic = storeTextSettings.isItalic;
const isUnderline = storeTextSettings.isUnderline;
const isStrikethrough = storeTextSettings.isStrikethrough;
const paragraphAlign = storeTextSettings.paragraphAlign;
const paragraphValign = storeTextSettings.paragraphValign;
const canIncreaseIndent = storeTextSettings.canIncreaseIndent;
const canDecreaseIndent = storeTextSettings.canDecreaseIndent;
const paragraphObj = storeFocusObjects.paragraphObject;
// if (paragraphObj.get_Ind()===null || paragraphObj.get_Ind()===undefined) {
// paragraphObj.get_Ind().put_FirstLine(0);
// }
// const firstLine = parseFloat(Common.Utils.Metric.fnRecalcFromMM(paragraphObj.get_Ind().get_FirstLine()).toFixed(2));
const spaceBefore = paragraphObj.get_Spacing().get_Before() < 0 ? paragraphObj.get_Spacing().get_Before() : Common.Utils.Metric.fnRecalcFromMM(paragraphObj.get_Spacing().get_Before());
const spaceAfter = paragraphObj.get_Spacing().get_After() < 0 ? paragraphObj.get_Spacing().get_After() : Common.Utils.Metric.fnRecalcFromMM(paragraphObj.get_Spacing().get_After());
const spaceBeforeFix = parseFloat(spaceBefore.toFixed(2));
const spaceAfterFix = parseFloat(spaceAfter.toFixed(2));
const displayBefore = spaceBefore < 0 ? _t.textAuto : spaceBeforeFix + ' ' + metricText;
const displayAfter = spaceAfter < 0 ? _t.textAuto : spaceAfterFix + ' ' + metricText;
const fontColorPreview = fontColor !== 'auto' ?
<span className="color-preview" style={{ background: `#${(typeof fontColor === "object" ? fontColor.color : fontColor)}`}}></span> :
<span className="color-preview auto"></span>;
return (
<Fragment>
<List>
<ListItem title={fontName} link="/edit-text-fonts/" after={displaySize} routeProps={{
changeFontSize: props.changeFontSize,
changeFontFamily: props.changeFontFamily
}}/>
<ListItem className='buttons'>
<Row>
<a className={'button' + (isBold ? ' active' : '')} onClick={() => { props.toggleBold(!isBold)}}><b>B</b></a>
<a className={'button' + (isItalic ? ' active' : '')} onClick={() => {props.toggleItalic(!isItalic)}}><i>I</i></a>
<a className={'button' + (isUnderline ? ' active' : '')} onClick={() => {props.toggleUnderline(!isUnderline)}} style={{textDecoration: "underline"}}>U</a>
<a className={'button' + (isStrikethrough ? ' active' : '')} onClick={() => {props.toggleStrikethrough(!isStrikethrough)}} style={{textDecoration: "line-through"}}>S</a>
</Row>
</ListItem>
<ListItem title={_t.textFontColor} link="/edit-text-font-color/" routeProps={{
onTextColorAuto: props.onTextColorAuto,
onTextColor: props.onTextColor
}}>
{!isAndroid ?
<Icon slot="media" icon="icon-text-color">{fontColorPreview}</Icon> :
fontColorPreview
}
</ListItem>
<ListItem title={_t.textAdditionalFormatting} link="/edit-text-add-formatting/" routeProps={{
onAdditionalStrikethrough: props.onAdditionalStrikethrough,
onAdditionalCaps: props.onAdditionalCaps,
onAdditionalScript: props.onAdditionalScript,
changeLetterSpacing: props.changeLetterSpacing
}}>
{!isAndroid && <Icon slot="media" icon="icon-text-additional"></Icon>}
</ListItem>
</List>
<List>
<ListItem className='buttons'>
<Row>
<a className={'button' + (paragraphAlign === 'left' ? ' active' : '')} onClick={() => {props.onParagraphAlign('left')}}>
<Icon slot="media" icon="icon-text-align-left"></Icon>
</a>
<a className={'button' + (paragraphAlign === 'center' ? ' active' : '')} onClick={() => {props.onParagraphAlign('center')}}>
<Icon slot="media" icon="icon-text-align-center"></Icon>
</a>
<a className={'button' + (paragraphAlign === 'right' ? ' active' : '')} onClick={() => {props.onParagraphAlign('right')}}>
<Icon slot="media" icon="icon-text-align-right"></Icon>
</a>
<a className={'button' + (paragraphAlign === 'just' ? ' active' : '')} onClick={() => {props.onParagraphAlign('just')}}>
<Icon slot="media" icon="icon-text-align-just"></Icon>
</a>
</Row>
</ListItem>
<ListItem className='buttons'>
<Row>
<a className={'button' + (paragraphValign === 'top' ? ' active' : '')} onClick={() => {props.onParagraphValign('top')}}>
<Icon slot="media" icon="icon-text-valign-top"></Icon>
</a>
<a className={'button' + (paragraphValign === 'center' ? ' active' : '')} onClick={() => {props.onParagraphValign('center')}}>
<Icon slot="media" icon="icon-text-valign-middle"></Icon>
</a>
<a className={'button' + (paragraphValign === 'bottom' ? ' active' : '')} onClick={() => {props.onParagraphValign('bottom')}}>
<Icon slot="media" icon="icon-text-valign-bottom"></Icon>
</a>
</Row>
</ListItem>
<ListItem className='buttons'>
<Row>
<a className={'button item-link' + (!canDecreaseIndent ? ' disabled' : '') } onClick={() => {props.onParagraphMove('left')}}>
<Icon slot="media" icon="icon-de-indent"></Icon>
</a>
<a className={'button item-link' + (!canIncreaseIndent ? ' disabled' : '') } onClick={() => {props.onParagraphMove('right')}}>
<Icon slot="media" icon="icon-in-indent"></Icon>
</a>
</Row>
</ListItem>
<ListItem title={_t.textBullets} link='/edit-text-bullets/' routeProps={{
onBullet: props.onBullet
}}>
{!isAndroid && <Icon slot="media" icon="icon-bullets"></Icon>}
</ListItem>
<ListItem title={_t.textNumbers} link='/edit-text-numbers/' routeProps={{
onNumber: props.onNumber
}}>
{!isAndroid && <Icon slot="media" icon="icon-numbers"></Icon>}
</ListItem>
<ListItem title={_t.textLineSpacing} link='/edit-text-line-spacing/' routeProps={{
onLineSpacing: props.onLineSpacing
}}>
{!isAndroid && <Icon slot="media" icon="icon-linespacing"></Icon>}
</ListItem>
</List>
<BlockTitle>{_t.textDistanceFromText}</BlockTitle>
<List>
<ListItem title={_t.textBefore}>
{!isAndroid && <div slot='after-start'>{displayBefore}</div>}
<div slot='after'>
<Segmented>
<Button outline className='decrement item-link' onClick={() => {props.onDistanceBefore(spaceBefore, true)}}>
{isAndroid ? <Icon icon="icon-expand-down"></Icon> : ' - '}
</Button>
{isAndroid && <label>{displayBefore}</label>}
<Button outline className='increment item-link' onClick={() => {props.onDistanceBefore(spaceBefore, false)}}>
{isAndroid ? <Icon icon="icon-expand-up"></Icon> : ' + '}
</Button>
</Segmented>
</div>
</ListItem>
<ListItem title={_t.textAfter}>
{!isAndroid && <div slot='after-start'>{displayAfter}</div>}
<div slot='after'>
<Segmented>
<Button outline className='decrement item-link' onClick={() => {props.onDistanceAfter(spaceAfter, true)}}>
{isAndroid ? <Icon icon="icon-expand-down"></Icon> : ' - '}
</Button>
{isAndroid && <label>{displayAfter}</label>}
<Button outline className='increment item-link' onClick={() => {props.onDistanceAfter(spaceAfter, false)}}>
{isAndroid ? <Icon icon="icon-expand-up"></Icon> : ' + '}
</Button>
</Segmented>
</div>
</ListItem>
</List>
</Fragment>
)
};
export {EditText};
const EditTextContainer = inject("storeTextSettings", "storeFocusObjects")(observer(EditText));
export {
EditTextContainer as EditText
};