/*********************************************************************
*                    SEGGER Microcontroller GmbH                     *
*        Solutions for real time microcontroller applications        *
**********************************************************************
*                                                                    *
*        (c) 1996 - 2020  SEGGER Microcontroller GmbH                *
*                                                                    *
*        Internet: www.segger.com    Support:  support@segger.com    *
*                                                                    *
**********************************************************************

** emWin V6.10 - Graphical user interface for embedded applications **
emWin is protected by international copyright laws.   Knowledge of the
source code may not be used to write a similar product.  This file may
only  be used  in accordance  with  a license  and should  not be  re-
distributed in any way. We appreciate your understanding and fairness.
----------------------------------------------------------------------
File        : GUI_Tutorial_Animation.c
Purpose     : Code of the wiki tutorial on animations in emWin.
Requirements: WindowManager - (x)
              MemoryDevices - ( )
              AntiAliasing  - ( )
              VNC-Server    - ( )
              PNG-Library   - ( )
              TrueTypeFonts - ( )
---------------------------END-OF-HEADER------------------------------
*/

#include "DIALOG.h"

/*********************************************************************
*
*       Types
*
**********************************************************************
*/
//
// Custom struct with data necessary for the animation
//
typedef struct {
  WM_HWIN hWin;
  int     xPosStart;
  int     xPosDest;
} ANIM_DATA;

/*********************************************************************
*
*       Defines
*
**********************************************************************
*/
#define ANIM_PERIOD   500

/*********************************************************************
*
*       Static data
*
**********************************************************************
*/
static WM_HWIN _hWindow;

/*********************************************************************
*
*       Static code
*
**********************************************************************
*/
/*********************************************************************
*
*       _OnDelete
*/
static void _OnDelete(void * pVoid) {
  U8 * pMovedIn;
  
  //
  // Get custom void pointer. Toggle the flag that saves if the window is moved in.
  //
  pMovedIn = (U8 *)pVoid;
  if(pMovedIn) {
    *pMovedIn ^= 1;
  }
}

/*********************************************************************
*
*       _AnimMoveWindow
*/
static void _AnimMoveWindow(GUI_ANIM_INFO * pInfo, void * pVoid) {
  ANIM_DATA * pData;
  int         xPos;
  int         yPos;

  pData = (ANIM_DATA *)pVoid;
  //
  // Calculate new window position with the ANIM_DATA struct
  //
  xPos = pData->xPosStart + ((pData->xPosDest - pData->xPosStart) * pInfo->Pos) / GUI_ANIM_RANGE;
  //
  // Get current y-position since it won't be changed with the animation.
  //
  yPos = WM_GetWindowOrgY(pData->hWin);
  //
  // Move window to new position
  //
  WM_MoveTo(pData->hWin, xPos, yPos);
}

/*********************************************************************
*
*       _cbWindow
*/
static void _cbWindow(WM_MESSAGE * pMsg) {
  switch (pMsg->MsgId) {
  case WM_PAINT:
    GUI_SetBkColor(GUI_RED);
    GUI_Clear();
    break;
  default:
    WM_DefaultProc(pMsg);
    break;
  }
}

/*********************************************************************
*
*       _cbBk
*/
static void _cbBk(WM_MESSAGE * pMsg) {
  int                    Id, NCode;
  static GUI_ANIM_HANDLE hAnim;
  static ANIM_DATA       Data;
  WM_HWIN                hItem;
  static WM_HWIN         hWin;
  static U8              MovedIn;

  switch(pMsg->MsgId) {
  case WM_SET_CALLBACK:
    //
    // Create a window that will be moved using an animation.
    //
    hWin = WM_CreateWindowAsChild(-50, 50, 50, 150, WM_HBKWIN, WM_CF_SHOW, _cbWindow, 0);
    //
    // Create button to trigger the animation.
    //
    hItem = BUTTON_CreateEx(10, 10, 80, 20, WM_HBKWIN, WM_CF_SHOW, 0, GUI_ID_BUTTON0);
    BUTTON_SetText(hItem, "Move in/out");
    break;
  case WM_PAINT:
    GUI_SetBkColor(GUI_WHITE);
    GUI_Clear();
    break;
  case WM_NOTIFY_PARENT:
    Id    = WM_GetId(pMsg->hWinSrc);
    NCode = pMsg->Data.v;
    switch(Id) {
    case GUI_ID_BUTTON0:
      switch (NCode) {
      case WM_NOTIFICATION_RELEASED:
        //
        // Check if animation is already running.
        //
        if (GUI_ANIM_IsRunning(hAnim) == 0) {
          //
          // Set up animation data.
          //
          Data.hWin      = hWin;                   // Handle of window to be moved.
          Data.xPosStart = WM_GetWindowOrgX(hWin); // Current x-position.
          Data.xPosDest  = (MovedIn) ? -50 : 10;   // Destination x-position.
          //
          // Create animation handle.
          //
          hAnim = GUI_ANIM_Create(ANIM_PERIOD, 25, &MovedIn, NULL);
          //
          // Add animation item.
          //
          GUI_ANIM_AddItem(hAnim, 0, ANIM_PERIOD, ANIM_ACCELDECEL, &Data, _AnimMoveWindow);
          //
          // Start animation for one time.
          //
          GUI_ANIM_StartEx(hAnim, 1, _OnDelete);
        }
        break;
      }
      break;
    }
    break;
  default:
    WM_DefaultProc(pMsg);
  }
}

/*********************************************************************
*
*       Public code
*
**********************************************************************
*/
/*********************************************************************
*
*       MainTask
*/
void MainTask(void) {
  //
  // Init emWin.
  //
  GUI_Init();
  //
  // Enable multi-buffering to avoid flickering during the animation.
  //
  WM_MULTIBUF_Enable(1);
  //
  // Set custom callback routine to background window.
  //
  WM_SetCallback(WM_HBKWIN, _cbBk);

  while (1) {
    GUI_Delay(100);
  }
}

/*************************** End of file ****************************/