1/* 2 * Copyright (c) 2021-2022 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 */ 15 16import Log from '../../../../../../../../common/src/main/ets/default/Log'; 17import SimpleToggleLoadComponent from './SimpleToggleLoadComponent'; 18import StyleConfiguration, { SimpleToggleLayoutEditGridStyle } from '../common/StyleConfiguration'; 19 20const TAG = 'Control-SimpleToggleLayoutEditGrid'; 21 22@Component 23export default struct SimpleToggleLayoutEditGrid { 24 @Link mToggles: string[]; 25 private mMaxCount: number = 0; 26 private mMinCount: number = 0; 27 @Prop mColumnCount: number; 28 @Prop mGlobalDragToggleName: string; 29 private gridTag: string = ''; 30 private logTag: string = ''; 31 private onItemDragStart: (toggleName: string) => void = () => {}; 32 private onItemDrop: (status: string) => void = () => {}; 33 @State style: SimpleToggleLayoutEditGridStyle = StyleConfiguration.getSimpleToggleLayoutEditGridStyle(); 34 private mCurrentDragToggleName: string = ''; 35 36 @Builder DragComponent() { 37 Column() { 38 SimpleToggleLoadComponent({ 39 keyId: this.mCurrentDragToggleName, 40 mEditMode: true, 41 mDragMode: true, 42 }) 43 } 44 .width(this.style.dragBgSize) 45 .height(this.style.dragBgSize) 46 } 47 48 aboutToAppear() { 49 this.logTag = TAG + '-' + this.gridTag 50 Log.showInfo(this.logTag, this.gridTag + 'aboutToAppear'); 51 } 52 53 aboutToDisappear() { 54 Log.showInfo(this.logTag, 'aboutToDisappear '); 55 } 56 57 build() { 58 Grid() { 59 ForEach(this.mToggles, (componentName: string) => { 60 GridItem() { 61 Column() { 62 SimpleToggleLoadComponent({ 63 keyId: componentName, 64 mEditMode: true 65 }) 66 }.width('100%') 67 .height(108) 68 } 69 }, (componentName: string) => componentName) 70 if (this.mToggles.length == 0) { 71 GridItem() { 72 } 73 } 74 } 75 .supportAnimation(true) 76 .height(this.calcGridHeight(Math.ceil(this.mToggles.length / this.mColumnCount), this.style.rowHeight, this.style.rowGap)) 77 .width('100%') 78 .columnsTemplate(this.calcColumnsTemplate(this.mColumnCount)) 79 .editMode(true) 80 .maxCount(this.calcMaxRowCount(this.mMaxCount, this.mColumnCount)) 81 .minCount(this.calcMinRowCount(this.mMinCount, this.mColumnCount)) 82 .cellLength(this.style.rowHeight) 83 .rowsGap(this.style.rowGap + 'px') 84 .columnsGap(this.style.columnGap) 85 .layoutDirection(1) 86 .direction(0) 87 .onItemDragEnter(this.onItemDragEnter.bind(this)) 88 .onItemDragMove(this.onItemDragMove.bind(this)) 89 .onItemDragLeave(this.onItemDragLeave.bind(this)) 90 .onItemDragStart((event, itemIndex) => { 91 this.onGridItemDragStart(event, itemIndex) 92 return this.DragComponent 93 }) 94 .onItemDrop(this.onGridItemDrop.bind(this)) 95 } 96 97 calcGridHeight(rowCount: number, rowHeight: number, rowGap: number) { 98 Log.showDebug(this.logTag, `calcGridHeight, rowCount: ${rowCount} rowHeight: ${rowHeight} rowGap: ${rowGap}`); 99 let height = rowCount * rowHeight + (rowCount - 1) * rowGap; 100 if (height <= 0) { 101 height = 108; 102 } 103 Log.showDebug(this.logTag, `calcGridHeight, height: ${height}`); 104 return height + 'px'; 105 } 106 107 calcColumnsTemplate(columnCount: number): string{ 108 Log.showDebug(this.logTag, `calcColumnsTemplate, columnCount: ${columnCount}`); 109 let columnsTemplate = '1fr'; 110 for (let i = 1;i < columnCount; i++) { 111 columnsTemplate += ' 1fr'; 112 } 113 Log.showDebug(this.logTag, `calcColumnsTemplate, columnsTemplate: ${columnsTemplate}`); 114 return columnsTemplate; 115 } 116 117 calcMaxRowCount(maxCount: number, columnCount: number): number{ 118 Log.showDebug(this.logTag, `calcMaxRowCount, maxCount: ${maxCount} columnCount: ${columnCount}`); 119 let maxRowCount = Math.ceil(maxCount / columnCount); 120 if (maxRowCount < 1) { 121 maxRowCount = 1; 122 }; 123 Log.showDebug(this.logTag, `calcMaxRowCount, maxRowCount: ${maxRowCount}`); 124 return maxRowCount; 125 } 126 127 calcMinRowCount(minCount: number, columnCount: number): number{ 128 Log.showDebug(this.logTag, `calcMinRowCount, minCount: ${minCount} columnCount: ${columnCount}`); 129 let minRowCount = Math.ceil(minCount / columnCount); 130 if (minRowCount < 1) { 131 minRowCount = 1; 132 } 133 Log.showDebug(this.logTag, `calcMinRowCount, minRowCount: ${minRowCount}`); 134 return minRowCount; 135 } 136 137 onItemDragEnter(event: ItemDragInfo) { 138 Log.showDebug(this.logTag, `onItemDragEnter, event: ${JSON.stringify(event)}`); 139 } 140 141 onItemDragMove(event: ItemDragInfo, itemIndex: number, insertIndex: number) { 142 Log.showDebug(this.logTag, `onItemDragMove, itemIndex: ${itemIndex} insertIndex: ${insertIndex} event: ${JSON.stringify(event)}`); 143 } 144 145 onItemDragLeave(event: ItemDragInfo, itemIndex: number) { 146 Log.showDebug(this.logTag, `onItemDragLeave, itemIndex: ${itemIndex} event: ${JSON.stringify(event)}`); 147 } 148 149 onGridItemDragStart(event: ItemDragInfo, itemIndex: number) { 150 Log.showDebug(this.logTag, `onGridItemDragStart, itemIndex: ${itemIndex} event: ${JSON.stringify(event)}`); 151 this.mCurrentDragToggleName = this.mToggles[itemIndex]; 152 if (this.onItemDragStart) { 153 this.onItemDragStart(this.mCurrentDragToggleName); 154 }; 155 Log.showDebug(this.logTag, `onGridItemDragStart, mCurrentDragToggleName: ${this.mCurrentDragToggleName}`); 156 } 157 158 onGridItemDrop(event: ItemDragInfo, itemIndex: number, insertIndex: number, isSuccess: boolean) { 159 Log.showDebug(this.logTag, `onGridItemDrop, itemIndex: ${itemIndex} insertIndex: ${insertIndex} isSuccess: ${isSuccess} event: ${JSON.stringify(event)}`); 160 if (!isSuccess) { 161 this.callOnItemDrop('fail'); 162 return; 163 }; 164 if (itemIndex == insertIndex) { 165 this.callOnItemDrop('cancel'); 166 return; 167 }; 168 let status = 'success'; 169 let currentDragToggleName = this.mCurrentDragToggleName; 170 let globalDragToggleName = this.mGlobalDragToggleName; 171 Log.showDebug(this.logTag, `onItemDrop, currentDragToggleName: ${currentDragToggleName}`); 172 Log.showDebug(this.logTag, `onItemDrop, globalDragToggleName: ${globalDragToggleName}`); 173 if (itemIndex >= 0 && insertIndex >= 0) { // move 174 Log.showDebug(this.logTag, `onItemDrop, move`); 175 if (itemIndex > insertIndex) { 176 this.mToggles.splice(insertIndex, 0, currentDragToggleName); 177 this.mToggles.splice(itemIndex + 1, 1); 178 } else { 179 this.mToggles.splice(insertIndex + 1, 0, currentDragToggleName); 180 this.mToggles.splice(itemIndex, 1); 181 }; 182 } else if (itemIndex == -1 && insertIndex >= 0) { // insert 183 Log.showDebug(this.logTag, `onItemDrop, insert`); 184 if (this.mToggles.length < this.mMaxCount) { 185 this.mToggles.splice(insertIndex, 0, globalDragToggleName); 186 } else { 187 this.mToggles = JSON.parse(JSON.stringify(this.mToggles)); 188 status = 'cancel'; 189 }; 190 } else if (itemIndex >= 0 && insertIndex == -1) { // delete 191 Log.showDebug(this.logTag, `onItemDrop, delete`); 192 if (this.mToggles.length > this.mMinCount) { 193 this.mToggles.splice(itemIndex, 1); 194 } else { 195 this.mToggles = JSON.parse(JSON.stringify(this.mToggles)); 196 status = 'cancel'; 197 }; 198 }; 199 this.callOnItemDrop(status); 200 } 201 202 callOnItemDrop(status: string): void { 203 Log.showDebug(this.logTag, `callOnItemDrop, status: ${status}`); 204 if (this.onItemDrop) { 205 this.onItemDrop(status); 206 }; 207 this.mCurrentDragToggleName = ''; 208 } 209} 210