1/* 2 * Copyright (c) 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 '../utils/Log'; 17import { SettingsModel } from '../model/SettingsModel'; 18import { StyleConstants } from '../constants/StyleConstants'; 19import { CommonConstants } from '../constants/CommonConstants'; 20import { PresetStyleConstants } from '../constants/PresetStyleConstants'; 21import { layoutConfigManager } from '../layoutconfig/LayoutConfigManager'; 22import { LauncherLayoutStyleConfig } from '../layoutconfig/LauncherLayoutStyleConfig'; 23 24const TAG = 'LayoutViewModel'; 25 26/** 27 * layout viewmodel 28 */ 29export class LayoutViewModel { 30 private mIsPad = true; 31 private mScreenHeight: number | undefined; 32 private mScreenWidth: number | undefined; 33 private mWorkSpaceHeight: number | undefined; 34 private mDockHeight: number | undefined; 35 private mSysUITopHeight: number | undefined; 36 private mSysUIBottomHeight: number | undefined; 37 private mIndicatorHeight: number | undefined; 38 private readonly mLauncherLayoutStyleConfig: LauncherLayoutStyleConfig; 39 private mNavigationBarStatus = false; 40 private mDesktopGap: number | undefined; 41 private mDesktopIconMarginLeft: number | undefined; 42 private mDesktopIconMarginTop: number | undefined; 43 private mDesktopNameHeight: number | undefined; 44 private mDesktopNameLines: number | undefined; 45 private mDesktopIconNameMargin: number | undefined; 46 private mDesktopIconSize: number | undefined; 47 private mDesktopItemSize: number | undefined; 48 private mDesktopNameSize: number | undefined; 49 private mDesktopFolderSize: number | undefined; 50 private mGridRealHeight: number | undefined; 51 private mCommonDialogWidth = ''; 52 53 private constructor() { 54 this.mLauncherLayoutStyleConfig = layoutConfigManager.getStyleConfig( 55 LauncherLayoutStyleConfig.LAUNCHER_COMMON_STYLE_CONFIG, LauncherLayoutStyleConfig.LAUNCHER_PRODUCT_STYLE_CONFIG); 56 } 57 58 /** 59 * get the LayoutViewModel instance 60 * 61 * @return LayoutViewModel 62 */ 63 static getInstance(): LayoutViewModel { 64 if (globalThis.LayoutViewModelInstance == null) { 65 globalThis.LayoutViewModelInstance = new LayoutViewModel(); 66 globalThis.LayoutViewModelInstance.initScreen(); 67 } 68 return globalThis.LayoutViewModelInstance; 69 } 70 71 /** 72 * init screen info 73 * 74 * @param navigationBarStatus 75 */ 76 initScreen(navigationBarStatus?: string): void { 77 this.mScreenWidth = AppStorage.Get('screenWidth'); 78 this.mScreenHeight = AppStorage.Get('screenHeight'); 79 Log.showDebug(TAG, `initScreen screenWidth: ${this.mScreenWidth}, screenHeight: ${this.mScreenHeight}`); 80 this.mSysUITopHeight = this.mLauncherLayoutStyleConfig.mSysTopHeight; 81 this.mNavigationBarStatus = navigationBarStatus === '0' ? true : false; 82 83 if (!this.mNavigationBarStatus) { 84 if (this.mScreenWidth > this.mScreenHeight) { 85 this.mSysUIBottomHeight = this.mLauncherLayoutStyleConfig.mSysBottomHeight * this.mScreenWidth / 1280; 86 } else { 87 this.mSysUIBottomHeight = this.mLauncherLayoutStyleConfig.mSysBottomHeight * this.mScreenWidth / 360; 88 } 89 } else { 90 this.mSysUIBottomHeight = 0; 91 } 92 AppStorage.SetOrCreate('sysUIBottomHeight', this.mSysUIBottomHeight); 93 this.mIndicatorHeight = this.mLauncherLayoutStyleConfig.mIndicatorHeight; 94 Log.showDebug(TAG, `initScreen SysUIBottomHeight: ${this.mSysUIBottomHeight}, 95 IndicatorHeight: ${this.mIndicatorHeight}, SysUITopHeight: ${this.mSysUITopHeight}, 96 SysUIBottomHeight: ${this.mSysUIBottomHeight}`); 97 this.mCommonDialogWidth = this.mLauncherLayoutStyleConfig.mCommonDialogWidth; 98 } 99 100 /** 101 * set device type 102 * 103 * @param deviceType: Device type 104 */ 105 setDevice(deviceType: string): void { 106 this.mIsPad = deviceType === CommonConstants.PAD_DEVICE_TYPE; 107 AppStorage.SetOrCreate('isPad', this.mIsPad); 108 } 109 110 /** 111 * get workSpaceHeight 112 */ 113 getWorkSpaceHeight(): number { 114 return this.mWorkSpaceHeight; 115 } 116 117 /** 118 * get dockHeight 119 */ 120 getDockHeight(): number { 121 return this.mDockHeight; 122 } 123 124 /** 125 * get UninstallDialogWidth 126 */ 127 getCommonDialogWidth(): string { 128 return this.mCommonDialogWidth; 129 } 130 131 /** 132 * get indicatorHeight 133 */ 134 getIndicator(): number { 135 return this.mIndicatorHeight; 136 } 137 138 /** 139 * calculate dock 140 */ 141 calculateDock(): any { 142 Log.showInfo(TAG, 'calculateDock start'); 143 let margin = this.mLauncherLayoutStyleConfig.mDockSaveMargin; 144 let dockGap = this.mLauncherLayoutStyleConfig.mDockGutter; 145 let iconSize = this.mLauncherLayoutStyleConfig.mDockIconSize; 146 let listItemGap = this.mLauncherLayoutStyleConfig.mDockItemGap; 147 let dockPadding = this.mLauncherLayoutStyleConfig.mDockPadding; 148 let marginBottom = this.mLauncherLayoutStyleConfig.mDockMarginBottomHideBar; 149 if (!this.mNavigationBarStatus) { 150 marginBottom = this.mLauncherLayoutStyleConfig.mDockMarginBottom; 151 } 152 let maxDockNum = 0; 153 let dockSpaceWidth = this.mScreenWidth - 2 * margin; 154 let maxRecentNum = 3; 155 if (this.mScreenWidth < PresetStyleConstants.DEFAULT_DOCK_RECENT_WIDTH || !this.mIsPad) { 156 maxRecentNum = 0; 157 maxDockNum = ~~((dockSpaceWidth - 2 * dockPadding + listItemGap) / (iconSize + listItemGap)); 158 } else { 159 let maxNum = ~~((dockSpaceWidth - dockGap - 4 * dockPadding + 2 * listItemGap) / (iconSize + listItemGap)); 160 maxDockNum = maxNum - maxRecentNum; 161 } 162 this.mDockHeight = iconSize + 2 * dockPadding + marginBottom; 163 this.mWorkSpaceHeight = this.mScreenHeight - this.mSysUIBottomHeight - this.mDockHeight; 164 let result = { 165 mDockGap: dockGap, 166 mIconSize: iconSize, 167 mListItemWidth: iconSize, 168 mListItemHeight: iconSize, 169 mListItemGap: listItemGap, 170 mDockPadding: dockPadding, 171 mMaxRecentNum: maxRecentNum, 172 mMaxDockNum: maxDockNum, 173 mDockHeight: iconSize + 2 * dockPadding, 174 mMarginBottom: marginBottom 175 }; 176 return result; 177 } 178 179 /** 180 * calculate desktop 181 */ 182 calculateDesktop(): any { 183 Log.showInfo(TAG, 'calculateDesktop start'); 184 let margin = this.mLauncherLayoutStyleConfig.mMargin; 185 let realWidth = this.mScreenWidth - 2 * margin; 186 let realHeight = this.mWorkSpaceHeight - this.mIndicatorHeight - this.mSysUITopHeight; 187 if (this.mNavigationBarStatus) { 188 realHeight = realHeight - this.mLauncherLayoutStyleConfig.mSysBottomHeight; 189 } 190 let itemSize = this.mLauncherLayoutStyleConfig.mAppItemSize; 191 let minGutter = this.mLauncherLayoutStyleConfig.mGridGutter; 192 let column = ~~((realWidth + minGutter) / (itemSize + minGutter)); 193 let userWidth = (realWidth + minGutter - (itemSize + minGutter) * column); 194 let gutter = (userWidth / (column - 1)) + minGutter; 195 let row = ~~((realHeight + gutter) / (itemSize + gutter)); 196 let marginTop = ((realHeight + gutter - (itemSize + gutter) * row) / 2); 197 if (!this.mIsPad) { 198 if (row > 6) { 199 row = 6; 200 } 201 202 if (this.mNavigationBarStatus) { 203 realHeight = realHeight + this.mLauncherLayoutStyleConfig.mSysBottomHeight; 204 } 205 let remainHeight = (realHeight + gutter - (itemSize + gutter) * row) 206 realHeight -= remainHeight 207 marginTop = remainHeight / 2 + this.mSysUITopHeight 208 } 209 //set desktop icon 210 let ratio = this.mLauncherLayoutStyleConfig.mIconRatio; 211 let lines = this.mLauncherLayoutStyleConfig.mNameLines; 212 let appTextSize = this.mLauncherLayoutStyleConfig.mNameSize; 213 let nameHeight = this.mLauncherLayoutStyleConfig.mNameHeight; 214 let iconNameMargin = this.mLauncherLayoutStyleConfig.mIconNameGap; 215 let iconMarginVertical = ratio * itemSize; 216 let iconHeight = itemSize - 2 * iconMarginVertical - nameHeight - iconNameMargin; 217 let iconMarginHorizontal = (itemSize - iconHeight) / 2; 218 if (AppStorage.Get('isPortrait') ) { 219 row = 11; 220 column = 5; 221 } 222 this.updateGrid(row, column); 223 224 this.mDesktopGap = gutter; 225 this.mDesktopIconMarginLeft = iconMarginHorizontal; 226 this.mDesktopIconMarginTop = iconMarginVertical; 227 this.mDesktopNameLines = lines; 228 this.mDesktopNameHeight = nameHeight; 229 this.mDesktopIconNameMargin = iconNameMargin; 230 this.mDesktopIconSize = iconHeight; 231 this.mDesktopItemSize = itemSize; 232 this.mDesktopNameSize = appTextSize; 233 this.mGridRealHeight = realHeight; 234 //set desktop config 235 let result = { 236 mMargin: margin, 237 mColumnsGap: gutter, 238 mRowsGap: gutter, 239 mColumns: column, 240 mRows: row, 241 mDesktopMarginTop: marginTop, 242 mGridWidth: realWidth, 243 mGridHeight: realHeight, 244 mAppItemSize: itemSize, 245 mNameSize: appTextSize, 246 mNameHeight: nameHeight, 247 mIconNameMargin: iconNameMargin, 248 mIconSize: iconHeight, 249 mNameLines: lines, 250 mIconMarginHorizontal: iconMarginHorizontal, 251 mIconMarginVertical: iconMarginVertical 252 }; 253 return result; 254 } 255 256 /** 257 * calculate desktop folder 258 * 259 * @param layoutInfo folder layoutInfo 260 */ 261 calculateFolder(layoutInfo: any): any { 262 Log.showInfo(TAG, 'calculateFolder start'); 263 let itemSize = this.mLauncherLayoutStyleConfig.mAppItemSize; 264 let gap = this.mDesktopGap; 265 let iconMargin = this.mDesktopIconMarginLeft; 266 let gridColumn = SettingsModel.getInstance().getGridConfig().row; 267 let folderSize = this.mGridRealHeight / gridColumn + itemSize - iconMargin * 2; 268 let folderGutter = this.mLauncherLayoutStyleConfig.mFolderGutterRatio * folderSize; 269 let folderMargin = this.mLauncherLayoutStyleConfig.mFolderMarginRatio * folderSize; 270 271 let column = layoutInfo.column; 272 let iconSize = (folderSize - folderGutter * 2 - folderMargin * 2) / column; 273 let nameHeight = this.mDesktopNameHeight; 274 let nameLines = this.mDesktopNameLines; 275 let iconNameMargin = this.mDesktopIconNameMargin; 276 277 this.mDesktopFolderSize = folderSize; 278 let result = { 279 mGridSize: folderSize, 280 mFolderAppSize: iconSize, 281 mFolderGridGap: folderGutter, 282 mGridMargin: folderMargin, 283 mNameHeight: nameHeight, 284 mNameLines: nameLines, 285 mIconNameMargin: iconNameMargin 286 }; 287 return result; 288 } 289 290 /** 291 * calculate open folder 292 * 293 * @param openFolderConfig layoutInfo 294 */ 295 calculateOpenFolder(openFolderConfig: any): any { 296 Log.showInfo(TAG, 'calculateOpenFolder start'); 297 let row = openFolderConfig.row; 298 let column = openFolderConfig.column; 299 let gutter = this.mLauncherLayoutStyleConfig.mFolderOpenGutter; 300 let padding = this.mLauncherLayoutStyleConfig.mFolderOpenPADDING; 301 let margin = this.mLauncherLayoutStyleConfig.mFolderOpenMargin; 302 let title = this.mLauncherLayoutStyleConfig.mFolderOpenTitle; 303 let itemSize = this.mDesktopItemSize; 304 let layoutWidth = column * itemSize + (column - 1) * gutter + 2 * padding; 305 let layoutHeight = row * itemSize + (row - 1) * gutter + 2 * padding; 306 let layoutSwiperHeight = row * itemSize + (row - 1) * gutter + 2 * padding + itemSize; 307 let result = { 308 mOpenFolderGridWidth: layoutWidth, 309 mOpenFolderGridHeight: layoutHeight, 310 mOpenFolderSwiperHeight: layoutSwiperHeight, 311 mOpenFolderAddIconSize: this.mDesktopIconSize, 312 mOpenFolderIconSize: this.mDesktopIconSize, 313 mOpenFolderAppSize: this.mDesktopItemSize, 314 mOpenFolderAppNameSize: this.mDesktopNameSize, 315 mOpenFolderAppNameHeight: this.mDesktopNameHeight, 316 mOpenFolderGridRow: row, 317 mOpenFolderGridColumn: column, 318 mOpenFolderGridGap: gutter, 319 mOpenFolderGridPadding: padding, 320 mFolderOpenMargin: margin, 321 mFolderOpenTitle: title, 322 mOpenFolderGridIconTopPadding: this.mDesktopIconMarginTop 323 }; 324 return result; 325 } 326 327 /** 328 * calculate add app 329 * 330 * @param addFolderConfig 331 */ 332 calculateFolderAddList(addFolderConfig: any): any { 333 Log.showInfo(TAG, 'calculateFolderAddList start'); 334 let column: number = addFolderConfig.column; 335 let margin: number = this.mLauncherLayoutStyleConfig.mFolderAddGridMargin; 336 let saveMargin: number = PresetStyleConstants.DEFAULT_SCREEN_GRID_GAP_AND_MARGIN; 337 let screenGap: number = PresetStyleConstants.DEFAULT_SCREEN_GRID_GAP_AND_MARGIN; 338 let gap: number = this.mLauncherLayoutStyleConfig.mFolderAddGridGap; 339 let maxHeight: number = this.mLauncherLayoutStyleConfig.mFolderAddMaxHeight * 340 (this.mScreenHeight - this.mSysUITopHeight); 341 let toggleSize: number = this.mLauncherLayoutStyleConfig.mFolderToggleSize; 342 let screenColumns: number = PresetStyleConstants.DEFAULT_PHONE_GRID_APP_COLUMNS; 343 let textSize: number = this.mLauncherLayoutStyleConfig.mFolderAddTextSize; 344 let textLines: number = this.mLauncherLayoutStyleConfig.mFolderAddTextLines; 345 let titleSize: number = this.mLauncherLayoutStyleConfig.mFolderAddTitleSize; 346 let linesHeight = textSize * textLines; 347 let buttonSize: number = this.mLauncherLayoutStyleConfig.mFolderAddButtonSize; 348 let ratio: number = this.mLauncherLayoutStyleConfig.mFolderAddIconRatio; 349 if (this.mIsPad) { 350 screenColumns = PresetStyleConstants.DEFAULT_PAD_GRID_APP_COLUMNS; 351 } 352 let columnsWidth = this.mScreenWidth - 2 * saveMargin - (screenColumns - 1) * screenGap; 353 let columnWidth = columnsWidth / screenColumns; 354 let layoutWidth = columnWidth * column + (column - 1) * screenGap; 355 let gridSize = layoutWidth - 2 * margin; 356 let itemSize = (gridSize - (column - 1) * gap) / column; 357 let layoutHeight = layoutWidth + StyleConstants.DEFAULT_APP_ADD_TITLE_SIZE + 358 StyleConstants.DEFAULT_BUTTON_HEIGHT_NUMBER + 359 StyleConstants.DEFAULT_DIALOG_BOTTOM_MARGIN_NUMBER; 360 let iconSize = (1 - 2 * ratio) * itemSize - linesHeight - this.mDesktopIconNameMargin; 361 362 let result = { 363 mAddFolderGridWidth: gridSize, 364 mAddFolderDialogWidth: layoutWidth, 365 mAddFolderDialogHeight: layoutHeight, 366 mAddFolderGridGap: gap, 367 mAddFolderGridMargin: margin, 368 mAddFolderMaxHeight: maxHeight, 369 mFolderToggleSize: toggleSize, 370 mAddFolderTextSize: textSize, 371 mAddFolderTextLines: textLines, 372 mAddFolderLinesHeight: linesHeight, 373 mAddFolderItemSize: itemSize, 374 mAddFolderIconPaddingTop: itemSize * ratio, 375 mAddFolderIconMarginHorizontal: (itemSize - iconSize) / 2, 376 mAddFolderIconSize: iconSize, 377 mAddFolderTitleSize: titleSize, 378 mAddFolderButtonSize: buttonSize 379 }; 380 return result; 381 } 382 383 /** 384 * calculate card form 385 */ 386 calculateForm(): any { 387 Log.showInfo(TAG, 'calculateForm start'); 388 let iconSize = this.mDesktopIconSize; 389 let folderSize = this.mDesktopFolderSize; 390 let itemSize = this.mDesktopItemSize; 391 let gap = this.mDesktopGap; 392 let iconMarginHorizontal = this.mDesktopIconMarginLeft; 393 let iconMarginVertical = this.mDesktopIconMarginTop; 394 let nameHeight = this.mDesktopNameHeight; 395 let widthDimension1: number = folderSize; 396 let heightDimension1: number = iconSize; 397 let widthDimension2 = folderSize; 398 let heightDimension2 = folderSize; 399 let widthDimension3 = (itemSize + gap) * 4 - gap - iconMarginHorizontal * 2; 400 let heightDimension3 = folderSize; 401 let widthDimension4 = widthDimension3; 402 let heightDimension4 = (itemSize + gap) * 4 - gap - 2 * iconMarginVertical - 403 nameHeight - this.mDesktopIconNameMargin; 404 let result = { 405 widthDimension1: widthDimension1, 406 heightDimension1: heightDimension1, 407 widthDimension2: widthDimension2, 408 heightDimension2: heightDimension2, 409 widthDimension3: widthDimension3, 410 heightDimension3: heightDimension3, 411 widthDimension4: widthDimension4, 412 heightDimension4: heightDimension4, 413 mIconNameMargin: this.mDesktopIconNameMargin 414 }; 415 return result; 416 } 417 418 /** 419 * calculate app center 420 */ 421 calculateAppCenter(): any { 422 Log.showInfo(TAG, 'calculateAppCenter start'); 423 let appCenterMarginLeft: number = this.mLauncherLayoutStyleConfig.mAppCenterMarginLeft; 424 let saveMargin: number = this.mLauncherLayoutStyleConfig.mAppCenterMargin; 425 let gutter: number = this.mLauncherLayoutStyleConfig.mAppCenterGutter; 426 let appItemSize = this.mLauncherLayoutStyleConfig.mAppCenterSize; 427 let width = this.mScreenWidth - 2 * appCenterMarginLeft; 428 let height = this.mWorkSpaceHeight; 429 let column = ~~((width + gutter) / (appItemSize + gutter)); 430 let row = ~~((height + gutter) / (appItemSize + gutter)); 431 let padding = (height - row * (appItemSize + gutter) + gutter) / 2; 432 let ratio = this.mLauncherLayoutStyleConfig.mAppCenterRatio; 433 let lines = this.mLauncherLayoutStyleConfig.mAppCenterNameLines; 434 let appTextSize = this.mLauncherLayoutStyleConfig.mAppCenterNameSize; 435 let nameHeight = lines * appTextSize; 436 let iconMarginVertical = ratio * appItemSize; 437 let iconHeight = appItemSize - 2 * iconMarginVertical - nameHeight - this.mDesktopIconNameMargin; 438 let result = { 439 mColumnsGap: gutter, 440 mRowsGap: gutter, 441 mColumns: column, 442 mRows: row, 443 mGridWidth: width, 444 mGridHeight: height - 2 * padding, 445 mPadding: padding, 446 mNameSize: appTextSize, 447 mNameHeight: nameHeight, 448 mIconSize: iconHeight, 449 mNameLines: lines, 450 mIconMarginVertical: iconMarginVertical, 451 mAppItemSize: appItemSize, 452 mAppCenterMarginLeft:appCenterMarginLeft 453 }; 454 return result; 455 } 456 457 /** 458 * update gridConfig info 459 * 460 * @param {number} row row of grid 461 * @param {number} column column of grid 462 */ 463 private updateGrid(row: number, column: number): void { 464 Log.showInfo(TAG, `updateGrid row ${row} column ${column}`); 465 let settingsModel = SettingsModel.getInstance(); 466 let gridConfig = settingsModel.getGridConfig(); 467 gridConfig.row = row; 468 gridConfig.column = column; 469 const layoutDimension = `${row}X${column}`; 470 gridConfig.layout = layoutDimension; 471 gridConfig.name = layoutDimension; 472 } 473}