226 views
in GUI Development by

Hi,

I am trying to implement a series of popups which have different priority to be displayed. My intention is to show a popup (NewPopup) in the next situations: 

a) No popup is currently displayed, so NewPopup is shown immediately; 

b) A popup is currently displayed (CurrentPopup) and NewPopup priority is greater than CurrentPopup priority, so NewPopup is shown immediately;

c) A popup is currently displayed and NewPopup priority is equal to or lower than CurrentPopup priority, so NewPopup should be shown once CurrentPopup is dismissed. 

For this purpose, one method and two variables are used as explained below:

- A "bool" variable called PopupOn is set to "true" when a popup is being shown (CurrentPopup). When CurrentPopup is dismissed, slot method "managePopup" set this variable to "false".

- A "int32" variable called PopupPrio stores current popup priority value as follows: <CurrentPopup.StackingPriority+1>. When CurrentPopup is dismissed, slot method "managePopup" set this variable to 0 (no priority).

- The created method with the name NewPopup() have six arguments and returns a popup with the desired appearance, according to given values for arguments. One of the arguments is a "int32" variable (aPriority) used to set StackPriority of the popup (0-low, 1-medium or 2-high priority). The method also presents the popup by means of "PresentDialog()", taking into account Stacking priority and information stored in PopupOn and PopupPrio to determine the current situation (a, b or c). This method may be called by several slot methods at the same time (every slot 'listens to' a specific boolean variable and calls the method to show a popup when variable value is "true"). 

NOTE: Popup is automatically dismissed when popup button is pressed or popup progress bar (Effectss::RectEffect used on a rectangle view for this purpose) is complete.

So far, I have achieved that popup is displayed successfully in situations a and b. However, I am not able to make NewPopup remain waiting for CurrentPopup to be dismissed, since CurrentPopup progress bar gets interrupted when "while" loop is reached in situation c. You can find the code of NewPopup() method below:

var SCREENS::Alert popup = new SCREENS::Alert;

//Here popup is cutomized (text, color, button...) according to passed in arguments, including StackPriority
//...
//...
//...
popup.StackingPriority = aPriority;
popup.onDone = managePopup;

if (!PopupOn) //situation a
{
  PresentDialog( popup, null, null, null, null, null, null, null, null, false );
  PopupOn = true;
  PopupPrio = aPriority+1;
}
else 
{
  if (PopupPrio < (aPriority+1))  //situation b
  {
    PresentDialog( popup, null, null, null, null, null, null, null, null, false );
    PopupOn = true;
    PopupPrio = aPriority+1; 
  } 
  else  //situation c
  {
     
    while (!IsCurrentDialog())
    { 
      continue;  //here I have tried many different sentences, but while loop is never done
    } 
    PresentDialog( popup, null, null, null, null, null, null, null, null, true );
    PopupOn = true;
    PopupPrio = aPriority+1;     
  }
}

return popup;

I understand that in situation c, "IsActiveDialog()" is "true" for NewPopup, although it is presented below CurrentPopup (hidden for user) due to StackPriority value, but "IsCurrentDialog()" is still "true" for CurrentPopup. I see the conflict but not how to solve this. Obviously, I am not using "while" loop properly, but I do not know how to evaluate when CurrentPopup gets dismissed and triggers  NewPopup presentation.

Could you give me a helping hand here?

Thanks in advance and best regards,

Fayna

1 Answer

+1 vote
by
 
Best answer

Hello Fayna,

Obviously, I am not using "while" loop properly, but I do not know how to evaluate when CurrentPopup gets dismissed and triggers  NewPopup presentation.

in fact, the while loop blocks all other activities in the GUI task. This approach is thus not the ideal one. What can you do? You need a more cooperative approach. For example:

1. Implement a queue (or list) where all waiting popups are stored. In the simplest case this could be a single chained list. Here you could add a variable (e.g. NextPopup) to the popup component and refer the first entry of such chain from a variable existing e.g. in the Application component.

2. Each time NewPopup() is invoked, check whether the priority of the new popup is higher than the of the actually presented popup. If yes, present the popup immediately.

3. If not, just add the popup to the queue (or list) explained above. If you manage the waiting popups in a single-chained list, just append the new popup to the chain. 

4. When the actually presented popup is closed, evaluate the priority of all popups pending in the queue (list). Select the one with the highest priority. Remove it from the queue (list) and present it now.

So far the theoretical consideration. I hope it helps you.

See also the both classes Core::Task and Core::TaskQueue. They implement similar technique to enqueue and process tasks. Unfortunately the implementation is not able to distinguish between several priorities. But may be it helps you further. Just an inspiration:

1. You can manage multiple Core::TaskQueue objects in your Application component for popups with low, medium and high priority.

2. You can derive a new class from Core::Task to represent a pending popup, e.g. YourUnit::PopupTask. This task could contain a variable to refer the respective popup.

3. if the priority of the new popup is equal or lower than the of the current popup, create a new task ( e.g. YourUnit::PopupTask) referring the popup and add it (schedule it) to the corresponding task queue object (for low, medium or high priority).

4. When the current popup is closed, just complete the associated task. The next task will then be triggered automatically.

The difficulty here is to deal with the multiple queues and pause the task processing for queue with lower priority if there is a popup presented belonging to the higher priority. You could:

5: Implement a separate task class which suspends its completion until the popup is closed.

Best regards

Paul Banach

 

by

Hi Paul,

Thanks for your answer. I have tried the cooperative approach you mentioned with poor success because I do not know how I could be able to concatenate several stored popups one after another just using the popup variable "NextPopup" and the system variable "CurrentPopup". Maybe I missunderstood your explanation, but I developed the next snippets of code for NextPopup() method and managePopup slot method:

/*NewPopup() method definition below*/

var SCREENS::Alert popup = new SCREENS::Alert;

//Here popup is customized (text, color, button...) according to passed in arguments, including StackPriority
//...
//...
//...
popup.StackingPriority = aPriority;
popup.onDone = managePopup;

if (CurrentPopup == null)  //situation a
{
  CurrentPopup = popup;
  PresentDialog( popup, null, null, null, null, null, null, null, null, false );
}
else 
{
  if (CurrentPopup.StackingPriority < popup.StackingPriority)  //situation b
  { 
    popup.NextPopup = CurrentPopup;
    CurrentPopup = popup;
    PresentDialog( CurrentPopup, null, null, null, null, null, null, null, null, false );
  } 
  else  //situation c
  {
    CurrentPopup.NextPopup = popup;   
  }
}

return popup;
/*managePopup slot method definition below*/

if (CurrentPopup.NextPopup != null) // Dismiss the current popup and show the next one
{
  DismissDialog( CurrentPopup, null, null, null, null, null, true ); 
  PresentDialog( CurrentPopup.NextPopup, null, null, null, null, null, null, null, null, true );
  CurrentPopup = CurrentPopup.NextPopup;
  CurrentPopup.NextPopup = null; 
}
else // Dismiss the current popup
{
  DismissDialog( CurrentPopup, null, null, null, null, null, false );
  CurrentPopup = null;
}

In the case of more than one NextPopup exist (situation c of my previous comment), the chained list would be something similar to this: CurrentPopup, CurrentPopup.NextPopup, CurrentPopup.NextPopup, CurrentPopup.NextPopup.NextPopup, and so on. For that purpose, it would be neccessary to know a priori how many popups would exist in the list in order to take them into account in the NextPopup() method, since they are added "manually" inside the method, as you can see. Also, it seems that popups only can be shown in the order they were added to the chained list, regardingless their priority or omitting already existing popups in the list with lower priority when adding a new one in order to be shown firstly. 

Following this approach, how could it be possible to evaluate how many popups are currently stored in the list (without including one by one in the method)? And is there a way to make this list dynamic to change the display order of stored popup regarding their priority? I would not know the size of the list or the prioriry of the popups it would include. How would you do it?

On the other hand, I checked task queue documentarion before implementing my first code to display popups with priority and tried to follow that way, but I discarded it because it got messy and it did not work out... That is the reason why I wanted to use the "while" loop approach (or something similar to it) in order to ignore whatever is happening "behind" CurrentPopup until dismissed. 

Thanks in advance for your help and best regards,

Fayna

 

by

Hello Fayna,

with poor success because I do not know how I could be able to concatenate several stored popups one after another just using the popup variable "NextPopup" and the system variable "CurrentPopup".

concerning your implementation, it seems you are already on the right track. I would try following:

1. Let assume CurrentPopup variable refers to the recently presented popup. So far I understand your application case, there can be more than one popup presented at the same time (case b). The order of popups in the list CurrentPopup corresponds thus to the order in which the popups have been presented.

2. Now, duplicate the variable CurrentPopup and name it e.g. PendingPopup. The variable PendingPopup should manage a list of popups which are still pending. Within the list the popups should be sorted accordingly their priority.

The variables PendingPopup and CurrentPopup can thus be seen as starts of two separate single-chained lists. Within each list the popups are chained by using their NextPopup variable. The following figure illustrates it. There are two popups presented (visible): Popup A and B. Whereby the Popup A is the latest one and overlays Popup B. The both popups C and D are not yet presented since their priority is less than the of popup B. Within the list PendingPopup the popups C and D are stored already by taking in account their priority. The priority of popup C is thus equal or higher than the of D. If they are equal, the popup D has been added to the list after C:

3. Adapt the implementation of NewPopup() as shown below. Note the loop to search for the adequate position within PendingPopup list. The popups in the list should be stored according to their priority:

/*NewPopup() method definition below*/

var SCREENS::Alert popup = new SCREENS::Alert;

//Here popup is customized (text, color, button...) according to passed in arguments, including StackPriority
//...
//...
//...
popup.StackingPriority = aPriority;
popup.onDone = managePopup;

if (CurrentPopup == null)  //situation a
{
  CurrentPopup = popup;
  PresentDialog( popup, null, null, null, null, null, null, null, null, false );
}
else 
{
  if (CurrentPopup.StackingPriority < popup.StackingPriority)  //situation b
  { 
    popup.NextPopup = CurrentPopup;
    CurrentPopup = popup;
    PresentDialog( CurrentPopup, null, null, null, null, null, null, null, null, false );
  } 
  else  //situation c
  {
    // The priority of the popup is higher than the of all other popups stored in the
    // PendingPopup list. Then arrange the new popup just at the beginning of the list.
    if ( !PendingPopup || ( popup.StackingPriority > PendingPopup.StackingPriority ))
    {
      popup.NextPopup = PendingPopup;
      PendingPopup    = popup;
    }

    // ... the priority of the new popup is equal or lower. Therefore search for the
    // adequate position in the list where the popup may be stored. 
    else
    {
      var Application::Popup prevPopup = PendingPopup;

      // Traverse the list of pending popups looking for the adequate position
      while ( prevPopup.NextPopup && ( prevPopup.NextPopup.StackingPriority >= popup.StackingPriority ))
        prevPopup = prevPopup.NextPopup;

      // Arrange the new popuzp just after 'prevPopup' in the list
      popup.NextPopup     = prevPopup.NextPopup;
      prevPopup.NextPopup = popup;
    }
  }
}

return popup;

4. Now, when the user closes the current popup, we have to check the priority of all other popups. We have to distinguish between following situations:

d. there is no other popup in the CurrentPopup list. Consequently, the next popup from the PendingPopup list can be presented (if any existing of course).

e. there is still other popup in the CurrentPopup list and its priority is lower than the of the next popup from the PendingPopup list. Then we present immediately the next popup from the PendingPopup list.

f. there is still other popup in the CurrentPopup list and its priority is equal or higher than the of the next popup from the PendingPopup list. Then we do nothing. The popup from the CurrentPopup list is already presented and after dismissing the recent popup it is active again.

This could be the corresponding implementation of the managePopup slot method:

/*managePopup slot method definition below*/

// First at all, dismiss the current popup and let 'CurrentPopup' variable
// refer the evtl. previously presented popup
DismissDialog( CurrentPopup, null, null, null, null, null, false );
CurrentPopup = CurrentPopup.NextPopup;

// Should present the pending popup? Case d and e:
if ( PendingPopup && 
   ( !CurrentPopup || ( PendingPopup.StackingPriority > CurrentPopup.StackingPriority )))
{
  var YourUnit::PopupClass popup = PendingPopup;

  // Remove the popup from the PendingPopup list and add it to the CurrentPopup list
  PendingPopup    = PendingPopup.NextPopup;
  popup.NextPopup = CurrentPopup;
  CurrentPopup    = popup;

  // Present the popup
  PresentDialog( popup, null, null, null, null, null, null, null, null, true );
}

So far the possible implementation. I hope it helps you as an inspiration.

Best regards

Paul Banach

by
Hi Paul,

I do thank you for your last comment. I would have never thought about using a second list of popups to compare and establish proper priority, so I appreciate you shared your approach. It resolved the priority issue with to-be-displayed popups queue and it seems to work perfectly.

Best regards,

Fayna

Ask Embedded Wizard

Welcome to the question and answer site for Embedded Wizard users and UI developers.

Ask your question and receive answers from the Embedded Wizard support team or from other members of the community!

Embedded Wizard Website | Privacy Policy | Imprint

...