/**************************************************************//*! * * Change the active screen * ******************************************************************/ static void D4D_ChangeScreen(D4D_SCREEN* pNewScreen, D4D_SCREEN* pOldScreen) { D4D_SCREEN_DATA* pData; D4D_MESSAGE tmp_msg; if(pNewScreen == NULL) return; if(pOldScreen == pNewScreen) return; tmp_msg.pScreen = pOldScreen; if(pOldScreen != NULL) { D4D_SetObjectFlags(pOldScreen->pData->focusedObject, D4D_OBJECT_F_REDRAWSTATE, D4D_FALSE); tmp_msg.nMsgId = D4D_MSG_KILLFOCUS; tmp_msg.pObject = pOldScreen->pData->focusedObject; D4D_SendMessage(&tmp_msg); // Draw NC screen area as an inactivate D4D_DrawScreenNC(pOldScreen, D4D_FALSE); // call de-activate event if(pOldScreen->OnDeactivate != NULL) pOldScreen->OnDeactivate(); } // invalidate the new screen (global complete redraw, not individual objects) D4D_InvalidateScreen(pNewScreen, D4D_TRUE); // if this is the first time activating pData = pNewScreen->pData; // Init the screen D4D_InitScreen(pNewScreen); D4D_SetObjectFlags(pData->focusedObject, D4D_OBJECT_F_REDRAWSTATE, D4D_FALSE); // Send to the object Focus message tmp_msg.pScreen = pNewScreen; tmp_msg.nMsgId = D4D_MSG_SETFOCUS; tmp_msg.pObject = pData->focusedObject; D4D_SendMessage(&tmp_msg); // inform the screen it has been activated if(pNewScreen->OnActivate) pNewScreen->OnActivate(); D4D_ClearKeysBuffer(); #ifdef D4D_LLD_TCH d4d_LastTouchedObj = NULL; #endif // finish all action for previous screen D4D_MouseChangedScreen(); }
/**************************************************************//*! * * Redraw all objects that need it on given screen * ******************************************************************/ static void D4D_RedrawScreenObject(D4D_OBJECT* pObject, D4D_BOOL complete) { D4D_MESSAGE msg; D4D_OBJECT_FLAGS flags = pObject->pData->flags; pObject->pData->flags &= ~(D4D_OBJECT_F_REDRAW | D4D_OBJECT_F_REDRAWC | D4D_OBJECT_F_REDRAWSTATE); if(!(flags & D4D_OBJECT_F_VISIBLE)) return; msg.pScreen = pObject->pData->pScreen; msg.pObject = pObject; msg.prm.draw = 0; if(complete || (flags & (D4D_OBJECT_F_REDRAW | D4D_OBJECT_F_REDRAWC | D4D_OBJECT_F_REDRAWSTATE))) /* object does need to redraw */ { /* forced complete redraw of all objects or object wants to be completely redrawn*/ if(complete || (flags & D4D_OBJECT_F_REDRAWC)) msg.prm.draw |= D4D_OBJECT_DRAWFLAGS_COMPLETE; /* notify object that state of object has been changed (focus, capture etc)*/ if(flags & D4D_OBJECT_F_REDRAWSTATE) msg.prm.draw |= D4D_OBJECT_DRAWFLAGS_STATE; // draw special? if((pObject == msg.pScreen->pData->focusedObject) && (pObject->pData->flags & D4D_OBJECT_F_TABSTOP)) { msg.prm.draw |= D4D_OBJECT_DRAWFLAGS_FOCUSED; if(pObject == d4d_pKeysCapturer) msg.prm.draw |= D4D_OBJECT_DRAWFLAGS_CAPTURING; } // will draw now // send the DRAW message msg.nMsgId = D4D_MSG_DRAW; D4D_SendMessage(&msg); // send the DRAWDONE message msg.nMsgId = D4D_MSG_DRAWDONE; D4D_SendMessage(&msg); } if(pObject->pRelations) { D4D_OBJECT** pChild = (D4D_OBJECT**)&(pObject->pRelations[D4D_OBJECT_USR_DATA_CHILD_IX]); while(*pChild) { D4D_RedrawScreenObject(*pChild, complete); pChild++; } } }
/**************************************************************************/ /*! * @brief The function set the obejct focus to new object * @param pScreen - the pointer to screen * @param pObject - the pointer to object that should be focused * @return None * @note In case that there is no other issue (obejct exists, visible, enable ...) the focus is changed to given one *******************************************************************************/ void D4D_FocusSet(D4D_SCREEN* pScreen, D4D_OBJECT_PTR pObject) { D4D_SCREEN_DATA* pData = pScreen->pData; D4D_OBJECT* pFocusedObj = pData->focusedObject; D4D_OBJECT* pNewFocus; if(pScreen == NULL) return; // check if object is really item of the current screen pNewFocus = D4D_FindObject(pScreen, pObject); if(pNewFocus == NULL) return; if(pNewFocus == pFocusedObj) // is selected object same as focused? return; if((pNewFocus->pData->flags & (D4D_OBJECT_F_TABSTOP | D4D_OBJECT_F_ENABLED)) != (D4D_OBJECT_F_TABSTOP | D4D_OBJECT_F_ENABLED)) // is this object selectable? return; if(!D4D_IsEnabled(pNewFocus)) return; // invalidate object which is loosing focus D4D_SetObjectFlags(pFocusedObj, D4D_OBJECT_F_REDRAWSTATE, D4D_FALSE); // invalidate object which is getting focus D4D_SetObjectFlags(pNewFocus, D4D_OBJECT_F_REDRAWSTATE, D4D_FALSE); // move the focus pData->focusedObject = pNewFocus; // prepare message d4d_msg.pScreen = pScreen; d4d_msg.nMsgId = D4D_MSG_KILLFOCUS; d4d_msg.pObject = pFocusedObj; D4D_SendMessage(&d4d_msg); // prepare message d4d_msg.pScreen = pScreen; d4d_msg.nMsgId = D4D_MSG_SETFOCUS; d4d_msg.pObject = pNewFocus; D4D_SendMessage(&d4d_msg); }
/**************************************************************************/ /*! * @brief Function switch on capturing the keys to objects * @param pObj - pointer to the object. if the parameter is handled as NULL, * the function switch off the capturing the keys to object. * @return none. * @note This function sets the object to the capture keys state. In this state the object obtains all the * keys inputs including system navigation keys (escape, up, and down). In this state the object is using * capture colors from a color scheme. To switch off from this state the active screen has to be changed or * this function has to be called with the input parameter set to NULL. *******************************************************************************/ void D4D_CaptureKeys(D4D_OBJECT_PTR pObj) { // NOTE: we need to send message, but we may just be in the middle of // message processing (very likely). This may cause problem with // the global d4d_msg object as we are changing it... // We better use the temporary memory to instanitate the message D4D_MESSAGE* pMsg = (D4D_MESSAGE*) d4d_scratchPad; if(d4d_pKeysCapturer == pObj) return; pMsg->pScreen = D4D_GetActiveScreen(); if(d4d_pKeysCapturer) { D4D_SetObjectFlags(d4d_pKeysCapturer, D4D_OBJECT_F_REDRAWSTATE, D4D_FALSE); pMsg->nMsgId = D4D_MSG_KILLCAPTURE; pMsg->pObject = d4d_pKeysCapturer; D4D_SendMessage(pMsg); d4d_pKeysCapturer = NULL; } if(pObj != NULL) { if((pObj->pData->flags & (D4D_OBJECT_F_VISIBLE | D4D_OBJECT_F_ENABLED | D4D_OBJECT_F_TABSTOP)) == (D4D_OBJECT_F_VISIBLE | D4D_OBJECT_F_ENABLED | D4D_OBJECT_F_TABSTOP)) { if(D4D_IsEnabled((D4D_OBJECT*)pObj)) { D4D_FocusSet(D4D_GetActiveScreen(), pObj); d4d_pKeysCapturer = (D4D_OBJECT*) pObj; D4D_SetObjectFlags(d4d_pKeysCapturer, D4D_OBJECT_F_REDRAWSTATE, D4D_FALSE); pMsg->nMsgId = D4D_MSG_SETCAPTURE; pMsg->pObject = d4d_pKeysCapturer; D4D_SendMessage(pMsg); } } } }
/**************************************************************//*! * * Redraw the screen based on redraw flags * ******************************************************************/ void D4D_RedrawScreen(D4D_SCREEN* pScreen) { D4D_SCREEN_DATA data = *pScreen->pData; D4D_OBJECT** pObj; pScreen->pData->flags &= ~(D4D_SCR_FINT_REDRAWC | D4D_SCR_FINT_CHECKOBJECTS); // prepare message d4d_msg.pScreen = pScreen; if(data.flags & (D4D_SCR_FINT_CHECKOBJECTS | D4D_SCR_FINT_REDRAWC)) D4D_LLD_LCD.D4DLCD_FlushBuffer(D4DLCD_FLSH_SCR_START); // redraw screen non client area if necessary if(data.flags & D4D_SCR_FINT_REDRAWC) { d4d_msg.pObject = NULL; d4d_msg.nMsgId = D4D_MSG_DRAW; D4D_SendMessage(&d4d_msg); D4D_DrawScreenNC(pScreen, D4D_TRUE); } if(data.flags & D4D_SCR_FINT_CHECKOBJECTS) { // redraw objects pObj = (D4D_OBJECT**)pScreen->pObjects; // Go through the all top level objects while(*pObj != NULL) { // redraw all top level objects includes it children D4D_RedrawScreenObject(*pObj, data.flags & D4D_SCR_FINT_REDRAWC); pObj++; } d4d_msg.pObject = NULL; d4d_msg.nMsgId = D4D_MSG_DRAWDONE; D4D_SendMessage(&d4d_msg); } if(data.flags & (D4D_SCR_FINT_CHECKOBJECTS | D4D_SCR_FINT_REDRAWC)) D4D_LLD_LCD.D4DLCD_FlushBuffer(D4DLCD_FLSH_SCR_END); }
/**************************************************************//*! * * helper to invoke OBJECT's message handler * * all information need to be already prepared in d4d_msg * ******************************************************************/ void D4D_SendMessageBack(D4D_MESSAGE* pMsg) { D4D_OBJECT* pObject = pMsg->pObject; if(pObject->pRelations) { D4D_OBJECT* pParentObj = (D4D_OBJECT*)pObject->pRelations[D4D_OBJECT_USR_DATA_PARENT_IX]; if(pParentObj) { pMsg->pObject = pParentObj; D4D_SendMessageBack(pMsg); } } pMsg->pObject = pObject; D4D_SendMessage(pMsg); }
/**************************************************************//*! * * Find the touched object function * ******************************************************************/ static D4D_BOOL D4D_FindTouchedObject(D4D_OBJECT* pObject, D4D_POINT point) { D4D_BOOL validCoor; if((pObject->pData->flags & (D4D_OBJECT_F_VISIBLE | D4D_OBJECT_F_ENABLED | D4D_OBJECT_F_TOUCHENABLE)) != (D4D_OBJECT_F_VISIBLE | D4D_OBJECT_F_ENABLED | D4D_OBJECT_F_TOUCHENABLE)) return D4D_FALSE; if(pObject->pObjFunc->CheckCoordinates == NULL) validCoor = D4D_ObjectCheckCoordinates(pObject, D4D_GetScreenToClientPoint(pObject, &point)); else // Check the coordination if its valid validCoor = pObject->pObjFunc->CheckCoordinates(pObject, D4D_GetScreenToClientPoint(pObject, &point)); // if the coordinations are valid or autorepeat is enabled if(validCoor) { // This is new touch d4d_LastTouchedObj = pObject; d4d_msg.pObject = pObject; d4d_msg.nMsgId = D4D_MSG_TOUCHED; // send the D4D_MSG_TOUCHED message D4D_SendMessage(&d4d_msg); if(pObject->pRelations) { D4D_OBJECT** pChildren = (D4D_OBJECT**)&pObject->pRelations[D4D_OBJECT_USR_DATA_CHILD_IX]; while(*pChildren && !D4D_FindTouchedObject(*pChildren, point)) { pChildren++; } } return D4D_TRUE; } return D4D_FALSE; }
/**************************************************************//*! * * Handle the TouchScreen (part of main poll call) * ******************************************************************/ static void D4D_HandleTouchScreen(D4D_SCREEN* pScreen) { D4D_SCREEN_DATA* pData = pScreen->pData; D4D_BOOL validCoor; D4D_OBJECT** pObjects; //D4D_POINT tmpClientTouch = D4D_GetScreenToClientPoint(pScreen, &d4d_TouchScreenCoor); // prepare message d4d_msg.pScreen = pScreen; d4d_msg.prm.draw = 0; //1. Check if this is new touch or not if(d4d_TouchScreen_Status & D4D_TCHSCR_STATUS_NEWTOUCH) { // new touch operation d4d_TouchScreen_Status &= ~(D4D_TCHSCR_STATUS_NEWTOUCH | D4D_TCHSCR_STATUS_LOSTTOUCH); // Handle Screen events if(pData->flags & D4D_SCR_FINT_TOUCHENABLE) { if(pScreen->flags & D4D_SCR_F_EXIT) { if(D4D_ScrCheckExitBtnCoor(pScreen, &d4d_TouchScreenCoor)) { D4D_EscapeScreen(); d4d_TouchScreen_Status &= ~D4D_TCHSCR_STATUS_NEWTOUCH; return; } } if(D4D_ScrCheckCoor(pScreen, &d4d_TouchScreenCoor)) { d4d_msg.pObject = NULL; d4d_msg.nMsgId = D4D_MSG_TOUCHED; // send the D4D_MSG_TOUCHED message D4D_SendMessage(&d4d_msg); } } pObjects = (D4D_OBJECT**)pScreen->pObjects; // check all objects while(*pObjects) { if(D4D_FindTouchedObject(*pObjects, d4d_TouchScreenCoor)) break; pObjects++; } }else { if(d4d_LastTouchedObj) { //Untouch operation if(!(d4d_TouchScreen_Status & D4D_TCHSCR_STATUS_TOUCHED)) { // prepare message d4d_msg.nMsgId = D4D_MSG_UNTOUCHED; d4d_msg.prm.draw = 0; if(pData->flags & D4D_SCR_FINT_TOUCHENABLE) { if(D4D_ScrCheckCoor(pScreen, &d4d_TouchScreenCoor)) { d4d_msg.pObject = NULL; // send the D4D_MSG_UNTOUCHED message to screen D4D_SendMessage(&d4d_msg); // To screen } } if(d4d_LastTouchedObj) { d4d_msg.pObject = d4d_LastTouchedObj; d4d_LastTouchedObj = NULL; // send the D4D_MSG_UNTOUCHED message to Object }else return; } else { //Autorepeat operations // Handle Screen events if(pData->flags & D4D_SCR_FINT_TOUCHENABLE) { if(D4D_ScrCheckCoor(pScreen, &d4d_TouchScreenCoor)) { d4d_msg.pObject = NULL; d4d_msg.nMsgId = D4D_MSG_TOUCH_AUTO; // send the D4D_MSG_TOUCH_AUTO message D4D_SendMessage(&d4d_msg); // To screen } } d4d_msg.pObject = d4d_LastTouchedObj; // Check the coordination if its valid if(d4d_LastTouchedObj->pObjFunc->CheckCoordinates) validCoor = d4d_LastTouchedObj->pObjFunc->CheckCoordinates(d4d_LastTouchedObj, D4D_GetScreenToClientPoint(d4d_LastTouchedObj, &d4d_TouchScreenCoor)); else validCoor = D4D_ObjectCheckCoordinates(d4d_LastTouchedObj, D4D_GetScreenToClientPoint(d4d_LastTouchedObj, &d4d_TouchScreenCoor)); // autorepeat touch if(!validCoor && (d4d_TouchScreen_Status & D4D_TCHSCR_STATUS_LOSTTOUCH)) return; // Check if the autorepeat touch is valid or no (LOST TOUCH EVENT) if(!validCoor) { d4d_TouchScreen_Status |= D4D_TCHSCR_STATUS_LOSTTOUCH; d4d_msg.nMsgId = D4D_MSG_TOUCH_LOST; }else { d4d_TouchScreen_Status &= ~D4D_TCHSCR_STATUS_LOSTTOUCH; d4d_msg.nMsgId = D4D_MSG_TOUCH_AUTO; } } // Send prepared message D4D_SendMessageBack(&d4d_msg); } } }
/**************************************************************************/ /*! * @brief The function change focus to the previous object in the given screen * @param pScreen - the pointer to screen * @return None * @note In case that there is no other usable object (visible, enable ...) the focus is not changed *******************************************************************************/ void D4D_FocusPrevObject(D4D_SCREEN* pScreen) { D4D_SCREEN_DATA* pData = pScreen->pData; const D4D_OBJECT* const* pObjects = pScreen->pObjects; D4D_OBJECT* pFocusedObj = pData->focusedObject; if(!pScreen) return; // sanity check of list of objects - contains Screen any object? if(*pObjects == NULL) return; do { // just get previous object pFocusedObj = D4D_FindPreviousObject(pFocusedObj, (((pFocusedObj->pData->flags) & (D4D_OBJECT_F_ENABLED | D4D_OBJECT_F_VISIBLE)) == (D4D_OBJECT_F_ENABLED | D4D_OBJECT_F_VISIBLE))); // object with focus enabled? if((pFocusedObj->pData->flags & (D4D_OBJECT_F_TABSTOP | D4D_OBJECT_F_ENABLED | D4D_OBJECT_F_VISIBLE)) == (D4D_OBJECT_F_TABSTOP | D4D_OBJECT_F_ENABLED | D4D_OBJECT_F_VISIBLE)) { D4D_OBJECT * pParent = pFocusedObj; D4D_BOOL couldBeFocused = D4D_TRUE; // Take care that the parents objects are also visible and enabled while(pParent = D4D_GetParentObject(pParent)) { if((pParent->pData->flags & (D4D_OBJECT_F_ENABLED | D4D_OBJECT_F_VISIBLE)) != (D4D_OBJECT_F_ENABLED | D4D_OBJECT_F_VISIBLE)) { couldBeFocused = D4D_FALSE; break; } } if(couldBeFocused) break; } // avoid endless loop if no focused object can be found }while(pFocusedObj != pData->focusedObject); if(pFocusedObj != pData->focusedObject) { // invalidate object which is loosing focus D4D_SetObjectFlags(pData->focusedObject, D4D_OBJECT_F_REDRAWSTATE, D4D_FALSE); // prepare message KILLFOCUS d4d_msg.pScreen = pScreen; d4d_msg.nMsgId = D4D_MSG_KILLFOCUS; d4d_msg.pObject = pData->focusedObject; D4D_SendMessage(&d4d_msg); // invalidate object which is getting focus D4D_SetObjectFlags((D4D_OBJECT*)pFocusedObj, D4D_OBJECT_F_REDRAWSTATE, D4D_FALSE); // move the focus pData->focusedObject = pFocusedObj; // prepare message d4d_msg.pScreen = pScreen; d4d_msg.nMsgId = D4D_MSG_SETFOCUS; d4d_msg.pObject = pFocusedObj; D4D_SendMessage(&d4d_msg); } }
/**************************************************************************/ /*! * @brief The function change focus to the next object in the given screen * @param pScreen - the pointer to screen * @param bInitialSearch - flag force start looking from the first object in screen object table * @return None * @note In case that there is no other usable object (visible, enable ...) the focus is not changed *******************************************************************************/ void D4D_FocusNextObject(D4D_SCREEN* pScreen, D4D_BOOL bInitialSearch) { D4D_SCREEN_DATA* pData = pScreen->pData; const D4D_OBJECT* const* pObjects = pScreen->pObjects; D4D_OBJECT* pFocusedObj = pData->focusedObject; if(!pScreen) return; // sanity check of list of objects - contains Screen any object? if(*pObjects == NULL) return; // currently focused object already has a tabstop if(bInitialSearch) { //SetUp start object pData->focusedObject = (D4D_OBJECT*)pObjects[0]; pFocusedObj = (D4D_OBJECT*)pObjects[0]; if((pObjects[0]->pData->flags & (D4D_OBJECT_F_TABSTOP | D4D_OBJECT_F_ENABLED)) == (D4D_OBJECT_F_TABSTOP | D4D_OBJECT_F_ENABLED)) return ; } do { // get next object pFocusedObj = D4D_FindNextObject(pFocusedObj, (((pFocusedObj->pData->flags) & (D4D_OBJECT_F_ENABLED | D4D_OBJECT_F_VISIBLE)) == (D4D_OBJECT_F_ENABLED | D4D_OBJECT_F_VISIBLE))); // object with focus enabled? if((pFocusedObj->pData->flags & (D4D_OBJECT_F_TABSTOP | D4D_OBJECT_F_ENABLED | D4D_OBJECT_F_VISIBLE)) == (D4D_OBJECT_F_TABSTOP | D4D_OBJECT_F_ENABLED | D4D_OBJECT_F_VISIBLE)) break; // avoid endless loop if no focused object can be found }while(((D4D_OBJECT*)pFocusedObj) != pData->focusedObject); if(((D4D_OBJECT*)pFocusedObj) != pData->focusedObject) { // invalidate object which is loosing focus D4D_SetObjectFlags(pData->focusedObject, D4D_OBJECT_F_REDRAWSTATE, D4D_FALSE); // prepare message KILLFOCUS d4d_msg.pScreen = pScreen; d4d_msg.nMsgId = D4D_MSG_KILLFOCUS; d4d_msg.pObject = pData->focusedObject; D4D_SendMessage(&d4d_msg); // invalidate object which is getting focus D4D_SetObjectFlags((D4D_OBJECT*)pFocusedObj, D4D_OBJECT_F_REDRAWSTATE, D4D_FALSE); // move the focus pData->focusedObject = ((D4D_OBJECT*)pFocusedObj); // prepare message d4d_msg.pScreen = pScreen; d4d_msg.nMsgId = D4D_MSG_SETFOCUS; d4d_msg.pObject = ((D4D_OBJECT*)pFocusedObj); D4D_SendMessage(&d4d_msg); } }