diff --git a/apps/documenteditor/mobile/locale/en.json b/apps/documenteditor/mobile/locale/en.json index 0d93dc185..feea3fe5b 100644 --- a/apps/documenteditor/mobile/locale/en.json +++ b/apps/documenteditor/mobile/locale/en.json @@ -81,11 +81,20 @@ "textAlign": "Align", "textMoveWithText": "Move with Text", "textAllowOverlap": "Allow Overlap", - "textDistanceFromText": "Distance from Text", "textBringToForeground": "Bring to Foreground", "textSendToBackground": "Send to Background", "textMoveForward": "Move Forward", - "textMoveBackward": "Move Backward" - + "textMoveBackward": "Move Backward", + "textActualSize": "Actual Size", + "textRemoveImage": "Remove Image", + "textPictureFromLibrary": "Picture from Library", + "textPictureFromURL": "Picture from URL", + "textLinkSettings": "Link Settings", + "textAddress": "Address", + "textImageURL": "Image URL", + "textReplaceImage": "Replace Image", + "textEmptyImgUrl": "You need to specify image URL.", + "textNotUrl": "This field should be a URL in the format \"http://www.example.com\"", + "notcriticalErrorTitle": "Warning" } } \ No newline at end of file diff --git a/apps/documenteditor/mobile/src/components/edit/Edit.jsx b/apps/documenteditor/mobile/src/components/edit/Edit.jsx index d4bdc1b88..4935ac0d6 100644 --- a/apps/documenteditor/mobile/src/components/edit/Edit.jsx +++ b/apps/documenteditor/mobile/src/components/edit/Edit.jsx @@ -8,10 +8,12 @@ import {Device} from '../../../../../common/mobile/utils/device'; import EditTextController from "./controller/EditText"; import EditParagraphController from "./controller/EditParagraph"; import EditShapeController from "./controller/EditShape"; +import EditImageController from "./controller/EditImage"; import {PageAdditionalFormatting, PageBullets, PageFonts, PageLineSpacing, PageNumbers} from "./EditText"; import {PageAdvancedSettings} from "./EditParagraph"; import {PageWrap, PageReorder, PageReplace} from "./EditShape"; +import {PageImageReorder, PageImageReplace, PageImageWrap, PageLinkSettings} from "./EditImage"; const routes = [ //Edit text @@ -52,6 +54,23 @@ const routes = [ { path: '/edit-shape-replace/', component: PageReplace, + }, + //Edit image + { + path: '/edit-image-wrap/', + component: PageImageWrap, + }, + { + path: '/edit-image-replace/', + component: PageImageReplace, + }, + { + path: '/edit-image-reorder/', + component: PageImageReorder, + }, + { + path: '/edit-image-link/', + component: PageLinkSettings, } ]; @@ -154,14 +173,14 @@ const EditTabs = props => { component: }) } - /*if (settings.indexOf('image') > -1) { + if (settings.indexOf('image') > -1) { editors.push({ caption: _t.textImage, id: 'edit-image', - component: + component: }) } - if (settings.indexOf('chart') > -1) { + /*if (settings.indexOf('chart') > -1) { editors.push({ caption: _t.textChart, id: 'edit-chart', diff --git a/apps/documenteditor/mobile/src/components/edit/EditImage.jsx b/apps/documenteditor/mobile/src/components/edit/EditImage.jsx new file mode 100644 index 000000000..21583db41 --- /dev/null +++ b/apps/documenteditor/mobile/src/components/edit/EditImage.jsx @@ -0,0 +1,192 @@ +import React, {Fragment, useState} from 'react'; +import {observer, inject} from "mobx-react"; +import {List, ListItem, ListInput, ListButton, Icon, Row, Col, Button, Page, Navbar, Segmented, BlockTitle, Toggle, Range} from 'framework7-react'; +import { useTranslation } from 'react-i18next'; +import {f7} from 'framework7-react'; + +const PageWrap = props => { + const { t } = useTranslation(); + const _t = t('Edit', {returnObjects: true}); + const storeImageSettings = props.storeImageSettings; + const imageObject = props.storeFocusObjects.imageObject; + const wrapType = storeImageSettings.getWrapType(imageObject); + const align = storeImageSettings.getAlign(imageObject); + const moveText = storeImageSettings.getMoveText(imageObject); + const overlap = storeImageSettings.getOverlap(imageObject); + const distance = Common.Utils.Metric.fnRecalcFromMM(storeImageSettings.getWrapDistance(imageObject)); + const metricText = Common.Utils.Metric.getCurrentMetricName(); + const [stateDistance, setDistance] = useState(distance); + return ( + + + + {props.onWrapType('inline')}}> + {props.onWrapType('square')}}> + {props.onWrapType('tight')}}> + {props.onWrapType('through')}}> + {props.onWrapType('top-bottom')}}> + {props.onWrapType('infront')}}> + {props.onWrapType('behind')}}> + + { + wrapType !== 'inline' && + + {_t.textAlign} + + + + { + props.onAlign(Asc.c_oAscAlignH.Left) + }}>left + { + props.onAlign(Asc.c_oAscAlignH.Center) + }}>center + { + props.onAlign(Asc.c_oAscAlignH.Righ) + }}>right + + + + + } + + + {props.onMoveText(!moveText)}}/> + + + {props.onOverlap(!overlap)}}/> + + + { + ('inline' !== wrapType && 'behind' !== wrapType && 'infront' !== wrapType) && + + {_t.textDistanceFromText} + + + + {setDistance(value)}} + onRangeChanged={(value) => {props.onWrapDistance(value)}} + > + + + {stateDistance + ' ' + metricText} + + + + + } + + ) +}; + +const PageLinkSettings = props => { + const { t } = useTranslation(); + const _t = t('Edit', {returnObjects: true}); + const [stateValue, setValue] = useState(''); + const onReplace = () => { + if (stateValue.trim().length > 0) { + if ((/((^https?)|(^ftp)):\/\/.+/i.test(stateValue))) { + props.onReplaceByUrl(stateValue.trim()); + } else { + f7.dialog.alert(_t.textNotUrl, _t.notcriticalErrorTitle); + } + } else { + f7.dialog.alert(_t.textEmptyImgUrl, _t.notcriticalErrorTitle); + } + }; + return ( + + + {_t.textAddress} + + {setValue(event.target.value)}} + > + + + + {onReplace()}}> + + + ) +}; + +const PageReplace = props => { + const { t } = useTranslation(); + const _t = t('Edit', {returnObjects: true}); + return ( + + + + {props.onReplaceByFile()}}> + + + + ) +}; + +const PageReorder = props => { + const { t } = useTranslation(); + const _t = t('Edit', {returnObjects: true}); + return ( + + + + {props.onReorder('all-up')}}> + {props.onReorder('all-down')}}> + {props.onReorder('move-up')}}> + {props.onReorder('move-down')}}> + + + ) +}; + +const EditImage = props => { + const { t } = useTranslation(); + const _t = t('Edit', {returnObjects: true}); + return ( + + + + + + + + {props.onDefaulSize()}}/> + {props.onRemoveImage()}}/> + + + ) +}; + +const EditImageContainer = inject("storeFocusObjects")(observer(EditImage)); +const PageWrapContainer = inject("storeFocusObjects", "storeImageSettings")(observer(PageWrap)); +const PageReplaceContainer = inject("storeFocusObjects")(observer(PageReplace)); +const PageReorderContainer = inject("storeFocusObjects")(observer(PageReorder)); +const PageLinkSettingsContainer = inject("storeFocusObjects")(observer(PageLinkSettings)); + +export {EditImageContainer as EditImage, + PageWrapContainer as PageImageWrap, + PageReplaceContainer as PageImageReplace, + PageReorderContainer as PageImageReorder, + PageLinkSettingsContainer as PageLinkSettings} \ No newline at end of file diff --git a/apps/documenteditor/mobile/src/components/edit/controller/EditImage.jsx b/apps/documenteditor/mobile/src/components/edit/controller/EditImage.jsx new file mode 100644 index 000000000..106fe8187 --- /dev/null +++ b/apps/documenteditor/mobile/src/components/edit/controller/EditImage.jsx @@ -0,0 +1,154 @@ +import React, {Component} from 'react'; +import { f7 } from 'framework7-react'; +import {Device} from '../../../../../../common/mobile/utils/device'; +import {observer, inject} from "mobx-react"; + +import { EditImage } from '../EditImage' + +class EditImageController extends Component { + constructor (props) { + super(props); + this.onWrapType = this.onWrapType.bind(this); + this.onRemoveImage = this.onRemoveImage.bind(this); + this.onReplaceByFile = this.onReplaceByFile.bind(this); + this.onReplaceByUrl = this.onReplaceByUrl.bind(this); + } + + closeModal () { + if ( Device.phone ) { + f7.sheet.close('#edit-sheet', true); + } else { + f7.popover.close('#edit-popover'); + } + } + + onDefaulSize () { + const api = Common.EditorApi.get(); + if (api) { + const imgSize = api.get_OriginalSizeImage(); + const properties = new Asc.asc_CImgProperty(); + properties.put_Width(imgSize.get_ImageWidth()); + properties.put_Height(imgSize.get_ImageHeight()); + properties.put_ResetCrop(true); + api.ImgApply(properties); + } + } + + onRemoveImage () { + const api = Common.EditorApi.get(); + if (api) { + api.asc_Remove(); + this.closeModal() + } + } + + onWrapType (type) { + const api = Common.EditorApi.get(); + if (api) { + const properties = new Asc.asc_CImgProperty(); + const sdkType = this.props.storeImageSettings.transformToSdkWrapType(type); + properties.put_WrappingStyle(sdkType); + api.ImgApply(properties); + } + } + + onAlign (type) { + const api = Common.EditorApi.get(); + if (api) { + const properties = new Asc.asc_CImgProperty(); + properties.put_PositionH(new Asc.CImagePositionH()); + properties.get_PositionH().put_UseAlign(true); + properties.get_PositionH().put_Align(type); + properties.get_PositionH().put_RelativeFrom(Asc.c_oAscRelativeFromH.Page); + api.ImgApply(properties); + } + } + + onMoveText (value) { + const api = Common.EditorApi.get(); + if (api) { + const properties = new Asc.asc_CImgProperty(); + properties.put_PositionV(new Asc.CImagePositionV()); + properties.get_PositionV().put_UseAlign(true); + properties.get_PositionV().put_RelativeFrom(value ? Asc.c_oAscRelativeFromV.Paragraph : Asc.c_oAscRelativeFromV.Page); + api.ImgApply(properties); + } + } + + onOverlap (value) { + const api = Common.EditorApi.get(); + if (api) { + const properties = new Asc.asc_CImgProperty(); + properties.put_AllowOverlap(value); + api.ImgApply(properties); + } + } + + onWrapDistance (value) { + const api = Common.EditorApi.get(); + if (api) { + const properties = new Asc.asc_CImgProperty(); + const paddings = new Asc.asc_CPaddings(); + const distance = Common.Utils.Metric.fnRecalcToMM(parseInt(value)); + paddings.put_Top(distance); + paddings.put_Right(distance); + paddings.put_Bottom(distance); + paddings.put_Left(distance); + properties.put_Paddings(paddings); + api.ImgApply(properties); + } + } + + onReplaceByFile () { + const api = Common.EditorApi.get(); + if (api) { + api.ChangeImageFromFile(); + this.closeModal(); + } + } + + onReplaceByUrl (value) { + const api = Common.EditorApi.get(); + if (api) { + const image = new Asc.asc_CImgProperty(); + image.put_ImageUrl(value); + api.ImgApply(image); + this.closeModal(); + } + } + + onReorder (type) { + const api = Common.EditorApi.get(); + if (api) { + const properties = new Asc.asc_CImgProperty(); + if ('all-up' == type) { + properties.put_ChangeLevel(Asc.c_oAscChangeLevel.BringToFront); + } else if ('all-down' == type) { + properties.put_ChangeLevel(Asc.c_oAscChangeLevel.SendToBack); + } else if ('move-up' == type) { + properties.put_ChangeLevel(Asc.c_oAscChangeLevel.BringForward); + } else if ('move-down' == type) { + properties.put_ChangeLevel(Asc.c_oAscChangeLevel.BringBackward); + } + api.ImgApply(properties); + } + } + + render () { + return ( + + ) + } +} + +export default inject("storeImageSettings")(observer(EditImageController)); \ No newline at end of file diff --git a/apps/documenteditor/mobile/src/store/focusObjects.js b/apps/documenteditor/mobile/src/store/focusObjects.js index 8f654e8c8..70dd0c389 100644 --- a/apps/documenteditor/mobile/src/store/focusObjects.js +++ b/apps/documenteditor/mobile/src/store/focusObjects.js @@ -73,4 +73,21 @@ export class storeFocusObjects { return undefined; } } + @computed get imageObject() { + let images = []; + for (let object of this._focusObjects) { + if (object.get_ObjectType() == Asc.c_oAscTypeSelectElement.Image) { + const imageObject = object.get_ObjectValue(); + if (imageObject && imageObject.get_ShapeProperties() === null && imageObject.get_ChartProperties() === null) { + images.push(object); + } + } + } + if (images.length > 0) { + let object = images[images.length - 1]; // get top + return object.get_ObjectValue(); + } else { + return undefined; + } + } } \ No newline at end of file diff --git a/apps/documenteditor/mobile/src/store/imageSettings.js b/apps/documenteditor/mobile/src/store/imageSettings.js new file mode 100644 index 000000000..277e4a31f --- /dev/null +++ b/apps/documenteditor/mobile/src/store/imageSettings.js @@ -0,0 +1,57 @@ +import {action, observable, computed} from 'mobx'; + +export class storeImageSettings { + wrapTypesTransform () { + const map = [ + { ui:'inline', sdk: Asc.c_oAscWrapStyle2.Inline }, + { ui:'square', sdk: Asc.c_oAscWrapStyle2.Square }, + { ui:'tight', sdk: Asc.c_oAscWrapStyle2.Tight }, + { ui:'through', sdk: Asc.c_oAscWrapStyle2.Through }, + { ui:'top-bottom', sdk: Asc.c_oAscWrapStyle2.TopAndBottom }, + { ui:'behind', sdk: Asc.c_oAscWrapStyle2.Behind }, + { ui:'infront', sdk: Asc.c_oAscWrapStyle2.InFront } + ]; + return { + sdkToUi: function(type) { + let record = map.filter(function(obj) { + return obj.sdk === type; + })[0]; + return record ? record.ui : ''; + }, + + uiToSdk: function(type) { + let record = map.filter(function(obj) { + return obj.ui === type; + })[0]; + return record ? record.sdk : 0; + } + } + } + + getWrapType (imageObject) { + const wrapping = imageObject.get_WrappingStyle(); + const imageWrapType = this.wrapTypesTransform().sdkToUi(wrapping); + return imageWrapType; + } + + transformToSdkWrapType (value) { + const sdkType = this.wrapTypesTransform().uiToSdk(value); + return sdkType; + } + + getAlign (imageObject) { + return imageObject.get_PositionH().get_Align(); + } + + getMoveText (imageObject) { + return imageObject.get_PositionV().get_RelativeFrom() === Asc.c_oAscRelativeFromV.Paragraph; + } + + getOverlap (imageObject) { + return imageObject.get_AllowOverlap(); + } + + getWrapDistance (imageObject) { + return imageObject.get_Paddings().get_Top(); + } +} \ No newline at end of file diff --git a/apps/documenteditor/mobile/src/store/mainStore.js b/apps/documenteditor/mobile/src/store/mainStore.js index b7d2b7f4b..1f9638895 100644 --- a/apps/documenteditor/mobile/src/store/mainStore.js +++ b/apps/documenteditor/mobile/src/store/mainStore.js @@ -5,6 +5,7 @@ import {storeUsers} from '../../../../common/mobile/lib/store/users'; import {storeTextSettings} from "./textSettings"; import {storeParagraphSettings} from "./paragraphSettings"; import {storeShapeSettings} from "./shapeSettings"; +import {storeImageSettings} from "./imageSettings"; export const stores = { storeFocusObjects: new storeFocusObjects(), @@ -12,6 +13,7 @@ export const stores = { users: new storeUsers(), storeTextSettings: new storeTextSettings(), storeParagraphSettings: new storeParagraphSettings(), - storeShapeSettings: new storeShapeSettings() + storeShapeSettings: new storeShapeSettings(), + storeImageSettings: new storeImageSettings() };