eDriven Q&A

Guys, this forum thread became too huge, so I created the eDriven forum at the address:

forum.edrivengui.com

Please use it for asking questions!

You can login to eDriven forum by creating an account or using Facebook:

1016130--71026--$facebook.png


I created this thread to answer the questions regarding eDriven framework (I’d like to have the eDriven.Gui thread for news and updates only).

Other threads covering eDriven.Gui:

eDriven
eDriven.Gui
eDriven.Gui - GUI for programmers

Just wanted to say, thank you for your answer! I’ll be keeping a close look on the package.

The thing is, the UnityGUI category is for the actual Unity GUI system. I’ve moved this to Assets Asset Store, which is for third-party assets.

–Eric

You’re right. Thanks.

Continuing from here: http://forum.unity3d.com/threads/143093-eDriven.Gui-GUI-for-programmers/page2

This goes into the next build, you would then use this one-liner:

eDriven.Core.Framework.EnableInfoMessages = false;

Just some Unity warnings, I believe this has nothing to do with a framework.

This works generally on each component type:

myCmp.KeyDownFilter = new List<KeyCode>(new[] { KeyCode.Return, KeyCode.Space }); 
myCmp.KeyUpFilter = new List<KeyCode>(new[] { KeyCode.Return, KeyCode.Space });

For TextField you also have:

myTextField.AlowedCharacters = "-0123456789"

Using this method overload, you could further customize alert buttons:

Alert.Show(
	delegate(string action) // this is the callback
	{
		Debug.Log("The action was: " + action);
	},
	new AlertOption(AlertOptionType.HeaderIcon, ImageLoader.Instance.Load("Icons/lock")),
	new AlertOption(AlertOptionType.Title, "Logging in"),
	new AlertOption(AlertOptionType.Message, "Please sign out with your Facebook account to post comments.\n\nAlternatively, you could log in manually."),
	new AlertOption(AlertOptionType.Button, new AlertButtonDescriptor("facebook", "Login with Facebook", Resources("Icons/facebook"), true)),
	new AlertOption(AlertOptionType.Button, new AlertButtonDescriptor("manual", "Login", Resources.Load("Icons/key"))),
	new AlertOption(AlertOptionType.Button, new AlertButtonDescriptor("cancel", "Cancel", Resources("Icons/cancel")))
);

Nope. eDriven.Gui currently works on top of the immediate GUI, thus inheriting all of it’s restrictions. You can style the TextField using the TextFieldStyleMapper, but only one font/color per text field:

checkbox.Selected = true;

(Selected property inherited from Button)

Use GetTabChildren() method of your Form (Container):

public override List<DisplayListMember> GetTabChildren()
{
    return new List<DisplayListMember> { _btnSubscribe, _btnFoo, _chkBar, _comboBaz };
}

Note: Each component has to be FocusEnabled = true.

In eDriven there’s no special window class - you can popup every component. For displaying popups you should use the PopupManager:

LoginDialog popup = new LoginDialog();
PopupManager.Instance.AddPopup(loginDialog);

To remove the popup use:

PopupManager.Instance.RemovePopup(popup);

To communicate with popup use setters (properties accessible from outside) and callback functions:

LoginDialog loginDialog = new LoginDialog();
{
	Message = "Please login", // property
	Callback = delegate(string loginAction) // callback
	{
		switch (loginAction)
		{
			case "success":
				Foo();
				break;
		}
	}
};
PopupManager.Instance.AddPopup(loginDialog);

For dialogs you could use the Dialog class. It has a header (if Draggable = true), and exposed Tools, HeaderGroup and ButtonGroup containers (available immediatelly inside the InitializationComplete()).

You can supply cour own buttons via ButtonGroup.AddChild. Your button could then trigger the ExecCallback method, which is a default callback (you can also supply other callbacks when overriding the dialog) and also removes the popup automatically.

public class MyCustomDialog : Dialog
{
	Button _btnClose;
	Button _btnCancel;
	Label _txtComp;
	
	protected override void InitializationComplete()
	{
		base.InitializationComplete();

		MinWidth = 200;
		MinHeight = 200;
		Width = 300;
		Height = 400;

		Draggable = false;
		Padding = 10;

		_btnClose = new Button { Icon = (Texture)Resources.Load("Icons/close_16"), Width = 20, Height = 20 };
		_btnClose.Click += delegate { PopupManager.Instance.RemovePopup(this); };
		Tools.AddChild(btnClose);

		ButtonGroup.Visible = ButtonGroup.IncludeInLayout = false; // we could even hide the button group
	}
	
	protected override void CreateChildren()
	{
		base.CreateChildren();

		_txtComp = new TextField {PercentWidth = 100, MouseEnabled = true, Editable = false}; // allow cropping if too long
		AddContentChild(_txtComp); // this goes into content

		_btnCancel = new Button
		{
			Text = "Close",
			Icon = (Texture)Resources.Load("Icons/cancel")
		};
		_btnCancel.Press += delegate
		{
			ExecCallback(CANCEL);
		};
		ButtonGroup.AddChild(_btnCancel); // this goes into the button group
	}
}

You got to listen for KEY_UP or KEY_DOWN event (depending of your choice) - but ONLY when component in focus. Here’s the excerpt from the LoadImages demo:

_txtSearch = new TextField
 {
	 Text = "croatian coast",
	 FocusEnabled = true,
	 Width = 400
 };
_txtSearch.SetFocus();
_txtSearch.KeyUp += delegate (Event e)
{
	KeyboardEvent ke = (KeyboardEvent) e;
	if (ke.KeyCode == KeyCode.Return)
	{
		Search();
	}		
};
AddChild(_txtSearch);

For Buttons, there is Button.PRESS event type, and correponding multicast delegate button.Press:

button.Press += delegate { Foo(); }

Press is the aggregate of CLICK and KEY_UP, meaning when button in focus it can be pressed by the ENTER key.

You are in the async world now.

Show method cannot possibly return the result because it is not synchronous (i.e. the result of the method isn’t known immediatelly, it has to wait for user’s interaction).

You have to use one of the Show() method overloads which supports supplying the callback function:

Alert.Show(
	delegate(string action) // a callback
	{
		Foo(action);
	},
	new AlertOption(AlertOptionType.Title, "Info"),
	new AlertOption(AlertOptionType.Message, "It's your choice."),
	new AlertOption(AlertOptionType.Flags, AlertButtonFlag.Ok | AlertButtonFlag.Cancel)
);

TabNavigator question.

_nav = new TabNavigator
{
	PercentWidth = 100,
	PercentHeight = 100,
	VerticalSpacing = 4,
	ButtonMinWidth = 40
};
AddContentChild(_nav);

_txtLayout = new TextField
{
	PercentWidth = 100,
	PercentHeight = 100,
	Editable = false,
	Multiline = true,
	ScrollContent = true,
	AlwaysShowVerticalScrollbar = true,
	NavigatorDescriptor = "Layout"
};
_nav.AddContentChild(_txtLayout);

_txtSpacing = new TextField
{
	PercentWidth = 100,
	PercentHeight = 100,
	Editable = false,
	Multiline = true,
	ScrollContent = true,
	AlwaysShowVerticalScrollbar = true,
	NavigatorDescriptor = "Spacing"
};
_nav.AddContentChild(_txtSpacing);

You could use the LoadingMask:

int count = 0;

LoadingMask mask = new LoadingMask(btn1);
mask.SetMessage(string.Format("Masking... {0} seconds", count));

Timer t = new Timer(1, 5);
t.Tick += delegate
			{
				count++;
				mask.SetMessage(string.Format("Masking... {0} seconds", count));
			};
t.Complete += delegate { mask.Unmask(); };
t.Start();

Except skining the CheckBox (or Button with button.ToggleMode = true), nothing else out of the box.

The answer could be: make a custom control.

Use AddField method to add any component. This means you can add the HBox containing a number of child components.

HBox hbox = new HBox();

TextField txt = new TextField { Width = 200; };
hbox.AddChild(txt);

Button btn = new Button ();
btn.Text = "Address book";
hbox.AddChild(btn);

_form.AddField("dummy", "Composite control", hbox);

Use TileLayout and size the container so that it can have only 3 children in a row.

The example is in LoadImages demo source (look for “_box” in LoadImages.cs)

It’s all 1.3, the DLL info has not been updated.

KeyboardMapper is used to map keyboard events globally for the application. This feature is mostly used for player controls etc.
If using KeyboardMapper - then your method is good, because you should use a flag.

But there’s another way to do it, an this is the primary way of doing things in eDriven:

All components dispatch KeyboardEvents. However, it only happens if they the component has ProcessKeys = true and when this (single component at a time) is in focus.

So you could subscribe to KeyUp multicast delegate (or AddListener(KeyboardEvent.KEY_UP) - which is the same).

However, there are a convenience protected virtual methods in component class: KeyUpHandler and KeyDownHandler, that automatically subscribe/unsubscribe to keyboard events when in focus, so it is better to use these (when inside the component), just to leave them to take care of subscribing/unsubscribing. Internally, it works like this:

if (/* I am processing key events and I am in focus */)
{
	KeyDown += KeyDownHandler;
	KeyUp += KeyUpHandler;
}
else
{
	KeyDown -= KeyDownHandler;
	KeyUp -= KeyUpHandler;
}

So, listen to key events this way:

_txtSearch.KeyUp += delegate (Event e)
{
	KeyboardEvent ke = (KeyboardEvent) e;
	if (ke.KeyCode == KeyCode.Return)
	{
		Search();
	}
}