Archive for the ‘user interface’ Category

Why Label is considered Control

June 11, 2010

“A label is considered to be a control because of its support for mnemonics (shortcut keys that transfer the focus to related controls).  A tooltip is considered to be a control because it appears and disappears depending on the user’s mouse movements.” – Pro WPF in C# 2010 Windows Presentation Foundation in .NET 4, Matthew MacDonald.

For example, a Label can allow a user to access a menu by typing the “menu mnemonic“.


November 26, 2009

I am always confused by the word “focus” (in the context of user interface, which embarrasses me very much since I am making a living as a “user interface designer”.)  Now I think I am a little clear about the meaning of it so just a note for myself.

In the WIMP environment, for a pointing device such as a mouse, it’s always clear where the “focus” is: it’s always where you point your mouse towards. In this kind of paradigm, the spatial input is continuous.  But in the context of a non-desktop environment where you use a D-pad; or in the WIMP if you use the keyboard as your current input, it’s not always clear where the input is. The concept of “focus” is used to indicate where the spatial input is currently in the GUI. If a UI element has the focus, I guess it depends on what kind of control it is, it can behave slightly differently. For a button, it means it will react as if it “received a mouse click” if the user presses the enter key; For an editable text field, it means it has a caret cursor inside it and is ready to take keyboard input (if you type something they will go into the text field in focus); For a hyperlink, it does the same thing if you press the enter key as if you click directly on it (normally load the page it links to:).)

Note that the visual feedback and behavior for the keyboard input/”discrete spatial input” paradigm is normally different from that of the mouse input/”continuous spatial input” (and also different from that of the touch input — more on this later). In the picture below, it shows the “Go” button is in focus while the “Search” button has a mouse hover.

Fig 1.

Focus on tab vs. mouse hover

Focus on tab vs. mouse hover

Here is some notes:

1. A UI element can be “disabled” but still receives focus. See figure 2-4.

Fig 2.

"Ok" button is disabled

"Ok" button is disabled

Fig 3.

"Cancel" button is in focus

"Cancel" button is in focus

Fig 4.

"Ok" button is in focus

"Ok" button is in focus

2.  In MSDN glossary, it says “input focus” means “The location where the user is currently directing input. Note that just because a location in the UI is highlighted does not necessarily mean this location has input focus.” I guess the scenario is when you are hovering the mouse over an UI element?

3. Touch screen paradigms. As in iPhone, Android opt not to deal focus (showing highlight or any other visuals) in “touch mode“. An interesting reflection is about potentially different interaction paradigms for capacitive touch vs. resistive touch. Can the level of pressure be reflected as whether the UI receives the focus as opposed to take a “click”? Will the “80 percent” of the users be surprised and/or confused?

4. Design guideline for “Input focus location” at MSDN.

5. Besides the keyboard, D-pad, mouse and touch, there is another scenario where the focus can be acquired: that is by code. When a focus is acquired programmatically, the UI behaves as if it’s acquired by a user tabbing the keyboard/D-pad.

6. It’s safe to say for now, the rationale for designing co-existent interaction paradigms is that you should treat the UI as if the user has multiple input/pointing devices at hand (mouse, d-pad, keyboard tabs/arrow keys, fingers). UI shall give feedback respectively to each of the input mechanisms. One input device shall not interfere with the behaviors of the others. For example, tabbing to get another UI element in focus should not result in your mouse cursor changing its current location.

Type of View.OnTouchListener

October 4, 2009

I found the documentation on the type of android.view.View.OnTouchListener misleading. It says: “Return true if the listener has consumed the event, false otherwise.”

For me, it looks like it should almost be the opposite:

“Return true if the event is allowed to propagate, false otherwise.”

//Sample code

public boolean onTouch(View v, evt:MotionEvent) {
switch(evt.getAction) {
case MotionEvent.ACTION_DOWN:
return true; // should allow propagate since we need to handle it in MOTION_MOVE block
case MotionEvent.ACTION_MOVE:
Log.d(“TOUCH”, “historical size is “+getHistoricalSize());
return false;
return false;//for any motions other than DOWN, we choose to block them. Unless other code want to handle it.

Please do feel free to correct me if I am wrong. Thanks.

MVC revisit: Take two

June 7, 2009

I find that MVC is much easier to understand both at the conceptual level and at the implementation level if you think about it from the perspective of how you communicate with the Model.

  1. Control is the input to Model. Basically, the Control is responsible to take input from the user or the system and stransfer it to the changes in the Model; The View is merely there to render the changes from the Model; so it can be considered as the output from the Model. You should keep the business logic as much as possible inside the Model and leave Control/View simple and dandy.For Flex 3 (Halo) components, the way of input is realized by implimenting the “change” listener of the controls, like this:

    <mx:TextInput id="mTxt" change="mVO.txtValue = mTxt.htmlText;"/>

    In Flex 3, when you bind a model to a control, it is one-way communication, meaning the control will reflect the change whenever there is one in the model; but the control would not be able to change the model. That’s why we need to wire through the change listener to make this happen.

    The output is hooked up by setter methods in the Model. Whenever you detect some changes that are historical, you would notify your listeners.

    public function set myValue(v:int):void
    myValue = v;

    In ActionScript 3, we normally implement “notifyListeners” by way of dispatchEvent. Your client listens to the event and updates the View by querying the changes from the Model. You may want to have different types of events so that your listeners can respond differently. For example, you normally would invalidate properties of your component and regenerate all the renderers when the data provider has changed, besides doing other updates; and you don’t want to do this kind of heavy-lifting each time when changes occur on the “less important” members of the Model.

  2. Asynchronous data. Sometimes you may compose something like an HTTPService component into your Model so that it can request external data.The data that are requested by the Control at a lot of times are not immediately available, and normally you would not notify your listeners until they are ready (For example, parsed into an XMLList object that can be consumed by component’s dataProvider).
  3. Static members are available before non-static members of the objects. You can use static members to set some initial values of your member variables.
  4. When you smell spaghetti code in your Model, try to partition/refactor your Model into smaller Value Objects. Value objects are a good way to structure your data/make flat Model hierarchical.
  5. For larger projects, you may want to duplicate Model (or value objects) so that multiple client can access the same data. For example, in your main window of your AIR application, you initialize your model like so:

    public var chatModel:ChatModel = new ChatModel();In another console window, you want to access the same model, like so:

    private var chatModel:ChatModel = Application.application.chatModel;

Working in 3D with Flash Player 10/ActionScript 3 101

December 30, 2008

1. The coordinate system in Flash Player is right handed. For angles in ActionScript, when dealing with DisplayObject properties such as rotationX, use degrees; when dealing with maths such as Math.atan, Math.cos etc., use radians.

2. Gumbo SDK and Flex SDK 3.2 have slightly different implementation on coordinates and layout. A UIComponent with the z depth appears much closer in Flash Player if complied with sdk 3.2 than if complied with Gumbo.

3. When Flash Player applies 3D, “the DisplayObject is drawn into a bitmap, then a vector rectangle (1 quad, not 2 triangles) is created with the dimensions of that bitmap, using that bitmap as a fill. The quad edges are then transformed into 3d world space and projected into 2d stage/global space.” (here, see comment #11.)

4. The Matrix3D and PerspectiveProjection class are used to manipulate visaul classes.

DisplayObject.perspectiveProjection.projectionCenter, which is the type of flash.geom.Point, determines the displayObject’s projection center. If you are setting root (which is  [_Main_mx_managers_SystemManager]) object’s projection center, be aware that  (a) root may be be available when the display list of the component is validated; (b) DisplayObject.transform.perspectiveProjection returns null unless you explicitly instantiate and assign a new PerspectiveProjection object to it, like so:

var pp:PerspectiveProjection = new PerspectiveProjection();
pp.projectionCenter = new Point(width/2, height/2);
contentPane.transform.perspectiveProjection = pp;//this prevents the mouse events from emitting from the contentPane

UICompnent(contentPane).parent.transform.perspectiveProjection = pp;//this doesn’t have the mouse event masking problem.

UICompnent(contentPane).root.transform.perspectiveProjection = pp;//this doesn’t have the mouse event masking problem.

Setting the projection center to the root object will affect the 3D projection of all the displayObjects on the stage, while setting the projection center for individual displayObjects will only affect those objects themselves and their children.

AppendRotation/PrependRotation/AppendTranslation/PrependTranslation apply transformation incrementally to a DisplayObject. To apply transformation in absolute values, use .transform.Matrix3D.recompose() instead:

import flash.geom.Vector3D;
import __AS3__.vec.Vector;

var v3:Vector.<Vector3D> = new Vector.<Vector3D>(3);
//The following line is required to avoid error in Gumbo but not sdk 3.2:
//items[id].transform.matrix3D = new Matrix3D();
v3 = item.transform.matrix3D.decompose();
var ang:Number = (-v + 180 +(centralAngle/numItems)*id)*Math.PI/180;
v3[0] = new Vector3D(0, radius*Math.sin(ang), radius*Math.cos(ang));

To quickly manipulate an object in 3D, you can also use a Matrix3D object as follows:

var matrix:Matrix3D  = new Matrix3D();
matrix.appendRotation(1, Vector3D.YAXIS);
//instantiate .transform.matrix3D property if it doesn’t have one yet:
myObject.z = 0;
myObject.transform.matrix3D = matrix;

“To make something not be 3d anymore, set its .transform.matrix to a non-null value (or set .transform.matrix3D to null)”.

5. Some quirks of Flex 3 (“Moxie”):

If you apply an effect (say mx.effects.Blur) on a UIComponent that has its transform.perspectiveProjection.projectionCenter set explicitly already, FP will first remove the .tranform.Matrix3D on the component before applying the effect. This makes the target look like it’s jumping back to the origin. (Tested on SDK 3.2).

If you try to set projectionCenter (of its parent) and z properties on a UIComponent at the same time, your component won’t be able to receive any mouse event at all. This seems to be fixed on Gumbo.

mx.effects.Move seems to have its own projection center set and ignores your setting for its (parent’s) projectionCenter.

Yesterday Once More

November 26, 2008