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 .height(this.calcGridHeight(Math.ceil(this.mToggles.length / this.mColumnCount), this.style.rowHeight, this.style.rowGap)) 76 .width('100%') 77 .columnsTemplate(this.calcColumnsTemplate(this.mColumnCount)) 78 .editMode(true) 79 .maxCount(this.calcMaxRowCount(this.mMaxCount, this.mColumnCount)) 80 .minCount(this.calcMinRowCount(this.mMinCount, this.mColumnCount)) 81 .cellLength(this.style.rowHeight) 82 .rowsGap(this.style.rowGap + 'px') 83 .columnsGap(this.style.columnGap) 84 .layoutDirection(1) 85 .direction(0) 86 .onItemDragEnter(this.onItemDragEnter.bind(this)) 87 .onItemDragMove(this.onItemDragMove.bind(this)) 88 .onItemDragLeave(this.onItemDragLeave.bind(this)) 89 .onItemDragStart((event, itemIndex) => { 90 this.onGridItemDragStart(event, itemIndex) 91 return this.DragComponent 92 }) 93 .onItemDrop(this.onGridItemDrop.bind(this)) 94 } 95 96 calcGridHeight(rowCount, rowHeight, rowGap) { 97 Log.showDebug(this.logTag, `calcGridHeight, rowCount: ${rowCount} rowHeight: ${rowHeight} rowGap: ${rowGap}`); 98 let height = rowCount * rowHeight + (rowCount - 1) * rowGap; 99 if (height <= 0) { 100 height = 108; 101 } 102 Log.showDebug(this.logTag, `calcGridHeight, height: ${height}`); 103 return height + 'px'; 104 } 105 106 calcColumnsTemplate(columnCount: number): string{ 107 Log.showDebug(this.logTag, `calcColumnsTemplate, columnCount: ${columnCount}`); 108 let columnsTemplate = '1fr'; 109 for (let i = 1;i < columnCount; i++) { 110 columnsTemplate += ' 1fr'; 111 } 112 Log.showDebug(this.logTag, `calcColumnsTemplate, columnsTemplate: ${columnsTemplate}`); 113 return columnsTemplate; 114 } 115 116 calcMaxRowCount(maxCount: number, columnCount: number): number{ 117 Log.showDebug(this.logTag, `calcMaxRowCount, maxCount: ${maxCount} columnCount: ${columnCount}`); 118 let maxRowCount = Math.ceil(maxCount / columnCount); 119 if (maxRowCount < 1) { 120 maxRowCount = 1; 121 }; 122 Log.showDebug(this.logTag, `calcMaxRowCount, maxRowCount: ${maxRowCount}`); 123 return maxRowCount; 124 } 125 126 calcMinRowCount(minCount: number, columnCount: number): number{ 127 Log.showDebug(this.logTag, `calcMinRowCount, minCount: ${minCount} columnCount: ${columnCount}`); 128 let minRowCount = Math.ceil(minCount / columnCount); 129 if (minRowCount < 1) { 130 minRowCount = 1; 131 } 132 Log.showDebug(this.logTag, `calcMinRowCount, minRowCount: ${minRowCount}`); 133 return minRowCount; 134 } 135 136 onItemDragEnter(event) { 137 Log.showDebug(this.logTag, `onItemDragEnter, event: ${JSON.stringify(event)}`); 138 } 139 140 onItemDragMove(event, itemIndex, insertIndex) { 141 Log.showDebug(this.logTag, `onItemDragMove, itemIndex: ${itemIndex} insertIndex: ${insertIndex} event: ${JSON.stringify(event)}`); 142 } 143 144 onItemDragLeave(event, itemIndex) { 145 Log.showDebug(this.logTag, `onItemDragLeave, itemIndex: ${itemIndex} event: ${JSON.stringify(event)}`); 146 } 147 148 onGridItemDragStart(event, itemIndex) { 149 Log.showDebug(this.logTag, `onGridItemDragStart, itemIndex: ${itemIndex} event: ${JSON.stringify(event)}`); 150 this.mCurrentDragToggleName = this.mToggles[itemIndex]; 151 if (this.onItemDragStart) { 152 this.onItemDragStart(this.mCurrentDragToggleName); 153 }; 154 Log.showDebug(this.logTag, `onGridItemDragStart, mCurrentDragToggleName: ${this.mCurrentDragToggleName}`); 155 } 156 157 onGridItemDrop(event, itemIndex, insertIndex, isSuccess) { 158 Log.showDebug(this.logTag, `onGridItemDrop, itemIndex: ${itemIndex} insertIndex: ${insertIndex} isSuccess: ${isSuccess} event: ${JSON.stringify(event)}`); 159 if (!isSuccess) { 160 this.callOnItemDrop('fail'); 161 return; 162 }; 163 if (itemIndex == insertIndex) { 164 this.callOnItemDrop('cancel'); 165 return; 166 }; 167 let status = 'success'; 168 let currentDragToggleName = this.mCurrentDragToggleName; 169 let globalDragToggleName = this.mGlobalDragToggleName; 170 Log.showDebug(this.logTag, `onItemDrop, currentDragToggleName: ${currentDragToggleName}`); 171 Log.showDebug(this.logTag, `onItemDrop, globalDragToggleName: ${globalDragToggleName}`); 172 if (itemIndex >= 0 && insertIndex >= 0) { // move 173 Log.showDebug(this.logTag, `onItemDrop, move`); 174 if (itemIndex > insertIndex) { 175 this.mToggles.splice(insertIndex, 0, currentDragToggleName); 176 this.mToggles.splice(itemIndex + 1, 1); 177 } else { 178 this.mToggles.splice(insertIndex + 1, 0, currentDragToggleName); 179 this.mToggles.splice(itemIndex, 1); 180 }; 181 } else if (itemIndex == -1 && insertIndex >= 0) { // insert 182 Log.showDebug(this.logTag, `onItemDrop, insert`); 183 if (this.mToggles.length < this.mMaxCount) { 184 this.mToggles.splice(insertIndex, 0, globalDragToggleName); 185 } else { 186 this.mToggles = JSON.parse(JSON.stringify(this.mToggles)); 187 status = 'cancel'; 188 }; 189 } else if (itemIndex >= 0 && insertIndex == -1) { // delete 190 Log.showDebug(this.logTag, `onItemDrop, delete`); 191 if (this.mToggles.length > this.mMinCount) { 192 this.mToggles.splice(itemIndex, 1); 193 } else { 194 this.mToggles = JSON.parse(JSON.stringify(this.mToggles)); 195 status = 'cancel'; 196 }; 197 }; 198 this.callOnItemDrop(status); 199 } 200 201 callOnItemDrop(status: string): void { 202 Log.showDebug(this.logTag, `callOnItemDrop, status: ${status}`); 203 if (this.onItemDrop) { 204 this.onItemDrop(status); 205 }; 206 this.mCurrentDragToggleName = ''; 207 } 208} 209