• 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 = 2.0;
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    IconPanel(parent = null) {
663        this.observeComponentCreation2((elmtId, isInitialRender) => {
664            Flex.create({ wrap: FlexWrap.Wrap });
665            Flex.onAreaChange((oldValue, newValue) => {
666                let newValueHeight = newValue.height;
667                let newValueWidth = newValue.width;
668                this.horizontalMenuHeight = newValueHeight;
669                this.horizontalMenuWidth = newValueWidth;
670            });
671            Flex.clip(true);
672            Flex.width(this.fontScale > MAX_FONT_SCALE ? this.customMenuWidth : this.theme.defaultMenuWidth);
673            Flex.padding({
674                top: this.measureFlexPadding(),
675                bottom: this.measureFlexPadding(),
676                left: this.measureFlexPadding() - 0.1,
677                right: this.measureFlexPadding() - 0.1
678            });
679            Flex.borderRadius(this.theme.containerBorderRadius);
680            Flex.margin({ bottom: this.theme.menuSpacing });
681            Flex.backgroundColor(this.theme.backGroundColor);
682            Flex.shadow(this.theme.iconPanelShadowStyle);
683            Flex.border({
684                width: this.theme.borderWidth, color: this.theme.borderColor,
685                radius: this.theme.containerBorderRadius
686            });
687            Flex.outline({
688                width: this.theme.outlineWidth, color: this.theme.outlineColor,
689                radius: this.theme.containerBorderRadius
690            });
691        }, Flex);
692        this.observeComponentCreation2((elmtId, isInitialRender) => {
693            If.create();
694            if (this.editorMenuOptions) {
695                this.ifElseBranchUpdateFunction(0, () => {
696                    this.observeComponentCreation2((elmtId, isInitialRender) => {
697                        ForEach.create();
698                        const forEachItemGenFunction = (_item, index) => {
699                            const item = _item;
700                            this.observeComponentCreation2((elmtId, isInitialRender) => {
701                                Button.createWithChild();
702                                Button.enabled(!(!item.action && !item.builder));
703                                Button.type(ButtonType.Normal);
704                                Button.backgroundColor(this.theme.backGroundColor);
705                                Button.onClick(() => {
706                                    if (item.builder) {
707                                        this.builder = item.builder;
708                                        this.showCustomerIndex = index;
709                                        this.showExpandedMenuOptions = false;
710                                        this.customerChange = !this.customerChange;
711                                    } else {
712                                        this.showCustomerIndex = WITHOUT_BUILDER;
713                                        if (!this.controller) {
714                                            this.showExpandedMenuOptions = true;
715                                        }
716                                    }
717                                    if (item.action) {
718                                        item.action();
719                                    }
720                                });
721                                Button.borderRadius(this.theme.iconBorderRadius);
722                                Button.width(this.measureButtonWidth());
723                                Button.height(this.theme.buttonSize);
724                            }, Button);
725                            this.observeComponentCreation2((elmtId, isInitialRender) => {
726                                If.create();
727                                if (item.symbolStyle !== undefined) {
728                                    this.ifElseBranchUpdateFunction(0, () => {
729                                        this.observeComponentCreation2((elmtId, isInitialRender) => {
730                                            SymbolGlyph.create();
731                                            SymbolGlyph.fontColor(this.theme.defaultSymbolTheme.fontColor);
732                                            SymbolGlyph.attributeModifier.bind(this)(item.symbolStyle);
733                                            SymbolGlyph.focusable(true);
734                                            SymbolGlyph.draggable(false);
735                                            SymbolGlyph.effectStrategy(SymbolEffectStrategy.NONE);
736                                            SymbolGlyph.symbolEffect(new SymbolEffect(), false);
737                                            SymbolGlyph.fontSize(this.theme.defaultSymbolTheme.fontSize);
738                                        }, SymbolGlyph);
739                                    });
740                                } else {
741                                    this.ifElseBranchUpdateFunction(1, () => {
742                                        this.observeComponentCreation2((elmtId, isInitialRender) => {
743                                            If.create();
744                                            if (Util.isSymbolResource(item.icon)) {
745                                                this.ifElseBranchUpdateFunction(0, () => {
746                                                    this.observeComponentCreation2((elmtId, isInitialRender) => {
747                                                        SymbolGlyph.create(item.icon);
748                                                        SymbolGlyph.fontColor(this.theme.defaultSymbolTheme.fontColor);
749                                                        SymbolGlyph.focusable(true);
750                                                        SymbolGlyph.draggable(false);
751                                                        SymbolGlyph.fontSize(this.theme.defaultSymbolTheme.fontSize);
752                                                    }, SymbolGlyph);
753                                                });
754                                            } else {
755                                                this.ifElseBranchUpdateFunction(1, () => {
756                                                    this.observeComponentCreation2((elmtId, isInitialRender) => {
757                                                        Image.create(item.icon);
758                                                        Image.width(this.theme.imageSize);
759                                                        Image.height(this.theme.imageSize);
760                                                        Image.fillColor(this.theme.imageFillColor);
761                                                        Image.focusable(true);
762                                                        Image.draggable(false);
763                                                    }, Image);
764                                                });
765                                            }
766                                        }, If);
767                                        If.pop();
768                                    });
769                                }
770                            }, If);
771                            If.pop();
772                            Button.pop();
773                        };
774                        this.forEachUpdateFunction(elmtId, this.editorMenuOptions, forEachItemGenFunction, undefined,
775                            true, false);
776                    }, ForEach);
777                    ForEach.pop();
778                });
779            } else {
780                this.ifElseBranchUpdateFunction(1, () => {
781                });
782            }
783        }, If);
784        If.pop();
785        Flex.pop();
786    }
787
788    SystemMenu(parent = null) {
789        this.observeComponentCreation2((elmtId, isInitialRender) => {
790            Column.create();
791            Column.width(this.fontScale > MAX_FONT_SCALE ? 'auto' : this.theme.defaultMenuWidth);
792            Column.shadow(this.theme.iconPanelShadowStyle);
793            Column.border({
794                width: this.theme.borderWidth, color: this.theme.borderColor,
795                radius: this.theme.containerBorderRadius
796            });
797            Column.constraintSize({
798                minWidth: this.theme.defaultMenuWidth
799            });
800        }, Column);
801        this.observeComponentCreation2((elmtId, isInitialRender) => {
802            If.create();
803            if (this.showCustomerIndex === -1 &&
804                (this.controller || (this.expandedMenuOptions && this.expandedMenuOptions.length > 0))) {
805                this.ifElseBranchUpdateFunction(0, () => {
806                    this.observeComponentCreation2((elmtId, isInitialRender) => {
807                        Menu.create();
808                        Menu.radius(this.theme.containerBorderRadius);
809                        Menu.clip(true);
810                        Menu.width(this.fontScale > MAX_FONT_SCALE ? 'auto' : this.theme.defaultMenuWidth);
811                        Menu.constraintSize({
812                            minWidth: this.theme.defaultMenuWidth
813                        });
814                        Menu.onAreaChange((oldValue, newValue) => {
815                            let newValueWidth = newValue.width;
816                            this.customMenuWidth =
817                                this.fontScale > MAX_FONT_SCALE && newValueWidth > this.theme.defaultMenuWidth ? newValueWidth :
818                                    this.theme.defaultMenuWidth;
819                            if (!this.controller) {
820                                return;
821                            }
822                            let richEditorSelection = this.controller.getSelection();
823                            let start = richEditorSelection.selection[0];
824                            let end = richEditorSelection.selection[1];
825                            if (start !== end) {
826                                this.cutAndCopyEnable = true;
827                            }
828                            if (start === 0 &&
829                                this.controller.getSpans({ start: end + 1, end: end + 1 }).length === 0) {
830                                this.visibilityValue = Visibility.None;
831                            } else {
832                                this.visibilityValue = Visibility.Visible;
833                            }
834                        });
835                    }, Menu);
836                    this.observeComponentCreation2((elmtId, isInitialRender) => {
837                        If.create();
838                        if (this.controller) {
839                            this.ifElseBranchUpdateFunction(0, () => {
840                                this.observeComponentCreation2((elmtId, isInitialRender) => {
841                                    MenuItemGroup.create();
842                                }, MenuItemGroup);
843                                this.observeComponentCreation2((elmtId, isInitialRender) => {
844                                    MenuItem.create({
845                                        startIcon: this.theme.cutIcon,
846                                        symbolStartIcon: this.theme.defaultSymbolTheme.symbolCutIcon,
847                                        content: '剪切',
848                                        labelInfo: 'Ctrl+X'
849                                    });
850                                    MenuItem.enabled(this.cutAndCopyEnable);
851                                    MenuItem.height(this.fontScale > MAX_FONT_STANDARD ? 'auto' :
852                                    this.theme.buttonSize);
853                                    MenuItem.borderRadius(this.theme.iconBorderRadius);
854                                    MenuItem.onClick(() => {
855                                        if (!this.controller) {
856                                            return;
857                                        }
858                                        let richEditorSelection = this.controller.getSelection();
859                                        if (this.onCut) {
860                                            this.onCut({ content: richEditorSelection });
861                                        } else {
862                                            this.pushDataToPasteboard(richEditorSelection);
863                                            this.controller.deleteSpans({
864                                                start: richEditorSelection.selection[0],
865                                                end: richEditorSelection.selection[1]
866                                            });
867                                        }
868                                    });
869                                }, MenuItem);
870                                MenuItem.pop();
871                                this.observeComponentCreation2((elmtId, isInitialRender) => {
872                                    MenuItem.create({
873                                        startIcon: this.theme.copyIcon,
874                                        symbolStartIcon: this.theme.defaultSymbolTheme.symbolCopyIcon,
875                                        content: '复制',
876                                        labelInfo: 'Ctrl+C'
877                                    });
878                                    MenuItem.enabled(this.cutAndCopyEnable);
879                                    MenuItem.height(this.fontScale > MAX_FONT_STANDARD ? 'auto' :
880                                    this.theme.buttonSize);
881                                    MenuItem.borderRadius(this.theme.iconBorderRadius);
882                                    MenuItem.margin({ top: this.theme.menuItemPadding });
883                                    MenuItem.onClick(() => {
884                                        if (!this.controller) {
885                                            return;
886                                        }
887                                        let richEditorSelection = this.controller.getSelection();
888                                        if (this.onCopy) {
889                                            this.onCopy({ content: richEditorSelection });
890                                        } else {
891                                            this.pushDataToPasteboard(richEditorSelection);
892                                            this.controller.closeSelectionMenu();
893                                        }
894                                    });
895                                }, MenuItem);
896                                MenuItem.pop();
897                                this.observeComponentCreation2((elmtId, isInitialRender) => {
898                                    MenuItem.create({
899                                        startIcon: this.theme.pasteIcon,
900                                        symbolStartIcon: this.theme.defaultSymbolTheme.symbolPasteIcon,
901                                        content: '粘贴',
902                                        labelInfo: 'Ctrl+V'
903                                    });
904                                    MenuItem.enabled(this.pasteEnable);
905                                    MenuItem.height(this.fontScale > MAX_FONT_STANDARD ? 'auto' :
906                                    this.theme.buttonSize);
907                                    MenuItem.borderRadius(this.theme.iconBorderRadius);
908                                    MenuItem.margin({ top: this.theme.menuItemPadding });
909                                    MenuItem.onClick(() => {
910                                        if (!this.controller) {
911                                            return;
912                                        }
913                                        let richEditorSelection = this.controller.getSelection();
914                                        if (this.onPaste) {
915                                            this.onPaste({ content: richEditorSelection });
916                                        } else {
917                                            this.popDataFromPasteboard(richEditorSelection);
918                                            this.controller.closeSelectionMenu();
919                                        }
920                                    });
921                                }, MenuItem);
922                                MenuItem.pop();
923                                this.observeComponentCreation2((elmtId, isInitialRender) => {
924                                    MenuItem.create({
925                                        startIcon: this.theme.selectAllIcon,
926                                        symbolStartIcon: this.theme.defaultSymbolTheme.symbolSelectAllIcon,
927                                        content: '全选',
928                                        labelInfo: 'Ctrl+A'
929                                    });
930                                    MenuItem.visibility(this.visibilityValue);
931                                    MenuItem.height(this.fontScale > MAX_FONT_STANDARD ? 'auto' :
932                                    this.theme.buttonSize);
933                                    MenuItem.borderRadius(this.theme.iconBorderRadius);
934                                    MenuItem.margin({ top: this.theme.menuItemPadding });
935                                    MenuItem.onClick(() => {
936                                        if (!this.controller) {
937                                            return;
938                                        }
939                                        if (this.onSelectAll) {
940                                            let richEditorSelection = this.controller.getSelection();
941                                            this.onSelectAll({ content: richEditorSelection });
942                                        } else {
943                                            this.controller.setSelection(-1, -1);
944                                            this.visibilityValue = Visibility.None;
945                                        }
946                                        this.controller.closeSelectionMenu();
947                                    });
948                                }, MenuItem);
949                                MenuItem.pop();
950                                MenuItemGroup.pop();
951                            });
952                        } else {
953                            this.ifElseBranchUpdateFunction(1, () => {
954                            });
955                        }
956                    }, If);
957                    If.pop();
958                    this.observeComponentCreation2((elmtId, isInitialRender) => {
959                        If.create();
960                        if (this.controller && !this.showExpandedMenuOptions &&
961                        this.expandedMenuOptions && this.expandedMenuOptions.length > 0) {
962                            this.ifElseBranchUpdateFunction(0, () => {
963                                this.observeComponentCreation2((elmtId, isInitialRender) => {
964                                    MenuItem.create({
965                                        content: '更多',
966                                        endIcon: this.theme.arrowDownIcon,
967                                        symbolEndIcon: this.theme.defaultSymbolTheme.symbolArrowDownIcon
968                                    });
969                                    MenuItem.height(this.fontScale > MAX_FONT_STANDARD ? 'auto' :
970                                    this.theme.buttonSize);
971                                    MenuItem.borderRadius(this.theme.iconBorderRadius);
972                                    MenuItem.margin({ top: this.theme.menuItemPadding });
973                                    MenuItem.onClick(() => {
974                                        this.showExpandedMenuOptions = true;
975                                    });
976                                }, MenuItem);
977                                MenuItem.pop();
978                            });
979                        } else if (this.showExpandedMenuOptions && this.expandedMenuOptions &&
980                            this.expandedMenuOptions.length > 0) {
981                            this.ifElseBranchUpdateFunction(1, () => {
982                                this.observeComponentCreation2((elmtId, isInitialRender) => {
983                                    ForEach.create();
984                                    const forEachItemGenFunction = (_item, index) => {
985                                        const expandedMenuOptionItem = _item;
986                                        this.observeComponentCreation2((elmtId, isInitialRender) => {
987                                            MenuItem.create({
988                                                startIcon: expandedMenuOptionItem.startIcon,
989                                                symbolStartIcon: expandedMenuOptionItem.symbolStartIcon,
990                                                content: expandedMenuOptionItem.content,
991                                                endIcon: expandedMenuOptionItem.endIcon,
992                                                symbolEndIcon: expandedMenuOptionItem.symbolEndIcon,
993                                                labelInfo: expandedMenuOptionItem.labelInfo,
994                                                builder: expandedMenuOptionItem.builder
995                                            });
996                                            MenuItem.height(this.fontScale > MAX_FONT_STANDARD ? 'auto' :
997                                            this.theme.buttonSize);
998                                            MenuItem.borderRadius(this.theme.iconBorderRadius);
999                                            MenuItem.margin({ top: this.theme.menuItemPadding });
1000                                            MenuItem.onClick(() => {
1001                                                if (expandedMenuOptionItem.action) {
1002                                                    expandedMenuOptionItem.action();
1003                                                }
1004                                            });
1005                                        }, MenuItem);
1006                                        MenuItem.pop();
1007                                    };
1008                                    this.forEachUpdateFunction(elmtId, this.expandedMenuOptions, forEachItemGenFunction,
1009                                        undefined, true, false);
1010                                }, ForEach);
1011                                ForEach.pop();
1012                            });
1013                        } else {
1014                            this.ifElseBranchUpdateFunction(2, () => {
1015                            });
1016                        }
1017                    }, If);
1018                    If.pop();
1019                    Menu.pop();
1020                });
1021            } else if (this.showCustomerIndex > -1 && this.builder) {
1022                this.ifElseBranchUpdateFunction(1, () => {
1023                    this.observeComponentCreation2((elmtId, isInitialRender) => {
1024                        Column.create();
1025                        Column.width(this.horizontalMenuWidth);
1026                    }, Column);
1027                    this.observeComponentCreation2((elmtId, isInitialRender) => {
1028                        If.create();
1029                        if (this.customerChange) {
1030                            this.ifElseBranchUpdateFunction(0, () => {
1031                                this.builder.bind(this)();
1032                            });
1033                        } else {
1034                            this.ifElseBranchUpdateFunction(1, () => {
1035                                this.builder.bind(this)();
1036                            });
1037                        }
1038                    }, If);
1039                    If.pop();
1040                    Column.pop();
1041                });
1042            } else {
1043                this.ifElseBranchUpdateFunction(2, () => {
1044                });
1045            }
1046        }, If);
1047        If.pop();
1048        Column.pop();
1049    }
1050
1051    rerender() {
1052        this.updateDirtyElements();
1053    }
1054}
1055
1056export function SelectionMenu(options, parent = null) {
1057    const __options__ = options;
1058    {
1059        (parent ? parent : this).observeComponentCreation2((elmtId, isInitialRender, options = __options__) => {
1060            if (isInitialRender) {
1061                let componentCall = new SelectionMenuComponent(parent ? parent : this, {
1062                    editorMenuOptions: options.editorMenuOptions,
1063                    expandedMenuOptions: options.expandedMenuOptions,
1064                    controller: options.controller,
1065                    onPaste: options.onPaste,
1066                    onCopy: options.onCopy,
1067                    onCut: options.onCut,
1068                    onSelectAll: options.onSelectAll
1069                }, undefined, elmtId, () => {
1070                }, { page: 'SelectionMenu/src/main/ets/components/MainPage.ets', line: 633, col: 3 });
1071                ViewPU.create(componentCall);
1072                let paramsLambda = () => {
1073                    return {
1074                        editorMenuOptions: options.editorMenuOptions,
1075                        expandedMenuOptions: options.expandedMenuOptions,
1076                        controller: options.controller,
1077                        onPaste: options.onPaste,
1078                        onCopy: options.onCopy,
1079                        onCut: options.onCut,
1080                        onSelectAll: options.onSelectAll
1081                    };
1082                };
1083                componentCall.paramsGenerator_ = paramsLambda;
1084            } else {
1085                (parent ? parent : this).updateStateVarsOfChildByElmtId(elmtId, {});
1086            }
1087        }, { name: 'SelectionMenuComponent' });
1088    }
1089}
1090
1091class Util {
1092    static isSymbolResource(resourceStr) {
1093        if (!Util.isResourceType(resourceStr)) {
1094            return false;
1095        }
1096        let resource = resourceStr;
1097        return resource.type === Util.RESOURCE_TYPE_SYMBOL;
1098    }
1099
1100    static isResourceType(resource) {
1101        if (!resource) {
1102            return false;
1103        }
1104        if (typeof resource === 'string' || typeof resource === 'undefined') {
1105            return false;
1106        }
1107        return true;
1108    }
1109}
1110
1111Util.RESOURCE_TYPE_SYMBOL = 40000;
1112
1113export default { SelectionMenu };