• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2023-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15const pasteboard = requireNapi('pasteboard');
16const hilog = requireNapi('hilog');
17const SymbolGlyphModifier = requireNapi('arkui.modifier').SymbolGlyphModifier;
18
19if (!('finalizeConstruction' in ViewPU.prototype)) {
20    Reflect.set(ViewPU.prototype, 'finalizeConstruction', () => {
21    });
22}
23
24const WITHOUT_BUILDER = -2;
25const MAX_FONT_STANDARD = 1.0;
26const MAX_FONT_SCALE = 1.75;
27const SYMBOL_SIZE = 24;
28const defaultTheme = {
29    imageSize: 24,
30    buttonSize: 40,
31    menuSpacing: 8,
32    expandedOptionPadding: 4,
33    defaultMenuWidth: 224,
34    menuItemPadding: {
35        'id': -1,
36        'type': 10002,
37        params: ['sys.float.padding_level1'],
38        'bundleName': '__harDefaultBundleName__',
39        'moduleName': '__harDefaultModuleName__'
40    },
41    imageFillColor: {
42        'id': -1,
43        'type': 10001,
44        params: ['sys.color.ohos_id_color_primary'],
45        'bundleName': '__harDefaultBundleName__',
46        'moduleName': '__harDefaultModuleName__'
47    },
48    backGroundColor: {
49        'id': -1,
50        'type': 10001,
51        params: ['sys.color.ohos_id_color_dialog_bg'],
52        'bundleName': '__harDefaultBundleName__',
53        'moduleName': '__harDefaultModuleName__'
54    },
55    iconBorderRadius: {
56        'id': -1,
57        'type': 10002,
58        params: ['sys.float.corner_radius_level2'],
59        'bundleName': '__harDefaultBundleName__',
60        'moduleName': '__harDefaultModuleName__'
61    },
62    containerBorderRadius: {
63        'id': -1,
64        'type': 10002,
65        params: ['sys.float.corner_radius_level4'],
66        'bundleName': '__harDefaultBundleName__',
67        'moduleName': '__harDefaultModuleName__'
68    },
69    borderWidth: {
70        'id': -1,
71        'type': 10002,
72        params: ['sys.float.ohos_id_menu_inner_border_width'],
73        'bundleName': '__harDefaultBundleName__',
74        'moduleName': '__harDefaultModuleName__'
75    },
76    borderColor: {
77        'id': -1,
78        'type': 10001,
79        params: ['sys.color.ohos_id_menu_inner_border_color'],
80        'bundleName': '__harDefaultBundleName__',
81        'moduleName': '__harDefaultModuleName__'
82    },
83    outlineWidth: {
84        'id': -1,
85        'type': 10002,
86        params: ['sys.float.ohos_id_menu_outer_border_width'],
87        'bundleName': '__harDefaultBundleName__',
88        'moduleName': '__harDefaultModuleName__'
89    },
90    outlineColor: {
91        'id': -1,
92        'type': 10001,
93        params: ['sys.color.ohos_id_menu_outer_border_color'],
94        'bundleName': '__harDefaultBundleName__',
95        'moduleName': '__harDefaultModuleName__'
96    },
97    cutIcon: {
98        'id': -1,
99        'type': 20000,
100        params: ['sys.media.ohos_ic_public_cut'],
101        'bundleName': '__harDefaultBundleName__',
102        'moduleName': '__harDefaultModuleName__'
103    },
104    copyIcon: {
105        'id': -1,
106        'type': 20000,
107        params: ['sys.media.ohos_ic_public_copy'],
108        'bundleName': '__harDefaultBundleName__',
109        'moduleName': '__harDefaultModuleName__'
110    },
111    pasteIcon: {
112        'id': -1,
113        'type': 20000,
114        params: ['sys.media.ohos_ic_public_paste'],
115        'bundleName': '__harDefaultBundleName__',
116        'moduleName': '__harDefaultModuleName__'
117    },
118    selectAllIcon: {
119        'id': -1,
120        'type': 20000,
121        params: ['sys.media.ohos_ic_public_select_all'],
122        'bundleName': '__harDefaultBundleName__',
123        'moduleName': '__harDefaultModuleName__'
124    },
125    shareIcon: {
126        'id': -1,
127        'type': 20000,
128        params: ['sys.media.ohos_ic_public_share'],
129        'bundleName': '__harDefaultBundleName__',
130        'moduleName': '__harDefaultModuleName__'
131    },
132    translateIcon: {
133        'id': -1,
134        'type': 20000,
135        params: ['sys.media.ohos_ic_public_translate_c2e'],
136        'bundleName': '__harDefaultBundleName__',
137        'moduleName': '__harDefaultModuleName__'
138    },
139    searchIcon: {
140        'id': -1,
141        'type': 20000,
142        params: ['sys.media.ohos_ic_public_search_filled'],
143        'bundleName': '__harDefaultBundleName__',
144        'moduleName': '__harDefaultModuleName__'
145    },
146    arrowDownIcon: {
147        'id': -1,
148        'type': 20000,
149        params: ['sys.media.ohos_ic_public_arrow_down'],
150        'bundleName': '__harDefaultBundleName__',
151        'moduleName': '__harDefaultModuleName__'
152    },
153    iconPanelShadowStyle: ShadowStyle.OUTER_DEFAULT_SM,
154    defaultSymbolTheme: {
155        fontSize: `${SYMBOL_SIZE}vp`,
156        fontColor: [{
157            'id': -1,
158            'type': 10001,
159            params: ['sys.color.ohos_id_color_primary'],
160            'bundleName': '__harDefaultBundleName__',
161            'moduleName': '__harDefaultModuleName__'
162        }],
163        symbolCutIcon: new SymbolGlyphModifier({
164            'id': -1,
165            'type': 40000,
166            params: ['sys.symbol.cut'],
167            'bundleName': '__harDefaultBundleName__',
168            'moduleName': '__harDefaultModuleName__'
169        }),
170        symbolCopyIcon: new SymbolGlyphModifier({
171            'id': -1,
172            'type': 40000,
173            params: ['sys.symbol.plus_square_on_square'],
174            'bundleName': '__harDefaultBundleName__',
175            'moduleName': '__harDefaultModuleName__'
176        }),
177        symbolPasteIcon: new SymbolGlyphModifier({
178            'id': -1,
179            'type': 40000,
180            params: ['sys.symbol.plus_square_dashed_on_square'],
181            'bundleName': '__harDefaultBundleName__',
182            'moduleName': '__harDefaultModuleName__'
183        }),
184        symbolSelectAllIcon: new SymbolGlyphModifier({
185            'id': -1,
186            'type': 40000,
187            params: ['sys.symbol.checkmark_square_on_square'],
188            'bundleName': '__harDefaultBundleName__',
189            'moduleName': '__harDefaultModuleName__'
190        }),
191        symbolShareIcon: new SymbolGlyphModifier({
192            'id': -1,
193            'type': 40000,
194            params: ['sys.symbol.share'],
195            'bundleName': '__harDefaultBundleName__',
196            'moduleName': '__harDefaultModuleName__'
197        }),
198        symbolTranslateIcon: new SymbolGlyphModifier({
199            'id': -1,
200            'type': 40000,
201            params: ['sys.symbol.translate_c2e'],
202            'bundleName': '__harDefaultBundleName__',
203            'moduleName': '__harDefaultModuleName__'
204        }),
205        symbolSearchIcon: new SymbolGlyphModifier({
206            'id': -1,
207            'type': 40000,
208            params: ['sys.symbol.magnifyingglass'],
209            'bundleName': '__harDefaultBundleName__',
210            'moduleName': '__harDefaultModuleName__'
211        }),
212        symbolArrowDownIcon: new SymbolGlyphModifier({
213            'id': -1,
214            'type': 40000,
215            params: ['sys.symbol.chevron_down'],
216            'bundleName': '__harDefaultBundleName__',
217            'moduleName': '__harDefaultModuleName__'
218        }),
219    },
220};
221
222class SelectionMenuComponent extends ViewPU {
223    constructor(parent, params, __localStorage, elmtId = -1, paramsLambda = undefined, extraInfo) {
224        super(parent, __localStorage, elmtId, extraInfo);
225        if (typeof paramsLambda === 'function') {
226            this.paramsGenerator_ = paramsLambda;
227        }
228        this.editorMenuOptions = undefined;
229        this.expandedMenuOptions = undefined;
230        this.controller = undefined;
231        this.onPaste = undefined;
232        this.onCopy = undefined;
233        this.onCut = undefined;
234        this.onSelectAll = undefined;
235        this.theme = defaultTheme;
236        this.builder = this.CloserFun;
237        this.__showExpandedMenuOptions = new ObservedPropertySimplePU(false, this, 'showExpandedMenuOptions');
238        this.__showCustomerIndex = new ObservedPropertySimplePU(-1, this, 'showCustomerIndex');
239        this.__customerChange = new ObservedPropertySimplePU(false, this, 'customerChange');
240        this.__cutAndCopyEnable = new ObservedPropertySimplePU(false, this, 'cutAndCopyEnable');
241        this.__pasteEnable = new ObservedPropertySimplePU(false, this, 'pasteEnable');
242        this.__visibilityValue = new ObservedPropertySimplePU(Visibility.Visible, this, 'visibilityValue');
243        this.__fontScale = new ObservedPropertySimplePU(1, this, 'fontScale');
244        this.__customMenuWidth = new ObservedPropertySimplePU(this.theme.defaultMenuWidth, this, 'customMenuWidth');
245        this.__horizontalMenuHeight = new ObservedPropertySimplePU(0, this, 'horizontalMenuHeight');
246        this.__horizontalMenuWidth =
247            new ObservedPropertySimplePU(this.theme.defaultMenuWidth, this, 'horizontalMenuWidth');
248        this.fontWeightTable =
249            ['100', '200', '300', '400', '500', '600', '700', '800', '900', 'bold', 'normal', 'bolder', 'lighter',
250                'medium',
251                'regular'];
252        this.isFollowingSystemFontScale = false;
253        this.appMaxFontScale = 3.2;
254        this.setInitiallyProvidedValue(params);
255        this.finalizeConstruction();
256    }
257
258    setInitiallyProvidedValue(params) {
259        if (params.editorMenuOptions !== undefined) {
260            this.editorMenuOptions = params.editorMenuOptions;
261        }
262        if (params.expandedMenuOptions !== undefined) {
263            this.expandedMenuOptions = params.expandedMenuOptions;
264        }
265        if (params.controller !== undefined) {
266            this.controller = params.controller;
267        }
268        if (params.onPaste !== undefined) {
269            this.onPaste = params.onPaste;
270        }
271        if (params.onCopy !== undefined) {
272            this.onCopy = params.onCopy;
273        }
274        if (params.onCut !== undefined) {
275            this.onCut = params.onCut;
276        }
277        if (params.onSelectAll !== undefined) {
278            this.onSelectAll = params.onSelectAll;
279        }
280        if (params.theme !== undefined) {
281            this.theme = params.theme;
282        }
283        if (params.builder !== undefined) {
284            this.builder = params.builder;
285        }
286        if (params.showExpandedMenuOptions !== undefined) {
287            this.showExpandedMenuOptions = params.showExpandedMenuOptions;
288        }
289        if (params.showCustomerIndex !== undefined) {
290            this.showCustomerIndex = params.showCustomerIndex;
291        }
292        if (params.customerChange !== undefined) {
293            this.customerChange = params.customerChange;
294        }
295        if (params.cutAndCopyEnable !== undefined) {
296            this.cutAndCopyEnable = params.cutAndCopyEnable;
297        }
298        if (params.pasteEnable !== undefined) {
299            this.pasteEnable = params.pasteEnable;
300        }
301        if (params.visibilityValue !== undefined) {
302            this.visibilityValue = params.visibilityValue;
303        }
304        if (params.fontScale !== undefined) {
305            this.fontScale = params.fontScale;
306        }
307        if (params.customMenuWidth !== undefined) {
308            this.customMenuWidth = params.customMenuWidth;
309        }
310        if (params.horizontalMenuHeight !== undefined) {
311            this.horizontalMenuHeight = params.horizontalMenuHeight;
312        }
313        if (params.horizontalMenuWidth !== undefined) {
314            this.horizontalMenuWidth = params.horizontalMenuWidth;
315        }
316        if (params.fontWeightTable !== undefined) {
317            this.fontWeightTable = params.fontWeightTable;
318        }
319        if (params.isFollowingSystemFontScale !== undefined) {
320            this.isFollowingSystemFontScale = params.isFollowingSystemFontScale;
321        }
322        if (params.appMaxFontScale !== undefined) {
323            this.appMaxFontScale = params.appMaxFontScale;
324        }
325    }
326
327    updateStateVars(params) {
328    }
329
330    purgeVariableDependenciesOnElmtId(rmElmtId) {
331        this.__showExpandedMenuOptions.purgeDependencyOnElmtId(rmElmtId);
332        this.__showCustomerIndex.purgeDependencyOnElmtId(rmElmtId);
333        this.__customerChange.purgeDependencyOnElmtId(rmElmtId);
334        this.__cutAndCopyEnable.purgeDependencyOnElmtId(rmElmtId);
335        this.__pasteEnable.purgeDependencyOnElmtId(rmElmtId);
336        this.__visibilityValue.purgeDependencyOnElmtId(rmElmtId);
337        this.__fontScale.purgeDependencyOnElmtId(rmElmtId);
338        this.__customMenuWidth.purgeDependencyOnElmtId(rmElmtId);
339        this.__horizontalMenuHeight.purgeDependencyOnElmtId(rmElmtId);
340        this.__horizontalMenuWidth.purgeDependencyOnElmtId(rmElmtId);
341    }
342
343    aboutToBeDeleted() {
344        this.__showExpandedMenuOptions.aboutToBeDeleted();
345        this.__showCustomerIndex.aboutToBeDeleted();
346        this.__customerChange.aboutToBeDeleted();
347        this.__cutAndCopyEnable.aboutToBeDeleted();
348        this.__pasteEnable.aboutToBeDeleted();
349        this.__visibilityValue.aboutToBeDeleted();
350        this.__fontScale.aboutToBeDeleted();
351        this.__customMenuWidth.aboutToBeDeleted();
352        this.__horizontalMenuHeight.aboutToBeDeleted();
353        this.__horizontalMenuWidth.aboutToBeDeleted();
354        SubscriberManager.Get().delete(this.id__());
355        this.aboutToBeDeletedInternal();
356    }
357
358    CloserFun(parent = null) {
359    }
360
361    get showExpandedMenuOptions() {
362        return this.__showExpandedMenuOptions.get();
363    }
364
365    set showExpandedMenuOptions(newValue) {
366        this.__showExpandedMenuOptions.set(newValue);
367    }
368
369    get showCustomerIndex() {
370        return this.__showCustomerIndex.get();
371    }
372
373    set showCustomerIndex(newValue) {
374        this.__showCustomerIndex.set(newValue);
375    }
376
377    get customerChange() {
378        return this.__customerChange.get();
379    }
380
381    set customerChange(newValue) {
382        this.__customerChange.set(newValue);
383    }
384
385    get cutAndCopyEnable() {
386        return this.__cutAndCopyEnable.get();
387    }
388
389    set cutAndCopyEnable(newValue) {
390        this.__cutAndCopyEnable.set(newValue);
391    }
392
393    get pasteEnable() {
394        return this.__pasteEnable.get();
395    }
396
397    set pasteEnable(newValue) {
398        this.__pasteEnable.set(newValue);
399    }
400
401    get visibilityValue() {
402        return this.__visibilityValue.get();
403    }
404
405    set visibilityValue(newValue) {
406        this.__visibilityValue.set(newValue);
407    }
408
409    get fontScale() {
410        return this.__fontScale.get();
411    }
412
413    set fontScale(newValue) {
414        this.__fontScale.set(newValue);
415    }
416
417    get customMenuWidth() {
418        return this.__customMenuWidth.get();
419    }
420
421    set customMenuWidth(newValue) {
422        this.__customMenuWidth.set(newValue);
423    }
424
425    get horizontalMenuHeight() {
426        return this.__horizontalMenuHeight.get();
427    }
428
429    set horizontalMenuHeight(newValue) {
430        this.__horizontalMenuHeight.set(newValue);
431    }
432
433    get horizontalMenuWidth() {
434        return this.__horizontalMenuWidth.get();
435    }
436
437    set horizontalMenuWidth(newValue) {
438        this.__horizontalMenuWidth.set(newValue);
439    }
440
441    aboutToAppear() {
442        if (this.controller) {
443            let richEditorSelection = this.controller.getSelection();
444            let start = richEditorSelection.selection[0];
445            let end = richEditorSelection.selection[1];
446            if (start !== end) {
447                this.cutAndCopyEnable = true;
448            }
449            if (start === 0 && this.controller.getSpans({ start: end + 1, end: end + 1 }).length === 0) {
450                this.visibilityValue = Visibility.None;
451            } else {
452                this.visibilityValue = Visibility.Visible;
453            }
454        } else if (this.expandedMenuOptions && this.expandedMenuOptions.length > 0) {
455            this.showExpandedMenuOptions = true;
456        }
457        let sysBoard = pasteboard.getSystemPasteboard();
458        if (sysBoard && sysBoard.hasDataSync()) {
459            this.pasteEnable = true;
460        }
461        let uiContext = this.getUIContext();
462        if (uiContext) {
463            this.isFollowingSystemFontScale = uiContext.isFollowingSystemFontScale();
464            this.appMaxFontScale = uiContext.getMaxFontScale();
465        }
466        this.fontScale = this.getFontScale();
467    }
468
469    hasSystemMenu() {
470        let showMenuOption = this.showCustomerIndex === -1 &&
471            (this.controller || (this.expandedMenuOptions && this.expandedMenuOptions.length > 0));
472        let showBuilder = this.showCustomerIndex > -1 && this.builder;
473        return Boolean(showMenuOption || showBuilder);
474    }
475
476    initialRender() {
477        this.observeComponentCreation2((elmtId, isInitialRender) => {
478            Column.create();
479            Column.useShadowBatching(true);
480            Column.constraintSize({
481                maxHeight: '100%',
482                minWidth: this.theme.defaultMenuWidth
483            });
484        }, Column);
485        this.observeComponentCreation2((elmtId, isInitialRender) => {
486            If.create();
487            if (this.editorMenuOptions && this.editorMenuOptions.length > 0) {
488                this.ifElseBranchUpdateFunction(0, () => {
489                    this.IconPanel.bind(this)();
490                });
491            } else {
492                this.ifElseBranchUpdateFunction(1, () => {
493                });
494            }
495        }, If);
496        If.pop();
497        this.observeComponentCreation2((elmtId, isInitialRender) => {
498            Scroll.create();
499            Scroll.backgroundColor(this.theme.backGroundColor);
500            Scroll.shadow(this.theme.iconPanelShadowStyle);
501            Scroll.borderRadius(this.theme.containerBorderRadius);
502            Scroll.outline(this.hasSystemMenu() ? {
503                width: this.theme.outlineWidth, color: this.theme.outlineColor,
504                radius: this.theme.containerBorderRadius
505            } : undefined);
506            Scroll.constraintSize({
507                maxHeight: `calc(100% - ${this.horizontalMenuHeight > 0 ?
508                    this.horizontalMenuHeight + this.theme.menuSpacing : 0}vp)`,
509                minWidth: this.theme.defaultMenuWidth
510            });
511        }, Scroll);
512        this.SystemMenu.bind(this)();
513        Scroll.pop();
514        Column.pop();
515    }
516
517    pushDataToPasteboard(richEditorSelection) {
518        let sysBoard = pasteboard.getSystemPasteboard();
519        let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_PLAIN, '');
520        if (richEditorSelection.spans && richEditorSelection.spans.length > 0) {
521            let count = richEditorSelection.spans.length;
522            for (let i = count - 1; i >= 0; i--) {
523                let item = richEditorSelection.spans[i];
524                if (item?.textStyle) {
525                    let span = item;
526                    let style = span.textStyle;
527                    let data = pasteboard.createRecord(pasteboard.MIMETYPE_TEXT_PLAIN,
528                        span.value.substring(span.offsetInSpan[0], span.offsetInSpan[1]));
529                    let prop = pasteData.getProperty();
530                    let temp = {
531                        'color': style.fontColor,
532                        'size': style.fontSize,
533                        'style': style.fontStyle,
534                        'weight': this.fontWeightTable[style.fontWeight],
535                        'fontFamily': style.fontFamily,
536                        'decorationType': style.decoration.type,
537                        'decorationColor': style.decoration.color
538                    };
539                    prop.additions[i] = temp;
540                    pasteData.addRecord(data);
541                    pasteData.setProperty(prop);
542                }
543            }
544        }
545        sysBoard.clearData();
546        sysBoard.setData(pasteData).then(() => {
547            hilog.info(0x3900, 'Ace', 'SelectionMenu copy option, Succeeded in setting PasteData.');
548        }).catch((err) => {
549            hilog.info(0x3900, 'Ace', 'SelectionMenu copy option, Failed to set PasteData. Cause:' + err.message);
550        });
551    }
552
553    popDataFromPasteboard(richEditorSelection) {
554        let start = richEditorSelection.selection[0];
555        let end = richEditorSelection.selection[1];
556        if (start === end && this.controller) {
557            start = this.controller.getCaretOffset();
558            end = this.controller.getCaretOffset();
559        }
560        let moveOffset = 0;
561        let sysBoard = pasteboard.getSystemPasteboard();
562        sysBoard.getData((err, data) => {
563            if (err) {
564                return;
565            }
566            let count = data.getRecordCount();
567            for (let i = 0; i < count; i++) {
568                const element = data.getRecord(i);
569                let tex = {
570                    fontSize: 16,
571                    fontColor: Color.Black,
572                    fontWeight: FontWeight.Normal,
573                    fontFamily: 'HarmonyOS Sans',
574                    fontStyle: FontStyle.Normal,
575                    decoration: { type: TextDecorationType.None, color: '#FF000000' }
576                };
577                if (data.getProperty() && data.getProperty().additions[i]) {
578                    const tmp = data.getProperty().additions[i];
579                    if (tmp.color) {
580                        tex.fontColor = tmp.color;
581                    }
582                    if (tmp.size) {
583                        tex.fontSize = tmp.size;
584                    }
585                    if (tmp.style) {
586                        tex.fontStyle = tmp.style;
587                    }
588                    if (tmp.weight) {
589                        tex.fontWeight = tmp.weight;
590                    }
591                    if (tmp.fontFamily) {
592                        tex.fontFamily = tmp.fontFamily;
593                    }
594                    if (tmp.decorationType && tex.decoration) {
595                        tex.decoration.type = tmp.decorationType;
596                    }
597                    if (tmp.decorationColor && tex.decoration) {
598                        tex.decoration.color = tmp.decorationColor;
599                    }
600                    if (tex.decoration) {
601                        tex.decoration = { type: tex.decoration.type, color: tex.decoration.color };
602                    }
603                }
604                if (element && element.plainText && element.mimeType === pasteboard.MIMETYPE_TEXT_PLAIN &&
605                this.controller) {
606                    this.controller.addTextSpan(element.plainText, {
607                        style: tex,
608                        offset: start + moveOffset
609                    });
610                    moveOffset += element.plainText.length;
611                }
612            }
613            if (this.controller) {
614                this.controller.setCaretOffset(start + moveOffset);
615            }
616            if (start !== end && this.controller) {
617                this.controller.deleteSpans({ start: start + moveOffset, end: end + moveOffset });
618            }
619        });
620    }
621
622    measureButtonWidth() {
623        let numOfBtnPerRow = 5;
624        let width = this.fontScale > MAX_FONT_SCALE ? this.customMenuWidth : this.theme.defaultMenuWidth;
625        if (this.editorMenuOptions && this.editorMenuOptions.length <= numOfBtnPerRow) {
626            return (width - this.theme.expandedOptionPadding * 2) / this.editorMenuOptions.length;
627        }
628        return (width - this.theme.expandedOptionPadding * 2) / numOfBtnPerRow;
629    }
630
631    measureFlexPadding() {
632        return Math.floor((this.theme.expandedOptionPadding - px2vp(2.0)) * 10) / 10;
633    }
634
635    getFontScale() {
636        try {
637            let uiContext = this.getUIContext();
638            let systemFontScale = uiContext.getHostContext()?.config?.fontSizeScale ?? 1;
639            if (!this.isFollowingSystemFontScale) {
640                return 1;
641            }
642            return Math.min(systemFontScale, this.appMaxFontScale);
643        } catch (exception) {
644            let code = exception.code;
645            let message = exception.message;
646            hilog.error(0x3900, 'Ace', `Faild to init fontsizescale info,cause, code: ${code}, message: ${message}`);
647            return 1;
648        }
649    }
650
651    onMeasureSize(selfLayoutInfo, children, constraint) {
652        this.fontScale = this.getFontScale();
653        let sizeResult = { height: 0, width: 0 };
654        children.forEach((child) => {
655            let childMeasureResult = child.measure(constraint);
656            sizeResult.width = childMeasureResult.width;
657            sizeResult.height = childMeasureResult.height;
658        });
659        return sizeResult;
660    }
661
662    updateMenuItemVisibility() {
663        if (!this.controller) {
664            return;
665        }
666        let richEditorSelection = this.controller.getSelection();
667        let start = richEditorSelection.selection[0];
668        let end = richEditorSelection.selection[1];
669        if (start !== end) {
670            this.cutAndCopyEnable = true;
671        }
672        if (start === 0 && this.controller.getSpans({ start: end + 1, end: end + 1 }).length === 0) {
673            this.visibilityValue = Visibility.None;
674        }
675        else {
676            this.visibilityValue = Visibility.Visible;
677        }
678    }
679
680    IconPanel(parent = null) {
681        this.observeComponentCreation2((elmtId, isInitialRender) => {
682            Flex.create({ wrap: FlexWrap.Wrap });
683            Flex.onAreaChange((oldValue, newValue) => {
684                let newValueHeight = newValue.height;
685                let newValueWidth = newValue.width;
686                this.horizontalMenuHeight = newValueHeight;
687                this.horizontalMenuWidth = newValueWidth;
688            });
689            Flex.clip(true);
690            Flex.width(this.fontScale > MAX_FONT_SCALE ? this.customMenuWidth : this.theme.defaultMenuWidth);
691            Flex.padding({
692                top: this.measureFlexPadding(),
693                bottom: this.measureFlexPadding(),
694                left: this.measureFlexPadding() - 0.1,
695                right: this.measureFlexPadding() - 0.1
696            });
697            Flex.borderRadius(this.theme.containerBorderRadius);
698            Flex.margin({ bottom: this.theme.menuSpacing });
699            Flex.backgroundColor(this.theme.backGroundColor);
700            Flex.shadow(this.theme.iconPanelShadowStyle);
701            Flex.border({
702                width: this.theme.borderWidth, color: this.theme.borderColor,
703                radius: this.theme.containerBorderRadius
704            });
705            Flex.outline({
706                width: this.theme.outlineWidth, color: this.theme.outlineColor,
707                radius: this.theme.containerBorderRadius
708            });
709        }, Flex);
710        this.observeComponentCreation2((elmtId, isInitialRender) => {
711            If.create();
712            if (this.editorMenuOptions) {
713                this.ifElseBranchUpdateFunction(0, () => {
714                    this.observeComponentCreation2((elmtId, isInitialRender) => {
715                        ForEach.create();
716                        const forEachItemGenFunction = (_item, index) => {
717                            const item = _item;
718                            this.observeComponentCreation2((elmtId, isInitialRender) => {
719                                Button.createWithChild();
720                                Button.enabled(!(!item.action && !item.builder));
721                                Button.type(ButtonType.Normal);
722                                Button.backgroundColor(this.theme.backGroundColor);
723                                Button.onClick(() => {
724                                    if (item.builder) {
725                                        this.builder = item.builder;
726                                        this.showCustomerIndex = index;
727                                        this.showExpandedMenuOptions = false;
728                                        this.customerChange = !this.customerChange;
729                                    } else {
730                                        this.showCustomerIndex = WITHOUT_BUILDER;
731                                        if (!this.controller) {
732                                            this.showExpandedMenuOptions = true;
733                                        }
734                                    }
735                                    if (item.action) {
736                                        item.action();
737                                    }
738                                });
739                                Button.borderRadius(this.theme.iconBorderRadius);
740                                Button.width(this.measureButtonWidth());
741                                Button.height(this.theme.buttonSize);
742                            }, Button);
743                            this.observeComponentCreation2((elmtId, isInitialRender) => {
744                                If.create();
745                                if (item.symbolStyle !== undefined) {
746                                    this.ifElseBranchUpdateFunction(0, () => {
747                                        this.observeComponentCreation2((elmtId, isInitialRender) => {
748                                            SymbolGlyph.create();
749                                            SymbolGlyph.fontColor(this.theme.defaultSymbolTheme.fontColor);
750                                            SymbolGlyph.attributeModifier.bind(this)(item.symbolStyle);
751                                            SymbolGlyph.focusable(true);
752                                            SymbolGlyph.draggable(false);
753                                            SymbolGlyph.effectStrategy(SymbolEffectStrategy.NONE);
754                                            SymbolGlyph.symbolEffect(new SymbolEffect(), false);
755                                            SymbolGlyph.fontSize(this.theme.defaultSymbolTheme.fontSize);
756                                        }, SymbolGlyph);
757                                    });
758                                } else {
759                                    this.ifElseBranchUpdateFunction(1, () => {
760                                        this.observeComponentCreation2((elmtId, isInitialRender) => {
761                                            If.create();
762                                            if (Util.isSymbolResource(item.icon)) {
763                                                this.ifElseBranchUpdateFunction(0, () => {
764                                                    this.observeComponentCreation2((elmtId, isInitialRender) => {
765                                                        SymbolGlyph.create(item.icon);
766                                                        SymbolGlyph.fontColor(this.theme.defaultSymbolTheme.fontColor);
767                                                        SymbolGlyph.focusable(true);
768                                                        SymbolGlyph.draggable(false);
769                                                        SymbolGlyph.fontSize(this.theme.defaultSymbolTheme.fontSize);
770                                                    }, SymbolGlyph);
771                                                });
772                                            } else {
773                                                this.ifElseBranchUpdateFunction(1, () => {
774                                                    this.observeComponentCreation2((elmtId, isInitialRender) => {
775                                                        Image.create(item.icon);
776                                                        Image.width(this.theme.imageSize);
777                                                        Image.height(this.theme.imageSize);
778                                                        Image.fillColor(this.theme.imageFillColor);
779                                                        Image.focusable(true);
780                                                        Image.draggable(false);
781                                                    }, Image);
782                                                });
783                                            }
784                                        }, If);
785                                        If.pop();
786                                    });
787                                }
788                            }, If);
789                            If.pop();
790                            Button.pop();
791                        };
792                        this.forEachUpdateFunction(elmtId, this.editorMenuOptions, forEachItemGenFunction, undefined,
793                            true, false);
794                    }, ForEach);
795                    ForEach.pop();
796                });
797            } else {
798                this.ifElseBranchUpdateFunction(1, () => {
799                });
800            }
801        }, If);
802        If.pop();
803        Flex.pop();
804    }
805
806    SystemMenu(parent = null) {
807        this.observeComponentCreation2((elmtId, isInitialRender) => {
808            Column.create();
809            Column.width(this.fontScale > MAX_FONT_SCALE ? 'auto' : this.theme.defaultMenuWidth);
810            Column.shadow(this.theme.iconPanelShadowStyle);
811            Column.border({
812                width: this.theme.borderWidth, color: this.theme.borderColor,
813                radius: this.theme.containerBorderRadius
814            });
815            Column.constraintSize({
816                minWidth: this.theme.defaultMenuWidth
817            });
818        }, Column);
819        this.observeComponentCreation2((elmtId, isInitialRender) => {
820            If.create();
821            if (this.showCustomerIndex === -1 &&
822                (this.controller || (this.expandedMenuOptions && this.expandedMenuOptions.length > 0))) {
823                this.ifElseBranchUpdateFunction(0, () => {
824                    this.observeComponentCreation2((elmtId, isInitialRender) => {
825                        Menu.create();
826                        Menu.radius(this.theme.containerBorderRadius);
827                        Menu.clip(true);
828                        Menu.width(this.fontScale > MAX_FONT_SCALE ? 'auto' : this.theme.defaultMenuWidth);
829                        Menu.constraintSize({
830                            minWidth: this.theme.defaultMenuWidth
831                        });
832                        Menu.onVisibleAreaChange([0.0, 1.0], () => {
833                            this.updateMenuItemVisibility();
834                        });
835                        Menu.onAreaChange((oldValue, newValue) => {
836                            let newValueWidth = newValue.width;
837                            this.customMenuWidth =
838                                this.fontScale > MAX_FONT_SCALE && newValueWidth > this.theme.defaultMenuWidth ? newValueWidth :
839                                    this.theme.defaultMenuWidth;
840                            this.updateMenuItemVisibility();
841                        });
842                    }, Menu);
843                    this.observeComponentCreation2((elmtId, isInitialRender) => {
844                        If.create();
845                        if (this.controller) {
846                            this.ifElseBranchUpdateFunction(0, () => {
847                                this.observeComponentCreation2((elmtId, isInitialRender) => {
848                                    MenuItemGroup.create();
849                                }, MenuItemGroup);
850                                this.observeComponentCreation2((elmtId, isInitialRender) => {
851                                    MenuItem.create({
852                                        startIcon: this.theme.cutIcon,
853                                        symbolStartIcon: this.theme.defaultSymbolTheme.symbolCutIcon,
854                                        content: '剪切',
855                                        labelInfo: 'Ctrl+X'
856                                    });
857                                    MenuItem.enabled(this.cutAndCopyEnable);
858                                    MenuItem.height(this.fontScale > MAX_FONT_STANDARD ? 'auto' :
859                                    this.theme.buttonSize);
860                                    MenuItem.borderRadius(this.theme.iconBorderRadius);
861                                    MenuItem.onClick(() => {
862                                        if (!this.controller) {
863                                            return;
864                                        }
865                                        let richEditorSelection = this.controller.getSelection();
866                                        if (this.onCut) {
867                                            this.onCut({ content: richEditorSelection });
868                                        } else {
869                                            this.pushDataToPasteboard(richEditorSelection);
870                                            this.controller.deleteSpans({
871                                                start: richEditorSelection.selection[0],
872                                                end: richEditorSelection.selection[1]
873                                            });
874                                        }
875                                    });
876                                }, MenuItem);
877                                MenuItem.pop();
878                                this.observeComponentCreation2((elmtId, isInitialRender) => {
879                                    MenuItem.create({
880                                        startIcon: this.theme.copyIcon,
881                                        symbolStartIcon: this.theme.defaultSymbolTheme.symbolCopyIcon,
882                                        content: '复制',
883                                        labelInfo: 'Ctrl+C'
884                                    });
885                                    MenuItem.enabled(this.cutAndCopyEnable);
886                                    MenuItem.height(this.fontScale > MAX_FONT_STANDARD ? 'auto' :
887                                    this.theme.buttonSize);
888                                    MenuItem.borderRadius(this.theme.iconBorderRadius);
889                                    MenuItem.margin({ top: this.theme.menuItemPadding });
890                                    MenuItem.onClick(() => {
891                                        if (!this.controller) {
892                                            return;
893                                        }
894                                        let richEditorSelection = this.controller.getSelection();
895                                        if (this.onCopy) {
896                                            this.onCopy({ content: richEditorSelection });
897                                        } else {
898                                            this.pushDataToPasteboard(richEditorSelection);
899                                            this.controller.closeSelectionMenu();
900                                        }
901                                    });
902                                }, MenuItem);
903                                MenuItem.pop();
904                                this.observeComponentCreation2((elmtId, isInitialRender) => {
905                                    MenuItem.create({
906                                        startIcon: this.theme.pasteIcon,
907                                        symbolStartIcon: this.theme.defaultSymbolTheme.symbolPasteIcon,
908                                        content: '粘贴',
909                                        labelInfo: 'Ctrl+V'
910                                    });
911                                    MenuItem.enabled(this.pasteEnable);
912                                    MenuItem.height(this.fontScale > MAX_FONT_STANDARD ? 'auto' :
913                                    this.theme.buttonSize);
914                                    MenuItem.borderRadius(this.theme.iconBorderRadius);
915                                    MenuItem.margin({ top: this.theme.menuItemPadding });
916                                    MenuItem.onClick(() => {
917                                        if (!this.controller) {
918                                            return;
919                                        }
920                                        let richEditorSelection = this.controller.getSelection();
921                                        if (this.onPaste) {
922                                            this.onPaste({ content: richEditorSelection });
923                                        } else {
924                                            this.popDataFromPasteboard(richEditorSelection);
925                                            this.controller.closeSelectionMenu();
926                                        }
927                                    });
928                                }, MenuItem);
929                                MenuItem.pop();
930                                this.observeComponentCreation2((elmtId, isInitialRender) => {
931                                    MenuItem.create({
932                                        startIcon: this.theme.selectAllIcon,
933                                        symbolStartIcon: this.theme.defaultSymbolTheme.symbolSelectAllIcon,
934                                        content: '全选',
935                                        labelInfo: 'Ctrl+A'
936                                    });
937                                    MenuItem.visibility(this.visibilityValue);
938                                    MenuItem.height(this.fontScale > MAX_FONT_STANDARD ? 'auto' :
939                                    this.theme.buttonSize);
940                                    MenuItem.borderRadius(this.theme.iconBorderRadius);
941                                    MenuItem.margin({ top: this.theme.menuItemPadding });
942                                    MenuItem.onClick(() => {
943                                        if (!this.controller) {
944                                            return;
945                                        }
946                                        if (this.onSelectAll) {
947                                            let richEditorSelection = this.controller.getSelection();
948                                            this.onSelectAll({ content: richEditorSelection });
949                                        } else {
950                                            this.controller.setSelection(-1, -1);
951                                            this.visibilityValue = Visibility.None;
952                                        }
953                                        this.controller.closeSelectionMenu();
954                                    });
955                                }, MenuItem);
956                                MenuItem.pop();
957                                MenuItemGroup.pop();
958                            });
959                        } else {
960                            this.ifElseBranchUpdateFunction(1, () => {
961                            });
962                        }
963                    }, If);
964                    If.pop();
965                    this.observeComponentCreation2((elmtId, isInitialRender) => {
966                        If.create();
967                        if (this.controller && !this.showExpandedMenuOptions &&
968                        this.expandedMenuOptions && this.expandedMenuOptions.length > 0) {
969                            this.ifElseBranchUpdateFunction(0, () => {
970                                this.observeComponentCreation2((elmtId, isInitialRender) => {
971                                    MenuItem.create({
972                                        content: '更多',
973                                        endIcon: this.theme.arrowDownIcon,
974                                        symbolEndIcon: this.theme.defaultSymbolTheme.symbolArrowDownIcon
975                                    });
976                                    MenuItem.height(this.fontScale > MAX_FONT_STANDARD ? 'auto' :
977                                    this.theme.buttonSize);
978                                    MenuItem.borderRadius(this.theme.iconBorderRadius);
979                                    MenuItem.margin({ top: this.theme.menuItemPadding });
980                                    MenuItem.onClick(() => {
981                                        this.showExpandedMenuOptions = true;
982                                    });
983                                }, MenuItem);
984                                MenuItem.pop();
985                            });
986                        } else if (this.showExpandedMenuOptions && this.expandedMenuOptions &&
987                            this.expandedMenuOptions.length > 0) {
988                            this.ifElseBranchUpdateFunction(1, () => {
989                                this.observeComponentCreation2((elmtId, isInitialRender) => {
990                                    ForEach.create();
991                                    const forEachItemGenFunction = (_item, index) => {
992                                        const expandedMenuOptionItem = _item;
993                                        this.observeComponentCreation2((elmtId, isInitialRender) => {
994                                            MenuItem.create({
995                                                startIcon: expandedMenuOptionItem.startIcon,
996                                                symbolStartIcon: expandedMenuOptionItem.symbolStartIcon,
997                                                content: expandedMenuOptionItem.content,
998                                                endIcon: expandedMenuOptionItem.endIcon,
999                                                symbolEndIcon: expandedMenuOptionItem.symbolEndIcon,
1000                                                labelInfo: expandedMenuOptionItem.labelInfo,
1001                                                builder: expandedMenuOptionItem.builder
1002                                            });
1003                                            MenuItem.height(this.fontScale > MAX_FONT_STANDARD ? 'auto' :
1004                                            this.theme.buttonSize);
1005                                            MenuItem.borderRadius(this.theme.iconBorderRadius);
1006                                            MenuItem.margin({ top: this.theme.menuItemPadding });
1007                                            MenuItem.onClick(() => {
1008                                                if (expandedMenuOptionItem.action) {
1009                                                    expandedMenuOptionItem.action();
1010                                                }
1011                                            });
1012                                        }, MenuItem);
1013                                        MenuItem.pop();
1014                                    };
1015                                    this.forEachUpdateFunction(elmtId, this.expandedMenuOptions, forEachItemGenFunction,
1016                                        undefined, true, false);
1017                                }, ForEach);
1018                                ForEach.pop();
1019                            });
1020                        } else {
1021                            this.ifElseBranchUpdateFunction(2, () => {
1022                            });
1023                        }
1024                    }, If);
1025                    If.pop();
1026                    Menu.pop();
1027                });
1028            } else if (this.showCustomerIndex > -1 && this.builder) {
1029                this.ifElseBranchUpdateFunction(1, () => {
1030                    this.observeComponentCreation2((elmtId, isInitialRender) => {
1031                        Column.create();
1032                        Column.width(this.horizontalMenuWidth);
1033                    }, Column);
1034                    this.observeComponentCreation2((elmtId, isInitialRender) => {
1035                        If.create();
1036                        if (this.customerChange) {
1037                            this.ifElseBranchUpdateFunction(0, () => {
1038                                this.builder.bind(this)();
1039                            });
1040                        } else {
1041                            this.ifElseBranchUpdateFunction(1, () => {
1042                                this.builder.bind(this)();
1043                            });
1044                        }
1045                    }, If);
1046                    If.pop();
1047                    Column.pop();
1048                });
1049            } else {
1050                this.ifElseBranchUpdateFunction(2, () => {
1051                });
1052            }
1053        }, If);
1054        If.pop();
1055        Column.pop();
1056    }
1057
1058    rerender() {
1059        this.updateDirtyElements();
1060    }
1061}
1062
1063export function SelectionMenu(options, parent = null) {
1064    const __options__ = options;
1065    {
1066        (parent ? parent : this).observeComponentCreation2((elmtId, isInitialRender, options = __options__) => {
1067            if (isInitialRender) {
1068                let componentCall = new SelectionMenuComponent(parent ? parent : this, {
1069                    editorMenuOptions: options.editorMenuOptions,
1070                    expandedMenuOptions: options.expandedMenuOptions,
1071                    controller: options.controller,
1072                    onPaste: options.onPaste,
1073                    onCopy: options.onCopy,
1074                    onCut: options.onCut,
1075                    onSelectAll: options.onSelectAll
1076                }, undefined, elmtId, () => {
1077                }, { page: 'SelectionMenu/src/main/ets/components/MainPage.ets', line: 633, col: 3 });
1078                ViewPU.create(componentCall);
1079                let paramsLambda = () => {
1080                    return {
1081                        editorMenuOptions: options.editorMenuOptions,
1082                        expandedMenuOptions: options.expandedMenuOptions,
1083                        controller: options.controller,
1084                        onPaste: options.onPaste,
1085                        onCopy: options.onCopy,
1086                        onCut: options.onCut,
1087                        onSelectAll: options.onSelectAll
1088                    };
1089                };
1090                componentCall.paramsGenerator_ = paramsLambda;
1091            } else {
1092                (parent ? parent : this).updateStateVarsOfChildByElmtId(elmtId, {});
1093            }
1094        }, { name: 'SelectionMenuComponent' });
1095    }
1096}
1097
1098class Util {
1099    static isSymbolResource(resourceStr) {
1100        if (!Util.isResourceType(resourceStr)) {
1101            return false;
1102        }
1103        let resource = resourceStr;
1104        return resource.type === Util.RESOURCE_TYPE_SYMBOL;
1105    }
1106
1107    static isResourceType(resource) {
1108        if (!resource) {
1109            return false;
1110        }
1111        if (typeof resource === 'string' || typeof resource === 'undefined') {
1112            return false;
1113        }
1114        return true;
1115    }
1116}
1117
1118Util.RESOURCE_TYPE_SYMBOL = 40000;
1119
1120export default { SelectionMenu };