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 */
15import { Log } from '@ohos/common';
16import { DragArea } from '@ohos/common';
17import { EventConstants } from '@ohos/common';
18import { localEventManager } from '@ohos/common';
19import { BaseDragHandler } from '@ohos/common';
20import { CommonConstants } from '@ohos/common';
21import { layoutConfigManager } from '@ohos/common';
22import { SmartDockStyleConfig } from '../config/SmartDockStyleConfig';
23import SmartDockModel from '../model/SmartDockModel';
24import SmartDockConstants from '../common/constants/SmartDockConstants';
25import type { LauncherDragItemInfo } from '@ohos/common';
26
27const TAG = 'SmartDockDragHandler';
28
29/**
30 * SmartDock DragHandler
31 */
32export default class SmartDockDragHandler extends BaseDragHandler {
33  private mDockCoordinateData = [];
34  private readonly mSmartDockModel: SmartDockModel;
35  private readonly mSmartDockStyleConfig: SmartDockStyleConfig;
36  private mDevice = CommonConstants.DEFAULT_DEVICE_TYPE;
37
38  constructor() {
39    super();
40    this.mSmartDockModel = SmartDockModel.getInstance();
41    this.mSmartDockStyleConfig = layoutConfigManager.getStyleConfig(SmartDockStyleConfig.APP_LIST_STYLE_CONFIG, SmartDockConstants.FEATURE_NAME);
42    Log.showInfo(TAG, 'constructor!');
43  }
44
45  static getInstance(): SmartDockDragHandler {
46    if (globalThis.SmartDockDragHandler == null) {
47      globalThis.SmartDockDragHandler = new SmartDockDragHandler();
48    }
49    Log.showDebug(TAG, 'getInstance!');
50    return globalThis.SmartDockDragHandler;
51  }
52
53  setDragEffectArea(effectArea): void {
54    Log.showDebug(TAG, `setDragEffectArea: ${JSON.stringify(effectArea)}`);
55    AppStorage.setOrCreate('smartDockDragEffectArea', effectArea);
56    super.setDragEffectArea(effectArea);
57    this.updateDockParam(effectArea);
58  }
59
60  isDragEffectArea(x: number, y: number): boolean {
61    const isInEffectArea = super.isDragEffectArea(x, y);
62    Log.showDebug(TAG, `isDragEffectArea x: ${x}, y: ${y}, isInEffectArea: ${isInEffectArea}`);
63    const deviceType = AppStorage.get('deviceType');
64    const pageDesktopDragEffectArea: DragArea = AppStorage.get('pageDesktopDragEffectArea');
65    Log.showDebug(TAG, `isDragEffectArea pageDesktopDragEffectArea: ${JSON.stringify(pageDesktopDragEffectArea)}`);
66    if (pageDesktopDragEffectArea) {
67      if (deviceType == CommonConstants.DEFAULT_DEVICE_TYPE) {
68        if (isInEffectArea || (y < pageDesktopDragEffectArea.bottom && y > pageDesktopDragEffectArea.top)
69        && x < pageDesktopDragEffectArea.right && x > pageDesktopDragEffectArea.left) {
70          return true;
71        }
72        return false;
73      }
74      return isInEffectArea;
75    }
76    return false;
77  }
78
79  private updateDockParam(effectArea: DragArea): void {
80    this.mDockCoordinateData = [];
81    const dockWidth = effectArea.right - effectArea.left;
82    const dockData: [] = this.getDragRelativeData();
83    const dataCount = dockData.length;
84    const dockPadding: {right: number, left: number, top: number, bottom: number} = AppStorage.get('dockPadding');
85    const itemSize = this.mSmartDockStyleConfig.mListItemWidth;
86    const itemGap = this.mSmartDockStyleConfig.mListItemGap;
87    if (dataCount > 0) {
88      for (let index = 0; index < dataCount; index++) {
89        if (index == dataCount - 1) {
90          this.mDockCoordinateData.push(effectArea.right - dockPadding.left - (itemSize / 2));
91          return;
92        }
93        this.mDockCoordinateData.push(effectArea.left + dockPadding.left + (itemSize / 2) + ((itemSize + itemGap) * index));
94      }
95    } else {
96      this.mDockCoordinateData.push(dockWidth);
97    }
98    Log.showDebug(TAG, `updateDockParam DockCoordinateData: ${JSON.stringify(this.mDockCoordinateData)}`);
99  }
100
101  protected getDragRelativeData(): any {
102    const dockData: [] = AppStorage.get('residentList');
103    return dockData;
104  }
105
106  protected getItemIndex(x: number, y: number): number {
107    if (super.isDragEffectArea(x, y)) {
108      for (let index = 0; index < this.mDockCoordinateData.length; index++) {
109        if (this.mDockCoordinateData[index] > x) {
110          return index;
111        }
112      }
113      return this.mDockCoordinateData.length;
114    }
115    return CommonConstants.INVALID_VALUE;
116  }
117
118  /**
119   * Get dragItem location by coordinates.
120   *
121   * @param x - x position
122   * @param y - y position
123   */
124  getDragItemIndexByCoordinates(x: number, y: number): number {
125    if (super.isDragEffectArea(x, y)) {
126      for (let index = 0; index < this.mDockCoordinateData.length; index++) {
127        if (this.mDockCoordinateData[index] + this.mSmartDockStyleConfig.mListItemWidth / 2 >= x) {
128          return index;
129        }
130      }
131    }
132    return CommonConstants.INVALID_VALUE;
133  }
134
135  protected getItemByIndex(index: number): any {
136    const dockData: [] = this.getDragRelativeData();
137    if (index >= 0 && index < dockData.length) {
138      return dockData[index];
139    }
140    return null;
141  }
142
143  layoutAdjustment(insertIndex: number, itemIndex: number): void {
144    if (insertIndex != CommonConstants.INVALID_VALUE || itemIndex != CommonConstants.INVALID_VALUE) {
145      this.mSmartDockModel.insertItemToIndex(insertIndex, itemIndex);
146    }
147  }
148
149  onDragDrop(x: number, y: number): boolean {
150    const dragItemInfo: LauncherDragItemInfo = AppStorage.get<LauncherDragItemInfo>('dragItemInfo');
151    if (!dragItemInfo.isDragging) {
152      return false;
153    }
154    const dragItemType: number = AppStorage.get('dragItemType');
155    const insertIndex = this.getItemIndex(x, y);
156    if (dragItemType === CommonConstants.DRAG_FROM_DOCK) {
157      const selectAppIndex: number = AppStorage.get('selectAppIndex');
158      globalThis.SmartDockDragHandler.layoutAdjustment(insertIndex, selectAppIndex);
159      return true;
160    }
161    if (dragItemType === CommonConstants.DRAG_FROM_DESKTOP
162    && AppStorage.get('deviceType') == CommonConstants.DEFAULT_DEVICE_TYPE) {
163      Log.showInfo(TAG, `onDrop insertIndex: ${insertIndex}`);
164      this.addItemToSmartDock(dragItemInfo, insertIndex);
165      return true;
166    }
167    return false;
168  }
169
170  addItemToSmartDock(dragItemInfo: LauncherDragItemInfo, insertIndex: number): boolean {
171    let addToDockRes = this.mSmartDockModel.addToSmartdock(dragItemInfo, insertIndex);
172    if (addToDockRes) {
173      localEventManager.sendLocalEventSticky(EventConstants.EVENT_REQUEST_PAGEDESK_ITEM_DELETE, {
174        bundleName: undefined,
175        keyName: dragItemInfo.keyName
176      });
177    }
178    return true;
179  }
180}