687 lines
26 KiB
C++
687 lines
26 KiB
C++
/*----------------------------------------------------------------------------
|
|
* Copyright (c) TJD Technologies Co., Ltd. 2024. All rights reserved.
|
|
*
|
|
* Description:
|
|
*
|
|
* Author: huangshuyi
|
|
*
|
|
* Create: 2024-7
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
#include "TjdUiAppFloatWindowBlend.h"
|
|
#include "TjdUiAppIds.h"
|
|
#include "TjdUiAppMainView.h"
|
|
#include "TjdUiImageIds.h"
|
|
#include "cmath"
|
|
#include "common/image_cache_manager.h"
|
|
#include "common/screen.h"
|
|
#include "components/root_view.h"
|
|
#include "dock/vibrator_manager.h"
|
|
#include "draw/draw_utils.h"
|
|
#include "engines/gfx/lite_m_gfx_engine.h"
|
|
#include "gfx_utils/heap_base.h"
|
|
#include "imgdecode/image_load.h"
|
|
#include "sql_setting.h"
|
|
#include "sys_config.h"
|
|
#include <string>
|
|
|
|
using namespace OHOS;
|
|
|
|
#define ENABLE_PRINT_INFO 1
|
|
#if ENABLE_PRINT_INFO
|
|
#define static_print_info(...) sys_ui_log_i(__VA_ARGS__) // 一般信息打印宏控制
|
|
#define static_print_warn(...) sys_ui_log_w(__VA_ARGS__) // 警告信息打印一般常开
|
|
#define static_print_error(...) sys_ui_log_e(__VA_ARGS__) // 错误信息打印一般常开
|
|
#else
|
|
#define static_print_info(...)
|
|
#define static_print_warn(...)
|
|
#define static_print_error(...)
|
|
#endif
|
|
|
|
namespace TJD {
|
|
|
|
#define FLOAT_WINDOW_BIN_PATH TJD_IMAGE_PATH "/img_main_floatwindow.bin"
|
|
#define IMAGE_WINDOW_WIDTH 76
|
|
#define IMAGE_ICON_WIDTH (76)
|
|
#define FLOATWINDOW_IMAGE_BG_X 218
|
|
#define FLOATWINDOW_IMAGE_BG_Y 195
|
|
#define FLOATWINDOW_IMAGE_BG_WIDTH 228
|
|
#define FLOATWINDOW_IMAGE_BG_HEIGHT 250
|
|
|
|
#define FLOAT_WINDOW_VIEWID "floatWindow"
|
|
|
|
struct iconFixInfo
|
|
{
|
|
TjdUiAppViewId sliceId; //点击进入的Slice的ID
|
|
int imageId;
|
|
const char *name;
|
|
};
|
|
struct iconInfo
|
|
{
|
|
iconFixInfo fixInfo;
|
|
double angle;
|
|
Rect area;
|
|
// 默认构造函数
|
|
iconInfo() : fixInfo{TJD_APP_VIEW_INVALID, 0, nullptr}, angle(0.0), area() {}
|
|
};
|
|
static uint8_t displayNum = 4;
|
|
static bool needCycle_ = false;
|
|
static uint8_t isInit = 0;
|
|
|
|
static const iconFixInfo g_fixInfoArray[] = {
|
|
{TJD_APP_VIEW_HR, IMG_MAIN_FLOATWINDOW_HEARTRATE, "hr"},
|
|
{TJD_APP_VIEW_SPO2, IMG_MAIN_FLOATWINDOW_SPO2, "spo2"},
|
|
{TJD_APP_VIEW_SPORT, IMG_MAIN_FLOATWINDOW_SPORT, "sport"},
|
|
{TJD_APP_VIEW_PLAYER, IMG_MAIN_FLOATWINDOW_MUSIC, "music"},
|
|
{TJD_APP_VIEW_SLEEP, IMG_MAIN_FLOATWINDOW_SLEEP, "sleep"},
|
|
{TJD_APP_VIEW_STRESS, IMG_MAIN_FLOATWINDOW_PRESSURE, "pressure"},
|
|
{TJD_APP_VIEW_BREATHING, IMG_MAIN_FLOATWINDOW_BREATHE, "breathe"},
|
|
{TJD_APP_VIEW_SPORT_RECORD, IMG_MAIN_FLOATWINDOW_SPORT_RECORD, "sport_record"},
|
|
{TJD_APP_VIEW_DAILYDATA, IMG_MAIN_FLOATWINDOW_DATA, "data"},
|
|
{TJD_APP_VIEW_PHONE, IMG_MAIN_FLOATWINDOW_PHONE, "phone"},
|
|
{TJD_APP_VIEW_MESSAGE_TOTAL, IMG_MAIN_FLOATWINDOW_MESSAGE, "message"},
|
|
{TJD_APP_VIEW_WEATHER, IMG_MAIN_FLOATWINDOW_WEATHER, "weather"},
|
|
{TJD_APP_VIEW_TIMER, IMG_MAIN_FLOATWINDOW_TIMER, "timer"},
|
|
{TJD_APP_VIEW_STOPWATCH, IMG_MAIN_FLOATWINDOW_STOPWATCH, "stopwatch"},
|
|
{TJD_APP_VIEW_ALARM, IMG_MAIN_FLOATWINDOW_CLOCK, "alarm"},
|
|
{TJD_APP_VIEW_CALCULATOR, IMG_MAIN_FLOATWINDOW_CALCULATOR, "calculator"},
|
|
{TJD_APP_VIEW_CALENDAR, IMG_MAIN_FLOATWINDOW_CALENDAR, "calendar"},
|
|
{TJD_APP_VIEW_COMPASS, IMG_MAIN_FLOATWINDOW_COMPASS, "compass"},
|
|
{TJD_APP_VIEW_RECORD, IMG_MAIN_FLOATWINDOW_RECORDING, "recording"},
|
|
{TJD_APP_VIEW_CAMERA, IMG_MAIN_FLOATWINDOW_CAMERA, "camera"},
|
|
{TJD_APP_VIEW_ALBUM, IMG_MAIN_FLOATWINDOW_PHOTO, "album"},
|
|
{TJD_APP_VIEW_EBOOK, IMG_MAIN_FLOATWINDOW_BOOK, "ebook"},
|
|
{TJD_APP_VIEW_BUSINESSCARD, IMG_MAIN_FLOATWINDOW_CARD, "businesscard"},
|
|
{TJD_APP_VIEW_WALLET, IMG_MAIN_FLOATWINDOW_WALLET, "wallet"},
|
|
{TJD_APP_VIEW_VIDEO_CTRL, IMG_MAIN_FLOATWINDOW_VIDEO, "video"},
|
|
{TJD_APP_VIEW_FEMALE, IMG_MAIN_FLOATWINDOW_PHYSIOLOGY, "physiology"},
|
|
{TJD_APP_VIEW_VOICE_ASSISTANT, IMG_MAIN_FLOATWINDOW_AI, "ai"},
|
|
{TJD_APP_VIEW_GAME, IMG_MAIN_FLOATWINDOW_GAME, "game"},
|
|
{TJD_APP_VIEW_SETTING, IMG_MAIN_FLOATWINDOW_SET, "setting"},
|
|
{TJD_APP_VIEW_LUCKY_CLOVER, IMG_MAIN_FLOATWINDOW_LEFUN, "lefun"},
|
|
{TJD_APP_VIEW_LEFUN_AI, IMG_MAIN_FLOATWINDOW_LEFUNAI, "lefunai"},
|
|
{TJD_APP_VIEW_MS_GAME, IMG_MAIN_FLOATWINDOW_SOMATOSENSORY, "somatosensory"},
|
|
{TJD_APP_VIEW_ALIPAY, IMG_MAIN_FLOATWINDOW_ALIPAY, "alipay"},
|
|
{TJD_APP_VIEW_PLAY_DIAL, IMG_MAIN_FLOATWINDOW_WATCHFACE, "watchface"},
|
|
{TJD_APP_VIEW_MAIN, IMG_MAIN_FLOATWINDOW_BAIDU, "baidu"},
|
|
};
|
|
|
|
static iconInfo *iconInfoPtr = nullptr;
|
|
|
|
static void CalculatePointOnCircle(double R, double angleDegrees, double &x, double &y, uint8_t isAbsCoor)
|
|
{
|
|
double adjustedAngle = 90.0 - angleDegrees;
|
|
if (adjustedAngle < 0) {
|
|
adjustedAngle += 360.0;
|
|
}
|
|
double radians = angleDegrees * UI_PI / 180.0;
|
|
double xRelative = R * sin(radians);
|
|
double yRelative = -R * cos(radians);
|
|
if (isAbsCoor) {
|
|
x = Screen::GetInstance().GetWidth() / 2 + xRelative;
|
|
y = Screen::GetInstance().GetWidth() / 2 + yRelative;
|
|
} else {
|
|
x = xRelative;
|
|
y = yRelative;
|
|
}
|
|
}
|
|
|
|
static double CalculateIconAngle(uint16_t CycleR, uint16_t iconR)
|
|
{
|
|
double ac = iconR;
|
|
double oc = CycleR - iconR;
|
|
double aoc = asin(ac / oc);
|
|
double angleDegrees = aoc * (180.0 / UI_PI);
|
|
return angleDegrees * 2;
|
|
}
|
|
|
|
double TjdUiAppFloatWindowBlend::FindCorrectIcon(void)
|
|
{
|
|
double iconStartAngle;
|
|
double iconEndAngle;
|
|
double diffAngle = 0;
|
|
const double iconGapAngle = angleReserve - angleIcon;
|
|
for (uint8_t elem : iconList) {
|
|
// printf("icon index:%d,name:%s,angle:%f\n", elem, imageIconArray[elem].name, imageIconArray[elem].angle);
|
|
iconStartAngle = iconInfoPtr[elem].angle - angleIcon / 2;
|
|
iconEndAngle = iconInfoPtr[elem].angle + angleIcon / 2;
|
|
if (startAngle > iconStartAngle && startAngle <= iconEndAngle) {
|
|
|
|
if (startAngle > iconInfoPtr[elem].angle) {
|
|
diffAngle = -(iconEndAngle - startAngle + iconGapAngle);
|
|
} else {
|
|
diffAngle = startAngle - iconStartAngle;
|
|
}
|
|
// printf("find correct icon:%s is need correct, diff angle:%f\n", imageIconArray[elem].name, diffAngle);
|
|
return diffAngle;
|
|
}
|
|
}
|
|
|
|
return startAngle - (iconInfoPtr[iconList.front()].angle - angleIcon / 2);
|
|
}
|
|
|
|
bool TjdUiAppFloatWindowBlend::OnDrag(OHOS::UIView &view, const OHOS::DragEvent &event)
|
|
{
|
|
if (floatWindowAnimator_.GetState() != OHOS::Animator::STOP) {
|
|
StopFloatWindowAnimator();
|
|
}
|
|
if (IsFloatWindowVisible() == true) {
|
|
int16_t yDiff = event.GetDeltaY();
|
|
RefreshDelta(yDiff);
|
|
UpdateFuchuang(yDiff, 0, false);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool TjdUiAppFloatWindowBlend::OnDragEnd(OHOS::UIView &view, const OHOS::DragEvent &event)
|
|
{
|
|
if (IsFloatWindowVisible() == true) {
|
|
OHOS::Point last = event.GetPreLastPoint();
|
|
OHOS::Point current = event.GetLastPoint();
|
|
if ((last.x == current.x) && (last.y == current.y)) {
|
|
last = current;
|
|
current = event.GetCurrentPos();
|
|
}
|
|
DragThrowAnimator(current, last, event.GetDragDirection());
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool TjdUiAppFloatWindowBlend::OnRotate(OHOS::UIView &view, const OHOS::RotateEvent &event)
|
|
{
|
|
if (floatWindowAnimator_.GetState() != OHOS::Animator::STOP) {
|
|
StopFloatWindowAnimator();
|
|
}
|
|
if (IsFloatWindowVisible() == true) {
|
|
lastRotate_ = event.GetRotate();
|
|
|
|
RefreshDelta(lastRotate_);
|
|
UpdateFuchuang(lastRotate_, 0, false);
|
|
int16_t x = FLOATWINDOW_IMAGE_BG_X + FLOATWINDOW_IMAGE_BG_WIDTH - IMAGE_WINDOW_WIDTH / 2; // 218 + 228 - 38 =
|
|
// 408
|
|
int16_t y = FLOATWINDOW_IMAGE_BG_Y + IMAGE_WINDOW_WIDTH / 2; // 195 + 38 = 230
|
|
const Point point = {x, y};
|
|
int curImageId = 0;
|
|
for (uint8_t elem : iconList) {
|
|
if (iconInfoPtr[elem].area.IsContains(point)) {
|
|
curImageId = iconInfoPtr[elem].fixInfo.imageId;
|
|
break;
|
|
}
|
|
}
|
|
if (lastImageId_ != -1 && curImageId != 0 && curImageId != lastImageId_) {
|
|
#if ENABLE_VIBRATOR
|
|
OHOS::VibratorFunc vibratorFunc = OHOS::VibratorManager::GetInstance()->GetVibratorFunc();
|
|
vibratorFunc(OHOS::VibratorType::VIBRATOR_TYPE_ONE);
|
|
#endif
|
|
}
|
|
lastImageId_ = curImageId;
|
|
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool TjdUiAppFloatWindowBlend::OnRotateEnd(OHOS::UIView &view, const OHOS::RotateEvent &event)
|
|
{
|
|
if (IsFloatWindowVisible() == true) {
|
|
DragThrowAnimator({0, 0}, {0, 0},
|
|
lastRotate_ > 0 ? OHOS::DragEvent::DIRECTION_TOP_TO_BOTTOM
|
|
: OHOS::DragEvent::DIRECTION_BOTTOM_TO_TOP);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool TjdUiAppFloatWindowBlend::OnClick(OHOS::UIView &view, const OHOS::ClickEvent &event)
|
|
{
|
|
std::string viewId = view.GetViewId();
|
|
if (viewId == FLOAT_WINDOW_VIEWID) {
|
|
HideFloatWindow();
|
|
} else {
|
|
const Point point = {event.GetCurrentPos().x, event.GetCurrentPos().y};
|
|
for (uint8_t elem : iconList) {
|
|
if (iconInfoPtr[elem].area.IsContains(point)) {
|
|
OHOS::NativeAbility::GetInstance().ChangeSlice(iconInfoPtr[elem].fixInfo.sliceId);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void TjdUiAppFloatWindowBlend::HideFloatWindow()
|
|
{
|
|
TjdUiAppMainView *mainView = TjdUiAppMainView::GetInstance();
|
|
if (mainView == nullptr) {
|
|
return;
|
|
}
|
|
SetVisible(false);
|
|
ClearBackgroundBlur();
|
|
ClearFocus();
|
|
// auto wfBase = dynamic_cast<TjdUiWfBase *>(mainView->GetViewByCardId(TJD_MAIN_PAGE_WATCH_FACE));
|
|
// if (wfBase->IsDialView()) {
|
|
// auto *dial = wfBase->GetDialViewGroup();
|
|
// if (dial != nullptr) {
|
|
// dial->OnActive();
|
|
// }
|
|
// } else {
|
|
// wfBase->OnActive();
|
|
// }
|
|
}
|
|
|
|
void TjdUiAppFloatWindowBlend::ShowFloatWindow()
|
|
{
|
|
TjdUiAppMainView *mainView = TjdUiAppMainView::GetInstance();
|
|
if (mainView == nullptr) {
|
|
return;
|
|
}
|
|
// auto wfBase = dynamic_cast<TjdUiWfBase *>(mainView->GetViewByCardId(TJD_MAIN_PAGE_WATCH_FACE));
|
|
// if (wfBase->IsDialView()) {
|
|
// auto *dial = wfBase->GetDialViewGroup();
|
|
// if (dial != nullptr) {
|
|
// dial->OnInactive();
|
|
// }
|
|
// } else {
|
|
// wfBase->OnInactive();
|
|
// }
|
|
SetVisible(true);
|
|
OHOS::RootView::GetInstance()->ClearBlurView(OHOS::RootView::GetInstance()->GetBlurView());
|
|
SetBackgroundBlur(32);
|
|
SetFullScreenBlur(false);
|
|
OHOS::FocusManager::GetInstance()->ClearFocus();
|
|
RequestFocus();
|
|
// TjdUiAppMainPageWf::GetInstance()->HideSystemViewIcon();
|
|
mainView->GetWfCommon()->HideSystemViewIcon();
|
|
}
|
|
|
|
bool TjdUiAppFloatWindowBlend::IsFloatWindowVisible(void) { return IsVisible(); }
|
|
|
|
TjdUiAppFloatWindowBlend::TjdUiAppFloatWindowBlend()
|
|
: floatWindowAnimator_(&floatWindowAnimatorCallback_, nullptr, 0, true)
|
|
{
|
|
floatWindowAnimatorCallback_.SetFloatWindowBlend(this);
|
|
|
|
uint8_t sliceNum;
|
|
isInit = 0;
|
|
|
|
const uint16_t *sliceId = sql_setting_get_floating_window_map(&sliceNum);
|
|
needCycle_ = false;
|
|
if (sliceNum <= 4) {
|
|
sliceNum = 4;
|
|
needCycle_ = true;
|
|
}
|
|
if (sliceNum == 4) {
|
|
iconInfoPtr = new iconInfo[sliceNum + 1];
|
|
} else {
|
|
iconInfoPtr = new iconInfo[sliceNum];
|
|
}
|
|
for (uint8_t i = 0; i < sliceNum; i++) {
|
|
uint8_t m = sizeof(g_fixInfoArray) / sizeof(g_fixInfoArray[0]);
|
|
uint8_t j;
|
|
for (j = 0; j < m; j++) {
|
|
if (sliceId[i] == g_fixInfoArray[j].sliceId) {
|
|
iconInfoPtr[i].fixInfo = g_fixInfoArray[j];
|
|
break;
|
|
}
|
|
}
|
|
if (j == m) {
|
|
iconInfoPtr[i].fixInfo = g_fixInfoArray[i];
|
|
}
|
|
}
|
|
if (sliceNum == 4) {
|
|
sliceNum = 5;
|
|
iconInfoPtr[4].fixInfo = iconInfoPtr[0].fixInfo;
|
|
}
|
|
|
|
SetIntercept(true);
|
|
SetViewId(FLOAT_WINDOW_VIEWID);
|
|
SetStyle(STYLE_BACKGROUND_OPA, OPA_TRANSPARENT);
|
|
SetDirection(1);
|
|
SetPosition(0, 0);
|
|
SetWidth(Screen::GetInstance().GetWidth());
|
|
SetHeight(Screen::GetInstance().GetHeight());
|
|
SetOnDragListener(this);
|
|
SetOnClickListener(this);
|
|
SetOnRotateListener(this);
|
|
|
|
imageFloatWindow = new UIImageView();
|
|
imageFloatWindow->SetOnClickListener(this);
|
|
imageFloatWindow->SetTouchable(true);
|
|
imageFloatWindow->SetIntercept(true);
|
|
Add(imageFloatWindow);
|
|
imageFloatWindow->SetPosition(FLOATWINDOW_IMAGE_BG_X, FLOATWINDOW_IMAGE_BG_Y);
|
|
ImageInfo *bgImgInfo;
|
|
bgImgInfo = ImageCacheManager::GetInstance().LoadOneInMultiRes(IMG_MAIN_FLOATWINDOW_BG, FLOAT_WINDOW_BIN_PATH);
|
|
|
|
finalImgInfo = new ImageInfo();
|
|
finalImgInfo->cacheNode = nullptr;
|
|
finalImgInfo->header.width = bgImgInfo->header.width;
|
|
finalImgInfo->header.height = bgImgInfo->header.height;
|
|
finalImgInfo->header.colorMode = ARGB8888;
|
|
finalImgInfo->header.compressMode = COMPRESS_MODE_NONE;
|
|
finalImgInfo->dataSize = ALIGN_BYTE(finalImgInfo->header.width, BYTE_ALIGNMENT) * finalImgInfo->header.height *
|
|
DrawUtils::GetByteSizeByColorMode(ARGB8888);
|
|
finalImgInfo->data = reinterpret_cast<uint8_t *>(ImageCacheMalloc(*finalImgInfo));
|
|
uint8_t *non_const_data = const_cast<uint8_t *>(finalImgInfo->data);
|
|
for (uint32_t i = 0; i < finalImgInfo->dataSize; i += 4) {
|
|
non_const_data[i] = 0x96;
|
|
non_const_data[i + 1] = 0x97;
|
|
non_const_data[i + 2] = 0x97;
|
|
non_const_data[i + 3] = 0x0;
|
|
}
|
|
// memset(const_cast<uint8_t*>(finalImgInfo->data), (uint32_t)0x00ffffff, finalImgInfo->dataSize / 4);
|
|
finalImgInfo->phyAddr = finalImgInfo->data;
|
|
|
|
// clang-format off
|
|
Rect dstRect(0, 0, finalImgInfo->header.width - 1, finalImgInfo->header.height - 1);
|
|
bgDstBufferInfo.mode = ARGB8888;
|
|
bgDstBufferInfo.width = bgImgInfo->header.width;
|
|
bgDstBufferInfo.height = bgImgInfo->header.height;
|
|
bgDstBufferInfo.stride = ALIGN_BYTE(bgDstBufferInfo.width, BYTE_ALIGNMENT) * DrawUtils::GetByteSizeByColorMode(ARGB8888);
|
|
bgDstBufferInfo.phyAddr = const_cast<uint8_t *>(finalImgInfo->data);
|
|
bgDstBufferInfo.virAddr = const_cast<uint8_t *>(finalImgInfo->data);
|
|
bgDstBufferInfo.compressMode = COMPRESS_MODE_NONE;
|
|
bgDstBufferInfo.rect = dstRect;
|
|
bgDstBufferInfo.color = 0;
|
|
bgSrcBufferInfo.mode = (ColorMode)bgImgInfo->header.colorMode;
|
|
bgSrcBufferInfo.width = bgImgInfo->header.width;
|
|
bgSrcBufferInfo.height = bgImgInfo->header.height;
|
|
bgSrcBufferInfo.stride = ALIGN_BYTE(bgSrcBufferInfo.width, BYTE_ALIGNMENT) * DrawUtils::GetByteSizeByColorMode(bgSrcBufferInfo.mode);
|
|
bgSrcBufferInfo.phyAddr = const_cast<uint8_t *>(bgImgInfo->data);
|
|
bgSrcBufferInfo.virAddr = const_cast<uint8_t *>(bgImgInfo->data);
|
|
bgSrcBufferInfo.compressMode = bgImgInfo->header.compressMode;
|
|
Rect bgSrcRect(0, 0, bgSrcBufferInfo.width - 1, bgSrcBufferInfo.height - 1);
|
|
bgSrcBufferInfo.rect = bgSrcRect;
|
|
bgSrcBufferInfo.color = 0;
|
|
BlendOption opt1;
|
|
opt1.opacity = OPA_OPAQUE;
|
|
opt1.mode = BlendMode::BLEND_SRC_OVER;
|
|
// clang-format on
|
|
|
|
BaseGfxEngine::GetInstance()->Blit(bgDstBufferInfo, {0, 0}, bgSrcBufferInfo, bgSrcRect, opt1);
|
|
|
|
#if ENABLE_VGU_ENGINE
|
|
LiteMGfxEngine::GetInstance()->SyncHwDraw();
|
|
#endif
|
|
|
|
// clang-format off
|
|
arcCenterX = Screen::GetInstance().GetWidth() / 2;
|
|
arcCenterY = Screen::GetInstance().GetHeight() / 2;
|
|
arcOuterRedius = Screen::GetInstance().GetWidth() / 2 - 20;
|
|
angleIcon = CalculateIconAngle(arcOuterRedius, IMAGE_WINDOW_WIDTH / 2);
|
|
startAngle = acos(MATH_ABS((arcCenterY - FLOATWINDOW_IMAGE_BG_Y)) / (arcOuterRedius - IMAGE_WINDOW_WIDTH / 2)) * 180 / UI_PI;
|
|
endAngle = 180 + asin(MATH_ABS((arcCenterX - FLOATWINDOW_IMAGE_BG_X)) / (arcOuterRedius - IMAGE_WINDOW_WIDTH / 2)) * 180 / UI_PI;
|
|
angleReserve = (endAngle - startAngle - angleIcon) / (displayNum - 1);
|
|
// clang-format on
|
|
|
|
uint8_t cnt = sliceNum;
|
|
iconList.clear();
|
|
for (uint8_t i = 0; i < cnt; i++) {
|
|
iconList.push_back(i);
|
|
}
|
|
UpdateFuchuang(0, 0, false);
|
|
imageFloatWindow->SetSrc(finalImgInfo);
|
|
}
|
|
|
|
TjdUiAppFloatWindowBlend::~TjdUiAppFloatWindowBlend()
|
|
{
|
|
ClearFocus();
|
|
ClearBackgroundBlur();
|
|
|
|
if (finalImgInfo) {
|
|
ImageCacheFree(*finalImgInfo);
|
|
delete finalImgInfo;
|
|
finalImgInfo = nullptr;
|
|
}
|
|
if (iconInfoPtr) {
|
|
delete[] iconInfoPtr;
|
|
iconInfoPtr = nullptr;
|
|
}
|
|
}
|
|
|
|
void TjdUiAppFloatWindowBlend::UpdateFuchuang(int16_t diffy, double angle, bool isUsedAngle)
|
|
{
|
|
double angleDiff;
|
|
if (isUsedAngle) {
|
|
angleDiff = angle;
|
|
const double EPSILON = 1e-6;
|
|
if (angleDiff < EPSILON) {
|
|
diffy = -1;
|
|
} else {
|
|
diffy = 1;
|
|
}
|
|
} else {
|
|
angleDiff = diffy * 0.4;
|
|
}
|
|
|
|
if (LiteMGfxEngine::GetInstance()->IsAsyncModeEnabled()) {
|
|
LiteMGfxEngine::GetInstance()->Flush(Rect(0, 0, 0, 0));
|
|
}
|
|
|
|
Rect bgSrcRect(0, 0, bgSrcBufferInfo.width - 1, bgSrcBufferInfo.height - 1);
|
|
BlendOption opt1;
|
|
opt1.opacity = OPA_OPAQUE;
|
|
opt1.mode = BlendMode::BLEND_SRC_OVER;
|
|
BaseGfxEngine::GetInstance()->Blit(bgDstBufferInfo, {0, 0}, bgSrcBufferInfo, bgSrcRect, opt1);
|
|
|
|
int16_t IconX, IconY;
|
|
double x_temp, y_temp;
|
|
int16_t iconContainerOffsetX;
|
|
int16_t iconContainerOffsetY;
|
|
iconContainerOffsetX = FLOATWINDOW_IMAGE_BG_X - arcCenterX;
|
|
iconContainerOffsetY = FLOATWINDOW_IMAGE_BG_Y - arcCenterY;
|
|
if (MATH_ABS(angleDiff) > angleReserve) {
|
|
if (angleDiff < 0) {
|
|
angleDiff = -angleReserve + 10;
|
|
} else {
|
|
angleDiff = angleReserve - 10;
|
|
}
|
|
}
|
|
|
|
for (uint8_t elem : iconList) {
|
|
BufferInfo logoBufferInfo;
|
|
ImageInfo *imgInfo = ImageCacheManager::GetInstance().LoadOneInMultiRes(iconInfoPtr[elem].fixInfo.imageId,
|
|
FLOAT_WINDOW_BIN_PATH);
|
|
logoBufferInfo.mode = (ColorMode)imgInfo->header.colorMode;
|
|
logoBufferInfo.width = imgInfo->header.width;
|
|
logoBufferInfo.height = imgInfo->header.height;
|
|
uint16_t fgWidth = imgInfo->header.width;
|
|
uint16_t fgHeight = imgInfo->header.height;
|
|
logoBufferInfo.stride =
|
|
ALIGN_BYTE(logoBufferInfo.width, BYTE_ALIGNMENT) * DrawUtils::GetByteSizeByColorMode(logoBufferInfo.mode);
|
|
logoBufferInfo.phyAddr = const_cast<uint8_t *>(imgInfo->data);
|
|
logoBufferInfo.virAddr = const_cast<uint8_t *>(imgInfo->data);
|
|
logoBufferInfo.compressMode = imgInfo->header.compressMode;
|
|
Rect logoBufferInfoRect(0, 0, logoBufferInfo.width - 1, logoBufferInfo.height - 1);
|
|
BlendOption opt2;
|
|
opt2.opacity = OPA_OPAQUE;
|
|
opt2.mode = BlendMode::BLEND_SRC_ATOP;
|
|
Rect srcInDstRect;
|
|
//
|
|
if (isInit == 0) {
|
|
iconInfoPtr[elem].angle = startAngle + angleIcon / 2 + angleReserve * elem;
|
|
} else {
|
|
iconInfoPtr[elem].angle += angleDiff;
|
|
}
|
|
|
|
if (iconInfoPtr[elem].angle < startAngle - angleIcon / 2 ||
|
|
iconInfoPtr[elem].angle > endAngle + angleIcon / 2) {
|
|
// continue;
|
|
}
|
|
CalculatePointOnCircle(arcOuterRedius - IMAGE_WINDOW_WIDTH / 2, iconInfoPtr[elem].angle, x_temp, y_temp, 1);
|
|
IconX = (int16_t)x_temp - IMAGE_ICON_WIDTH / 2 - FLOATWINDOW_IMAGE_BG_X;
|
|
IconY = (int16_t)y_temp - IMAGE_ICON_WIDTH / 2 - FLOATWINDOW_IMAGE_BG_Y;
|
|
//如果图标完全超出背景图范围
|
|
if (IconX < -IMAGE_ICON_WIDTH || IconY < -IMAGE_ICON_WIDTH) {
|
|
continue;
|
|
}
|
|
uint16_t real_w, real_h;
|
|
real_w = logoBufferInfo.width;
|
|
real_h = logoBufferInfo.height;
|
|
logoBufferInfo.rect.SetX(0);
|
|
logoBufferInfo.rect.SetY(0);
|
|
if (IconX < 0) {
|
|
real_w = real_w + IconX;
|
|
logoBufferInfo.rect.SetX(MATH_ABS(IconX));
|
|
IconX = 0;
|
|
}
|
|
if (IconY < 0) {
|
|
real_h = real_h + IconY;
|
|
logoBufferInfo.rect.SetY(MATH_ABS(IconY));
|
|
IconY = 0;
|
|
}
|
|
if (real_w == 0 || real_h == 0) {
|
|
continue;
|
|
}
|
|
logoBufferInfo.rect.SetWidth(real_w);
|
|
logoBufferInfo.rect.SetHeight(real_h);
|
|
|
|
uint16_t absX = x_temp - IMAGE_ICON_WIDTH / 2;
|
|
uint16_t absY = y_temp - IMAGE_ICON_WIDTH / 2;
|
|
iconInfoPtr[elem].area.SetRect(absX, (uint16_t)absY, (uint16_t)absX + IMAGE_ICON_WIDTH - 1,
|
|
(uint16_t)absY + IMAGE_ICON_WIDTH - 1);
|
|
srcInDstRect.SetX(IconX);
|
|
srcInDstRect.SetY(IconY);
|
|
srcInDstRect.SetWidth(real_w);
|
|
srcInDstRect.SetHeight(real_h);
|
|
|
|
BaseGfxEngine::GetInstance()->Blit(bgDstBufferInfo, {0, 0}, logoBufferInfo, srcInDstRect, opt2);
|
|
}
|
|
isInit = 1;
|
|
#if ENABLE_VGU_ENGINE
|
|
LiteMGfxEngine::GetInstance()->SyncHwDraw();
|
|
#endif
|
|
imageFloatWindow->Invalidate();
|
|
#if 1
|
|
if (diffy < 0) {
|
|
if ((iconInfoPtr[iconList.front()].angle + angleIcon / 2) < startAngle) {
|
|
double angleLast = iconInfoPtr[iconList.back()].angle;
|
|
iconInfoPtr[iconList.front()].angle = angleLast + angleReserve;
|
|
iconList.splice(iconList.end(), iconList, iconList.begin());
|
|
if (needCycle_ == true) {
|
|
iconInfoPtr[iconList.back()].fixInfo = iconInfoPtr[iconList.front()].fixInfo;
|
|
}
|
|
}
|
|
} else if (diffy > 0) {
|
|
auto it = iconList.begin();
|
|
std::advance(it, displayNum - 1);
|
|
if ((iconInfoPtr[*it].angle + angleIcon / 2) > endAngle) {
|
|
double angleFirst = iconInfoPtr[iconList.front()].angle;
|
|
iconInfoPtr[iconList.back()].angle = angleFirst - angleReserve;
|
|
auto lastElementIt = std::prev(iconList.end());
|
|
iconList.splice(iconList.begin(), iconList, lastElementIt);
|
|
if (needCycle_ == true) {
|
|
it = iconList.begin();
|
|
std::advance(it, displayNum - 1);
|
|
iconInfoPtr[iconList.front()].fixInfo = iconInfoPtr[iconList.back()].fixInfo;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void TjdUiAppFloatWindowBlend::FloatWindowAnimatorCallback::Callback(OHOS::UIView *view)
|
|
{
|
|
if (instance_ == nullptr) {
|
|
return;
|
|
}
|
|
if (instance_->SlideOrAutoAlign_ == 1) {
|
|
curtTime_++;
|
|
if (curtTime_ <= dragTimes_) {
|
|
double f = CubicEaseOut1(startValueY_, endValueY_, curtTime_, dragTimes_);
|
|
instance_->UpdateFuchuang(0, f - previousValueY_, true);
|
|
previousValueY_ = f;
|
|
} else {
|
|
instance_->StopFloatWindowAnimator();
|
|
}
|
|
} else {
|
|
curtTime_++;
|
|
if (curtTime_ <= dragTimes_) {
|
|
bool needStopY = false;
|
|
if (startValueY__ != endValueY__) {
|
|
int16_t actY = easingFunc_(startValueY__, endValueY__, curtTime_, dragTimes_);
|
|
instance_->UpdateFuchuang(actY - previousValueY__, 0, false);
|
|
|
|
if (IsNeedReCalculateDragEnd()) {
|
|
double angle = instance_->FindCorrectIcon();
|
|
instance_->StartAutoAlignAnimator(angle);
|
|
}
|
|
previousValueY__ = actY;
|
|
} else {
|
|
needStopY = true;
|
|
}
|
|
if (needStopY) {
|
|
instance_->StopFloatWindowAnimator();
|
|
}
|
|
} else {
|
|
instance_->StopFloatWindowAnimator();
|
|
}
|
|
}
|
|
}
|
|
|
|
void TjdUiAppFloatWindowBlend::FloatWindowAnimatorCallback::OnStop(OHOS::UIView &view)
|
|
{
|
|
int16_t x = FLOATWINDOW_IMAGE_BG_X + FLOATWINDOW_IMAGE_BG_WIDTH - IMAGE_WINDOW_WIDTH / 2; // 218 + 228 - 38 =
|
|
// 408
|
|
int16_t y = FLOATWINDOW_IMAGE_BG_Y + IMAGE_WINDOW_WIDTH / 2; // 195 + 38 = 230
|
|
const Point point = {x, y};
|
|
int curImageId = 0;
|
|
for (uint8_t elem : instance_->iconList) {
|
|
if (iconInfoPtr[elem].area.IsContains(point)) {
|
|
instance_->lastImageId_ = iconInfoPtr[elem].fixInfo.imageId;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool TjdUiAppFloatWindowBlend::FloatWindowAnimatorCallback::IsNeedReCalculateDragEnd()
|
|
{
|
|
int16_t animationLess = 0;
|
|
animationLess = endValueY__ - previousValueY__;
|
|
if ((MATH_ABS(animationLess) > 10)) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
double TjdUiAppFloatWindowBlend::FloatWindowAnimatorCallback::CubicEaseOut1(double startPos, double endPos,
|
|
uint16_t curTime, uint16_t durationTime)
|
|
{
|
|
if (curTime < durationTime) {
|
|
float t = static_cast<float>(curTime) / durationTime;
|
|
float x = 1.0f - powf(1.0f - t, 3.0f); // 计算1 - (1 - t)^3
|
|
return startPos + x * (endPos - startPos);
|
|
}
|
|
return endPos;
|
|
}
|
|
|
|
void TjdUiAppFloatWindowBlend::StartSlideAnimator(int16_t dragDistanceY)
|
|
{
|
|
SlideOrAutoAlign_ = 0;
|
|
int16_t dragTimes = MATH_ABS(dragDistanceY) / DRAG_TIMES_COEFFICIENT;
|
|
if (dragTimes < MIN_DRAG_TIMES) {
|
|
dragTimes = MIN_DRAG_TIMES;
|
|
}
|
|
floatWindowAnimatorCallback_.ResetCallback();
|
|
floatWindowAnimatorCallback_.SetDragStartValue(static_cast<int16_t>(0));
|
|
floatWindowAnimatorCallback_.SetDragEndValue(dragDistanceY);
|
|
floatWindowAnimatorCallback_.SetDragTimes(dragTimes * DRAG_ACC_FACTOR / GetDragACCLevel());
|
|
floatWindowAnimator_.Start();
|
|
}
|
|
void TjdUiAppFloatWindowBlend::StartAutoAlignAnimator(double diffAngle)
|
|
{
|
|
SlideOrAutoAlign_ = 1;
|
|
int16_t dragTimes = MATH_ABS(diffAngle);
|
|
if (dragTimes < MIN_DRAG_TIMES) {
|
|
dragTimes = MIN_DRAG_TIMES;
|
|
}
|
|
floatWindowAnimatorCallback_.ResetCallback();
|
|
floatWindowAnimatorCallback_.SetDragStartValue(static_cast<double>(0));
|
|
floatWindowAnimatorCallback_.SetDragEndValue(diffAngle);
|
|
floatWindowAnimatorCallback_.SetDragTimes(dragTimes);
|
|
floatWindowAnimator_.Start();
|
|
}
|
|
|
|
void TjdUiAppFloatWindowBlend::StopFloatWindowAnimator() { floatWindowAnimator_.Stop(); }
|
|
|
|
} // namespace TJD
|