Snapping time in a window motion

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • Snapping time in a window motion

      Hello,

      I'm working on a custom widget that would use motion (sort of horizontal listwheel or swipelist).

      And I'd like to reduce time for snapping the items to the snap position just like listwheel widget does .

      As far as I understand there is a variable Period in WM_MOTION_INFO structure that controls motion time depending on the start moving force by a PID.

      When I start moving the variable Period need to be a quite big value for a long time motion.

      When I want to stop my widget by a PID the same variable Period also makes a long snapping time before final stop.

      I tried to measure the speed in WM_TIMER and change Period value in WM_MOTION_MOVE when speed is quite low but it is not working.

      Apparently Period value need to be changed only in WM_MOTION_INIT.

      Here is my sample code:

      C Source Code

      1. #include "DIALOG.h"
      2. #include "stdio.h"
      3. WM_HWIN hWin;
      4. LISTWHEEL_Handle hLstwhl;
      5. int i, xPos;
      6. char str[2];
      7. // Callback for the desktop window
      8. void _cbBk(WM_MESSAGE * pMsg) {
      9. int i;
      10. GUI_RECT Rect = { 0, 150, 30, 451 };
      11. switch (pMsg->MsgId) {
      12. case WM_PAINT:
      13. GUI_SetBkColor(GUI_DARKGRAY);
      14. GUI_Clear();
      15. // Horizontal listwheel text
      16. GUI_SetColor(GUI_WHITE);
      17. GUI_SetFont(GUI_FONT_20_ASCII);
      18. GUI_DispStringHCenterAt("Custom horizontal listwheel (wrap off)", 200, 10);
      19. GUI_SetFont(GUI_FONT_16_ASCII);
      20. GUI_DispStringHCenterAt("Snap points", 200, 30);
      21. // Draw snap markers for horizontal listwheel
      22. for (i = 60; i <= 360; i += 50)
      23. GUI_DrawVLine(i, 52, 57);
      24. // Draw arrow
      25. GUI_DrawLine(365, 85, 375, 80);
      26. GUI_DrawLine(365, 85, 375, 90);
      27. GUI_DrawHLine(85, 365, 400);
      28. // Some notes about the problem
      29. GUI_DispStringAt("When accelerating it to long time rotation by a PID and then stop,", 410, 77);
      30. GUI_DispStringAt("then items are snapping with the same period as of they are starting rotation (quite slow)", 410, 95);
      31. // Listwheel by EmWin text
      32. GUI_SetFont(GUI_FONT_20_ASCII);
      33. GUI_DispStringInRectEx("Listwheel by EmWin", &Rect, GUI_TA_HCENTER | GUI_TA_BOTTOM, 18, GUI_ROTATE_CCW);
      34. Rect.x0 = 32;
      35. Rect.x1 = 47;
      36. GUI_SetFont(GUI_FONT_16_ASCII);
      37. GUI_DispStringInRectEx("Snap points", &Rect, GUI_TA_HCENTER | GUI_TA_BOTTOM, 11, GUI_ROTATE_CCW);
      38. // Draw snap markers
      39. for (i = 150; i <= 450; i += 50)
      40. GUI_DrawHLine(i, 52, 57);
      41. // Draw arrow
      42. GUI_DrawLine(115, 300, 125, 295);
      43. GUI_DrawLine(115, 300, 125, 305);
      44. GUI_DrawHLine(300, 115, 150);
      45. // Some notes about my goal as listwheel by EmWin does
      46. GUI_DispStringAt("When accelerating it to long time rotation by a PID and then stop,", 160, 292);
      47. GUI_DispStringAt("then items are snapping quite fast", 160, 310);
      48. break;
      49. default:
      50. WM_DefaultProc(pMsg);
      51. break;
      52. }
      53. }
      54. // Callback for the horizontal listwheel
      55. void _cbWin(WM_MESSAGE * pMsg) {
      56. GUI_RECT Rect;
      57. int i;
      58. char str[10];
      59. WM_MOTION_INFO* pInfo;
      60. switch (pMsg->MsgId) {
      61. case WM_MOTION:
      62. pInfo = (WM_MOTION_INFO*)pMsg->Data.p;
      63. switch (pInfo->Cmd) {
      64. case WM_MOTION_INIT:
      65. // Start motion, set snap, overlap and period values
      66. pInfo->Flags = WM_CF_MOTION_X | WM_MOTION_MANAGE_BY_WINDOW;
      67. pInfo->SnapX = 50;
      68. pInfo->Overlap = 25;
      69. pInfo->Period = 1000;
      70. break;
      71. case WM_MOTION_MOVE:
      72. // Some code when motion is acting (limiting and stopping the motion)
      73. xPos += pInfo->dx;
      74. if (pInfo->IsDragging)
      75. pInfo->IsOutside = (xPos < -4720) | (xPos > 0);
      76. if (xPos < -4720) {
      77. xPos = -4720;
      78. pInfo->StopMotion = pInfo->IsDragging ^ 1;
      79. }
      80. if (xPos > 20) {
      81. xPos = 20;
      82. pInfo->StopMotion = pInfo->IsDragging ^ 1;
      83. }
      84. // Call WM_PAINT
      85. WM_Invalidate(pMsg->hWin);
      86. break;
      87. case WM_MOTION_GETPOS:
      88. pInfo->xPos = xPos;
      89. break;
      90. }
      91. break;
      92. case WM_PAINT:
      93. // Draw horizontal listwheel with 100 items depending on motion position
      94. GUI_SetBkColor(GUI_RED);
      95. GUI_Clear();
      96. Rect.x0 = xPos;
      97. Rect.x1 = xPos + 50;
      98. Rect.y0 = 0;
      99. Rect.y1 = 49;
      100. GUI_SetColor(GUI_WHITE);
      101. GUI_SetFont(GUI_FONT_20_ASCII);
      102. for (i = 1; i <= 100; i++) {
      103. GUI_DrawRectEx(&Rect);
      104. sprintf(str, "%d", i);
      105. GUI_DispStringInRect(str, &Rect, GUI_TA_HCENTER | GUI_TA_VCENTER);
      106. Rect.x0 += 50;
      107. Rect.x1 += 50;
      108. }
      109. break;
      110. default:
      111. WM_DefaultProc(pMsg);
      112. break;
      113. }
      114. }
      115. // Some additional draw on the listwheel items
      116. static int _LISTWHEEL_CustomDraw(const WIDGET_ITEM_DRAW_INFO* pDrawItemInfo) {
      117. switch (pDrawItemInfo->Cmd) {
      118. case WIDGET_ITEM_DRAW:
      119. LISTWHEEL_OwnerDraw(pDrawItemInfo);
      120. GUI_SetColor(GUI_WHITE);
      121. GUI_DrawRect(pDrawItemInfo->x0, pDrawItemInfo->y0, pDrawItemInfo->x1, pDrawItemInfo->y1 + 1);
      122. break;
      123. default:
      124. return LISTWHEEL_OwnerDraw(pDrawItemInfo);
      125. break;
      126. }
      127. return 0;
      128. }
      129. void MainTask(void) {
      130. GUI_Init();
      131. WM_MULTIBUF_Enable(1);
      132. // Set callback for the desktop window
      133. WM_SetCallback(WM_HBKWIN, _cbBk);
      134. WM_MOTION_Enable(1);
      135. // Create a "horizontal listwheel", set callback
      136. hWin = WM_CreateWindowAsChild(60, 60, 301, 50, WM_HBKWIN, WM_CF_SHOW, _cbWin, 0);
      137. // Create a listwheel by EmWin, set some parameters
      138. hLstwhl = LISTWHEEL_CreateEx(60, 150, 50, 301, WM_HBKWIN, WM_CF_SHOW, 0, GUI_ID_LISTWHEEL0, NULL);
      139. LISTWHEEL_SetLineHeight(hLstwhl, 50);
      140. LISTWHEEL_SetFont(hLstwhl, GUI_FONT_20_ASCII);
      141. LISTWHEEL_SetTextAlign(hLstwhl, GUI_TA_HCENTER | GUI_TA_VCENTER);
      142. LISTWHEEL_SetTextColor(hLstwhl, LISTWHEEL_CI_UNSEL, GUI_WHITE);
      143. LISTWHEEL_SetTextColor(hLstwhl, LISTWHEEL_CI_SEL, GUI_WHITE);
      144. LISTWHEEL_SetBkColor(hLstwhl, LISTWHEEL_CI_UNSEL, GUI_RED);
      145. LISTWHEEL_SetBkColor(hLstwhl, LISTWHEEL_CI_SEL, GUI_RED);
      146. LISTWHEEL_SetOwnerDraw(hLstwhl, _LISTWHEEL_CustomDraw);
      147. // Set 100 items
      148. for (i = 1; i <= 100; i++) {
      149. sprintf(str, "%d", i);
      150. LISTWHEEL_AddString(hLstwhl, str);
      151. }
      152. while(1) {
      153. GUI_Delay(50);
      154. }
      155. }
      Display All
      What could be done to get it right?

      Thank you.

      Alex.
    • Hello, Florian,

      thanks for your answer. I'll try to explain better.

      As I see the variable Period also has an impact on the total moving time if we're starting a moving operation by a PID quite fast.

      So if we reduce Period value then it takes less time to stop (and therefore to snap) when we touch moving window by a PID with a fast click/release without capture.

      But then the total moving time is also declining if we allow it "go the whole way" without touch.

      So the problem is how to get a long moving time without touch and at the same time how to get a quick stop when we do fast click/release? Just like this is done in some way in LISTWHEEL widget.

      Alex.
    • Hi Alex,

      I don't think it'll be easy to implement the LISTWHEEL's behavior into your custom widget. When the LISTWHEEL was made, there was no motion support but only timers (ancient times...).
      Also, as you already said, you can only set the Period in WM_MOTION_INIT, not after the init.

      Best regards,

      Florian