888 views
in GUI Development by
Hi,

I have a WindowsTouchHandler that implements onTop, onBottom, onLeft and on Right. I also have a few pushbuttons on the screen. I am noticing that when I implement onLeft or onRight, I lose the ability to implement onTop and on Bottom as well as any of the pushbuttons. If I restart the system and implement onBottom, I do have the ability to do onLeft and onRight but the pushbuttons don't work. Is there some type of ordering command or technique, I have to implement to have all the touch handling (onTop, onBottom, onLeft, onRight and all pushbutton responses) work simultaneously? Thanks.

1 Answer

0 votes
by

Hi,

it's difficult to give you good advices based on the provided information... Maybe a short illustration or a piece of code could help to understand what you currently get and what you finally want to achieve.

What do you mean with "WIndowsTouchHandler"? I assume you have a GUI component and a wipe touch handler that is used to detect a wipe gesture in all four directions.

Can you explain "I am noticing that when I implement onLeft or onRight, I lose the ability to implement onTop and on Bottom as well as any of the pushbuttons."?

And what do mean with "If I restart the system.."? Which system is restarted? The PC, the target or Embedded Wizard Studio?

Maybe, the documentation about simple touch handler and wipe touch handler can help. Please take care about the Z-order of all objects (also of the touch handlers!!!). In case you have a touch handler that is on top of a push button, the push buttons touch handler will not get the touch event as long as the touch events are handled by the overlapping touch handler. See section 'Combine several touch handlers together'.

Best regards,

Manfred.

by

My apologies for the confusion. Above is my window. The set of two rows at the top (Views, Parameter, etc and Gas Exchange, etc) is a menu that can disappear with a wipeup and appear again with a wipedown. Wipeleft and right, slides the window to the next display in the 2nd row. In the example above, the current display is "Gas Exchange", if the user wipes left, the next display "Chlorphyll Fluorescence" will display. If the user then wipes right, the previous display "Gas Exchange" displays. This is all being done with a WipeTouchHandle (not a WindowsTouchHandler, my bad). Under some of the squares such as H2Or, there is a pushbutton which is activated when the user presses the square. All of this functionality works fine individually but when I start doing combinations I lose activation functionality. For example, when I wipe left or right, I lose the ability to implement onTop and onBottom as well as any of the pushbutton touch events. By restarting the system, I meant that I had to restart the code on the target in order get a "fresh start". I am assuming that the information in your last paragraph still applies (looking at simple touch handler and wipe touch handler, z-order, etc). With this clarification, if there are other things I should be looking at, please advise. Thank you.

 

 

by

Thank you for providing the additional information - now the goals are clear...

You can structure it in the following way (without knowing your software architecture):

Let's assume the small blue items are on top and they contain a simple touch handler that reacts as soon as the user has pressed and released the item (slot method OnRelease). In case of a short press / release touch cycle, it is detected as a simple button press.

As soon as the touch handler within the small blue item detects a wipe gesture (see RetargetCondition) it retargets the touch event to the next touch handler (according to the Z-order).

Behind the blue items is a slide touch handler that manages the up/down movement of the blue items list (e.g. managed within an Outline Box). The touch events are received either directly, when the user touches somewhere between the blue items or when the touch event is relayed from one of the blue items.

In case of a left/right gesture is detected the touch event is retarget again.

Behind the slide touch handler is a wipe touch handler that handles the left/right wipe gestures so that the page left / page right movement can be managed.

Please have a look to the chapter 'Combine several touch handlers together' - this contains a small example that demonstrates the deflection of the touch events.

Does this help?

Best regards,

Manfred.

 

by
Yes, thank you. Here's the current issue: The blue pushbutton (for example H2Or) works fine, but if I change screens (for example using the top menu I am currently in "View". If I select "Parameters" which does a SwitchToDialog to another screen and then select "View" again doing a SwitchToDialog to the original screen)  the property slot (OnShowH2OSettings) for the postsignal is equal to null and therefore does nothing. Did the postsignal setting get lost when the SwitchToDialog was called? I have the code for setting the postsignal in Application::Application.init().

var Application::DataDisplay1 dialog1 = new Application::DataDisplay1;

dialog1.OnShowH2OSettings = onShowH2OSettings;

DataDisplay1 is the screen with the blue squares. In the Drawer (the 2 row menu at the top) when "View" is selected, should the postsignal be set again? Thanks.
by
Hello,

the switching the dialogs should not modify any properties. I suppose you create a new instance of the DataDisplay1 and you present it by using SwitchToDialog. The new instance is thus not the same as created in Init() method. As consequence, in the new instance all the slot connections are not yet initialized. Can you verify this and eventually post your implementation of how you switch the dialogs?

Best regards

Paul Banach
by
Thanks. Here's the switching dialog mechanics.

1) When the application first comes up, in Application::Container.Init():

var Application::DataDisplay1 dialog1 = new Application::DataDisplay1;

dialog1.OnShowH2OSettings = onShowH2OSettings;

Drawer.Var1 = this;
this.PresentDialog(dialog1, null, null, null, null, null, null, null, null, false );

This is the default "View" dialog.

2) When the user selects "Parameter" in the menu, a slot method is called (in the Drawer component) which contains:

var Application::ParamSetupDialog dialog = new Application::ParamSetupDialog;

Var1.SwitchToDialog( dialog, null, null, null, null, null, null, null, null, null, false );

ParamSetupDialog is not an instance of DataDisplay1.

3) When the user selects "View" in the menu, a slot method is called (in the Drawer component) which contains:

var Application::DataDisplay1 dialog1 = new Application::DataDisplay1;
Var1.SwitchToDialog( dialog1, null, null, null, null, null, null, null, null, null, false );

Again DataDisplay1 is not an instance of ParamSetupDialog. It is here where I have lost my postsignal OnShowH2OSettings.

Thanks for you help.
by

Hello,

In step 3 when the user selects "View" your aplication creates a new instance of Application::DataDisplay1 and switches to this dialog. This instance is another one compared to the created in step1. Therefore it has no initialization for OnShowH2OSettings.

What can you do:

Option 1: in step 3 perform also the necessary property initialization as you do in step 1.

This expects that you have access to the slot method onShowH2OSettings. From your implementation I see you store the instance containing this method in the Drawer.Var1 variable. You can thus use Var1 to access the slot method:

var Application::DataDisplay1 dialog1 = new Application::DataDisplay1;
dialog1.OnShowH2OSettings = Var1.onShowH2OSettings;
Var1.SwitchToDialog( dialog1, null, null, null, null, null, null, null, null, null, false );

I don't know the declaration of Var1 so if you get an type conversion error with the above implementation try to cast Var1 to the type of your Application::Container:

var Application::DataDisplay1 dialog1 = new Application::DataDisplay1;
dialog1.OnShowH2OSettings = ((Application::Container)Var1).onShowH2OSettings;
Var1.SwitchToDialog( dialog1, null, null, null, null, null, null, null, null, null, false );

Option 2: Instead to create a second instance of Application::DataDisplay1 reuse the already existing one. 

For this purpose use a further variable to store dialog1 instance created in step 1 directly in the Drawer. So the code in step 3 could see like this:

// Assuming 'Var2' stores the 'dialog1' from Step1. Switch back to this dialog.
Var1.SwitchToDialog( Var2, null, null, null, null, null, null, null, null, null, false );

In this case you simp,y switch back to the exact the same dialog instance as you have created in step 1.

Does it help you?

Best regards

Paul Banach

 

by

Yes, I used Option 2 and that works.

In Application::Application.Init():

var Application::DataDisplay1 dialog1 = new Application::DataDisplay1;

Drawer.VarView = dialog1;

Then in Drawer callback (onButton1) for View menu item:

VarContainer.SwitchToDialog( VarView, null, null, null, null, null, null, null, null, null, false );

That works great. Thank you.

To take it a step further, I would like to set all my dialog instances each to a variable so I can refer to them later. For example, for the ParamSetupDialog I have done the same thing as DataDisplay1 above:

In Application:: Application.Init():

var Application::ParamSetupDialog dialog2 = new Application::ParamSetupDialog ;

Drawer.VarParam = dialog2;

But when I then try to refer to VarParam in the Drawer component in the callback (onButton2) (when the Parameters menu item is selected), it gives me an error.

VarContainer.SwitchToDialog( VarParam, null, null, null, null, null, null, null, null, null, false );

VarParam.Heading.String = "General Parameters";

[23.8.2019 11:19:54] Error Application::Drawer.onButton2 (3:10) : Unknown identifier 'Heading' used in scope of the class 'Core::Group'.

Before when ParamSetupDialog was created on the fly in the callback (onButton2), there was no issue.

var Application::ParamSetupDialog dialog = new Application::ParamSetupDialog;

dialog.Heading.String = "General Parameters";

Any ideas? Thanks again.

by

Hi,

please check the declaration of the variable VarParam. According to the error message, the variable is declared with class Core::Group. This is the very base class comun for all GUI components. The member Heading, however, is defined in the derived class Application::ParamSetupDialog. The compiler, during compilation time, has no idea that the variable will refer to an instance of the derived class. To solve the problem you have:

Option 1: Adapt the declaration of VarParam to the correct class here I think it is: Application::ParamSetupDialog.

Option 2: Use object runtime cast operator to test at the runtime whether VarParam really refers to an instance of the expected class:

VarContainer.SwitchToDialog( VarParam, null, null, null, null, null, null, null, null, null, false );

// Test whether 'VarParam' refers an instance of the class 'Application::ParamSetupDialog'
var Application::ParamSetupDialog dialog = (Application::ParamSetupDialog)VarParam;

// When the cast was successful -> you can access the members of the instance
if ( dialog != null )
  dialog.Heading.String = "General Parameters";

Best regards

Paul Banach

by

Ok I see. Option 2 worked perfectly. Now the pushbuttons and wipe up/down work together even when I change dialogs. Thank you. 

I have one last issue regarding the WipeTouchHandler. When I wipe left or right, the functionality of the pushbutton callbacks and the wipe up/down for the menu no longer works. The WipeTouchHandler is at the Application::Application level.

OnBottom = onWipeBottom
OnTop = onWipeTop
OnLeft = onWipeLeft
OnRight = onWipeRight

I have used the "wipe-touch-handler" example for the drawer (wipe up/down) and I have used the "using-touch-handler" example for the switching between dialogs (wipe left/right)

slot Application::Application.onWipeBottom
{
// The drawer is already visible. Thus nothing to do.
if ( Drawer.Visible )
  return;

// The drawer component should be visible and able to handle user
// inputs.
Drawer.Visible = true;
Drawer.Enabled = true;

// Start a fade-in animation
PullInOutEffect.Reversed = false;
PullInOutEffect.Enabled  = true;

// While the animation is running suppress the Wipe Touch Handler from
// being able to process more gestures. The Handler is enabled again
// when the animation is finished.
WipeTouchHandler.Enabled = false;
}

slot Application::Application.onWipeTop
{
// The drawer is already visible. Thus nothing to do.
if ( !Drawer.Visible )
  return;

// Start a fade-out animation
PullInOutEffect.Reversed = true;
PullInOutEffect.Enabled  = true;

// While the animation is running suppress the Wipe Touch Handler from
// being able to process more gestures. The Handler is enabled again
// when the animation is finished.
WipeTouchHandler.Enabled = false;
Timer.Enabled = false;
}

slot Application::Application.onWipeLeft
{
// The user wants to browse to the next page.
// Already the last page visible?
if ( pageNo == 3 )
  pageNo = -1;

pageNo = pageNo + 1;       

// Display the page text 
switch ( pageNo )
{
  case 0 :   
  {    
    SwitchToDialog( VarViewApp, Effects::SlideLeftCentered, Effects::SlideLeftCentered, null, null, null, null, null, null, null, false ); 
  }
  case 1 :   
  {    
    SwitchToDialog( VarCustomApp, Effects::SlideLeftCentered, Effects::SlideLeftCentered, null, null, null, null, null, null, null, false ); 
  }
  case 2 : 
  {
    SwitchToDialog( VarCustomApp, Effects::SlideLeftCentered, Effects::SlideLeftCentered, null, null, null, null, null, null, null, false );   
  }
  case 3 : 
  {
    SwitchToDialog( VarGraphApp, Effects::SlideLeftCentered, Effects::SlideLeftCentered, null, null, null, null, null, null, null, false );   
  }
  default :;
}

slot Application::Application.onWipeRight
{
// The user wants to browse to the next page.
// Already the first page visible?
if ( pageNo == 0 )
  pageNo = 4;

pageNo = pageNo - 1; 

// Display the page text 
switch ( pageNo )
{
  case 0 :   
  {    
    SwitchToDialog( VarViewApp, Effects::SlideRightCentered, Effects::SlideRightCentered, null, null, null, null, null, null, null, false ); 
  }
  case 1 :   
  {    
    SwitchToDialog( VarCFMApp, Effects::SlideRightCentered, Effects::SlideRightCentered, null, null, null, null, null, null, null, false ); 
  }
  case 2 : 
  {
    SwitchToDialog( VarCustomApp, Effects::SlideRightCentered, Effects::SlideRightCentered, null, null, null, null, null, null, null, false );   
  }
  case 3 : 
  {
    SwitchToDialog( VarGraphApp, Effects::SlideRightCentered, Effects::SlideRightCentered, null, null, null, null, null, null, null, false );   
  }

  default :;
}

In Application::Application.Init()
{
.......
var Application::DataDisplay1 dialog1 = new Application::DataDisplay1;
VarViewApp = dialog1;
var Application::DataDisplayCFM dialog6 = new Application::DataDisplayCFM;
VarCFMApp = dialog6;
var Application::DataDisplayCustom dialog7 = new Application::DataDisplayCustom;
VarCustomApp = dialog7;
var Application::Graph dialog8 = new Application::Graph;
VarGraphApp = dialog8;
....
}

The issue seems to be after a wipe left or right is done and then a wipe bottom is attempted, at the beginning of the onWipeBottom function:

if ( Drawer.Visible )
  return;

The Drawer.Visible = true even though the Drawer is not seen on the screen and therefore returns out of the onWipeBottom function.

Also, the postsignal is lost for the pushbutton if a wipe left or right is done and then a pushbutton is pressed.

Any ideas? Thanks again.

by

Hi,

two Ideas:

1. I see in OnWipeBottom you make the Drawer visible. In OnWipeTop you start an effect to hide/fade-out the drawer. Do you set the drawer's property Visible to the value false when the effect is finished? Depending on used animation effect, the effect will modify the position or the opacity of the drawer. Its status Visible, however, will remain true the whole time. Usually you can install an OnFinished slot method to the effect and as soon as the effect is done, set the Drawer's property Visible to false. You can imagine, this makes the drawer 'really' hidden. Or you ignore the property Visible and remember the Drawer state in your own variable, which you set/clear when the user shows/hides the drawer. 

2. Is the Drawer's property Visible initialized with the default value false? If not, even if you arrange the Drawer outside of visible area, it will have the status Visible.

Best regards

Paul Banach

by
Thank you for your reponse. It now works!

Idea #1 was already implemented. Idea #2 I changed Drawer's properties Visible and Enabled to false. Also I found that when the left and right wiping was being done the dialogs were not being switched in the Container area and therefore the Drawer appeared to be working but was no visible. Once the SwitchToDialog was called in the Container group (Container.SwitchToDialog(....)) it all looks to work.

Thank you so much for your help.

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

...