370 views
in GUI Development by

I am creating a set of main dialogs (Dialog A, Dialog B...) which can be interchanged depending on what button is pressed in the menu above (Actions, Setup...) or what button is pressend in the horizontal scroll menu (AA, BB...). The 2 row menu is a drawer which can be swiped up or down to show or hide, respectively. The main dialogs need to put restacked to the back so the menu can be seen.  What is the best way to achieve this? When I start the program, in the init() for the menu drawer I have:

var Application::BtmDialog1 dialog1 = new Application::BtmDialog1;  // Dialog A
var Core::Root                         root      = GetRoot();
root.PresentDialog( dialog1, null, null, null, null, null, null, null, null, false ); // Display Dialog A

I get this as an error: [20.5.2019 11:13:27] Runtime Application::Drawer.Init (3:6) : 'PresentDialog' in scope of a 'null' object.
Why am I getting this error? Is the best way to do this or is there another way that is better? (ie., Add/Remove?)

Ideally when the "Setup" button is selected, I would like "Dialog A" to disappear and have "Dialog B" to be displayed behind the menu. 

var Application::BtmDialog3 dialog3 = new Application::BtmDialog3;
var Core::Root                         root      = GetRoot();

root.SwitchToDialog( dialog3, null, null, null, null, null, null, null, null, null, false );
root.RestackBack( dialog3 );

Since I have the error above, I'm unable to get to this code yet. Not sure if I'm on the right track. 

 

 

1 Answer

0 votes
by

Hi,

let me first address the error message. Your implementation is correct. The problem, you use the method GetRoot() during the initialization of an object. At this time the object is not yet part of the view tree. As consequence the method GetRoot() returns null. What can you do?

Option 1: Defer the operation. For this purpose

- add a new slot method to the affected component

- Move your implementation from the Init() method the slot method.

- In the Init() method just request the slot method to be called (later). Use the postsignal statement for this purpose.

Option 2: May be you can avoid the usage of GetRoot()? If you want the dialog to be presented in context of the component itself, you can just call PresentDialog(...) without the preceding root.

Now let me address your particular application case.

1. The buttons (the drawer) I would implement as a separate GUI component which is shown directly within the application (root) component.

2. To present the dialogs so that they don't interfer with the drawer I would create an empty component and arrange in the application (root) object restacked just behind the drwer component. This component let be named e.g. Container.

3. When the user presses a button in the drawer, the resulting dialog is presented in context of the Container component. Youz have two options:

Option 1: The drawer creates and presents the diualogs by itself. In such case the drawer need to know the Container component. The simplest would be:

- to have a variable in the drawer component declared with the type Core::Group.

- In the Init() method of of the application component just initialoize the variable as follows:

Drawer.TheVariable = Container;

- Now you can access from the drawer the Container component and present the dialogs. For example:

TheVariable.PresentDialog( dialog3, ... );

Option 2: Delegate the operations to the application component. For this purpose:

- For every button in the drawer have a corresponding property in the drawer component declared with the type slot.

- Assignbing a value to one of the properties causes the assocuated onset method being executed. 

- In the onset method just assign the value to the corresponding button.

- For every button in the drawer have a slot method in the application component.

- In Inspctor window configure the above mentioned properties of the drawer so that they refer the corresponding slot methods.

Now when the user presses a button, a slot method in the apploication component is executed.

- In the slot method implement the code to present the dialog in context of the Container component. For example:

Container.PresentDialog( dialog3, ... );

Now let me address your third question, how to hide a dialog while presenting another one. THis can be achieved very conveniently by using the method SwichToDialog().

I hope it helps you furter.

Best regards

Paul Banach

by
Hi Paul,

Thank you for your quick response. I am trying to create the varable in the drawer component declared with type Core::Group (#3 Option1 in your response) and I am getting the error:
[20.5.2019 15:30:48] Error Application::Drawer.Var1 (1:1) : Can not cast from type 'int8' to type 'Core::Group' in the initialization of 'Var1'. The both types are not compatible. No automatic conversion possible.
[20.5.2019 15:30:48] Error : Can not initialize a new object. The constructor of the class 'Application::Application' is failed.
[20.5.2019 15:30:48] Runtime Core::Group.Add (2:3) : Chora exception: 'No view to add'.

I basically just dragged a variable (under the Chora template), put it in my drawer component, renamed it and changed the type to Core::Group.  Do I need to cast it somehow?  Thanks!
by

The new added variables have as default value 0 (zero). You see this in the attribute Default of the variable. This is ok for variables declared with a numeric type. Since you have declared the variable with Core::Group as type, the variable is intended to store an object of the given class (concrete a pointer to the object). The value 0 (zero) is in this case incompatible with such declaratoin. If you double click on the error message EmWi leads you to the corresponding attribute.

How to solve the problec? You have two options:

Option 1: Change the default value to something compatible with the type declaratiom. Here use the value null to represent 'no object'.

Option 2: Remove the default value 0 (zero). In this case EmWi will automatically select the right initialization value compatible for the variable. For this purpose:

- First ensure the variable is selected.

- In Inspector look for the attribute Default of the variable.

- Click on this attribute with right mouse button to show a context menu.

- In the context menu select 'Restore default value'.

Thereupon the value of the attribute Default disppears and the status of this attribute changes to not modified. The following figure demonstrates what to do:

by
I used Option 1 and it's all working properly! Thank you!

Embedded Wizard Website | Privacy Policy | Imprint

...