zebkit.ui.Panel

                zebkit.layout.Layoutable 
                          |
                    zebkit.ui.Panel
                          |
        +-----------------+-----------+--------------+  
        |                             |              |
zebkit.ui.web.HTMLElement      zebkit.ui.Button    Many others
                                                zebkit UI components  

Zebkit UI components are instances of “zebkit.ui.Panel” class. The class unifies UI components with common API, events handling, metrics and behavior. “zebkit.ui.Panel” class provides the following main UI component possibilities and features:

    zebkit.require("ui", "layout", function(ui, layout) {
        ...
        // create panel with border layout manager
        var panel = new ui.Panel(new layout.BorderLayout());
        // add button component at the top part of the container
        panel.add("top", new ui.Button("Button"));
        // add text area component to occupy central part of the 
        // container
        panel.add("center", new ui.TextArea("Text area"));
        ...
    });
    zebkit.require("ui", function(ui) {
        ...
        // instantiate anonymous panel class that implements 
        // "paint(g)" method to draw red circle in the panel 
        var panel = new ui.Panel([
            function paint(g) {
                g.setColor("red");
                g.beginPath();
                g.arc(Math.floor(this.width  / 2),
                      Math.floor(this.height / 2),
                      Math.floor((this.width-1)/2),0,2*Math.PI,false);
                g.closePath();
                g.fill();
            }
        ]);
        ...
    });
    zebkit.require("ui", function(ui) {
        ...
        // Handle pointer entered and exited events
        var panel = new ui.Panel([
            function pointerEntered(e) {
                console.log("Pointer is in the panel");
            },

            function pointerExited(e) {
                console.log("Pointer is out of the panel");
            }
        ]);
        ...
    });

Placing UI hierarchy

Zebkit UI components framework utilizes HTML5 Canvas as a target surface to render UI components hierarchy (theoretically zebkit can be adapted to any Canvas-like surface). The surface is abstracted with “zebkit.ui.zCanvas” class that as any other UI component, inherits “zebkit.ui.Panel”. zCanvas is the destination to place an UI hierarchy. To do it follow the steps listed below:

For example:

zebkit.require("ui", "layout", function(ui, layout) {
    // create HTML Canvas element where zebkit UI to host
    // zebkit UI components hierarchy 
    var htmlCanvas = new ui.zCanvas(500, 400);

    // to place UI components use root layer of 
    // created HTML canvas
    var root = htmlCanvas.root;

    // everything has to be ordered with rules
    // so specify layout manager 
    root.setLayout(new layout.BorderLayout(8));

    // add button zebkit component
    root.add("bottom", new ui.Button("Hello zebkit"));    
    ...

Simple zebkit application

Find below a simple zebkit application that builds the following UI components hierarchy:

# HTML5 Canvas surface
zebkit.ui.zCanvas 
  +-root  # root layer 
     |
     +-zebkit.ui.Panel 
        |   (blue)
        |
        +- zebkit.ui.Label 
        |   ("Test Label")
        |
        +- zebkit.ui.Button 
        |   ("Button")
        |
        +- zebkit.ui.Panel 
            | (orange)
            |
            +-zebkit.ui.TextField
             ("Text Field")
Components hierarchy

The application code is shown below:

zebkit.require("ui","layout","draw",function(ui,layout,draw) {
    (new ui.zCanvas("layoutSample", 300, 420)).root.properties({
        layout: new layout.BorderLayout(),
        kids  : {
            "center": new ui.Panel({
                border: new draw.Border("white", 2),
                bounds: [10,10, 380, 280],
                background: "#3F76AA",
                kids: [
                    new ui.Label("Test Label").properties({
                        color: "white",
                        font: "bold",
                        bounds: [10, 10, 360, 50]
                    }),
                    new ui.Button("Button").setBounds(10,60,270,50),
                    new ui.Panel({
                        bounds: [10, 120, 280, 270],
                        background: "orange",
                        kids: [
                            new ui.TextField("Text Field")
                            .setBounds(10, 10, 250, 30)
                            .toPreferredHeight()
                            .setBorder(new draw.Border("white"))  
                        ]
                    })
                ]
            })
        }
    });
});

UI container API

It has been mentioned many times zebkit UI is organized as a multi-level hierarchy of various UI components. To manage the hierarchy UI component API provides the following methods and fields:

Method or fieldDescription

UI hierarchy fields:
parent, kids

References to a parent component (parent) and array of child components (kids)

Insertion API:
add([constraints],component)
setAt(index,component)
setByConstraints(constraints,component)
insert(index,constraints,component)

Add, insert, re-set a child component.

Removal API:
removeAt(index)
remove(comp)
removeAll()
removeMe()

Remove child component by child component index, by passed child component instance, all children or the given component.

Layout API:
layout
constraints
byConstraints(ctr)
setLayout(ctr)

Setup layout manager, find child components by its constraints.

UI component defines a layout manager to order its child components. Layout manager is special class that:

Layout manager is mandatory. If an UI component has not defined a layout manager a default one is taken. The default layout manager doesn’t have any special rules to order child components. Actually it does nothing, what means defined with a child component size and coordinates (“x”, “y”, “width”, “height”) will have effect.

For more details consult “zebkit.ui.Panel” API documentation.

Traveling over UI components hierarchy

Finding components in an UI hierarchy is implemented with “byPath(…)” method that is a part of panel API. The method gets two parameters:

The XPath like expression has to satisfy number of requirements:

Let’s imagine we have the following UI hierarchy:

zcan ("zebkit.ui.zCanvas")
  |
  +-- root ("zebkit.ui.Panel")
       +-- pan1 ("zebkit.ui.Panel")
       |     | 
       |     +-- lab1 ("zebkit.ui.Label")
       |     +-- tf1  ("zebkit.ui.TextField")
       |
       +-- pan2 ("zebkit.ui.Panel")
             | 
             +-- ta1 ("zebkit.ui.TextArea")
             +-- bt1 ("zebkit.ui.Button")  

Then examples of path expressions and traversing results are shown in the table below:

Path Result

zcan.byPath(“//*”, callback)

root, pan1, lab1, tf1, pan2, ta1, bt1

zcan.byPath(“/*”, callback)

root

zcan.byPath(“./zebkit.ui.Panel”, callback)

zcan, root

zcan.byPath(“//zebkit.ui.Label”, callback)

lab1

zcan.byPath(“//~zebkit.ui.Label”, callback)

lab1, tf1, ta1
(since tf1 and ta1 are instances
of "zebkit.ui.Label" class)

zcan.byPath(“/*/*“,callback)

pan1, pan2

pan1.byPath(“./*“,callback)

pan1, lab1, tf1

It is possible to use id shortcut path to find a component by its id (if the id has been set with “setId(id)” method). The shortcut path expression starts form ”#” prefix that precedes an id value:

// found component in hierarchy by its id 
var foundComp = root.byPath("#test");

Optionally path part can include property value filter that defines a property value traversing component have to match:

// find all visible labels component 
root.byPath("//zebkit.ui.Label[@isVisible=true]",function(found) {
    ...
});
// find all labels component that defines id property
root.byPath("//zebkit.ui.Label[@id]", function(foundComp) {
    ...
});

XPath like expressions can be optionally used with other “zebkit.ui.Panel” API methods:

    // Make visible all child text field components on ll level  
    // for the root  
    root.properties("//zebkit.ui.TextField", { visisble: true });
    // Register listener for all found button components 
    // that are child of the root recursively  
    root.on("//zebkit.ui.Button", function(button) {
        ...
    });

UI Component metrics

ScreenShot

MetricDescription
x,y
setLocation(x,y)
component coordinates relatively to its parent component
width,height
setSize(w,h)
component size and component size method setter
setBounds(x,y,w,h) component bounds (location and size) setter
getPreferredSize()
setPreferredSize(w,h)
the size the component desires to have plus border and padding gaps. The getter method returns result as "{ width:intValue, height:intValue }" data structure. The "pure" preferred size of a component is calculated by its layout manager. Layout manager implements special "calcPreferredSize(comp)" method that does the calculation. The "pure" preferred size does not include border and padding gaps.
left,right,top,bottom,
setPaddings(t,l,r,b)
setPadding(p)
component paddings and appropriate setters to setup the paddings.
getLeft(),getRight()
getTop(),getBottom()
calculated gaps as amount of padding and border gaps.
border.getLeft(),border.getRight()
border.getTop(),border.getBottom()
border gaps if border is has been defined for the component

Component validation

For the sake of performance UI component saves its state to avoid redundant preferred size calculation, repainting and lay outing. The state can be valid or invalid. Developer can check the component state by accessing “isValid” boolean property. The following methods allow developers to control a component state:

In most cases developers should not care to much about UI component validation and invalidation. Proper invalidation and validation is implemented in particular UI component basing on its specific implementation. UI Component API methods do validation and invalidation when it is necessary. Just use it as is with no extra thought regarding its internal implementation.