I’m trying to extend the ViewSet class to support cycling through views via next() and prev() methods. However, for some reason when I call activate() from my new class, it doesn’t change the current View.
Weirdly, when I call activate() on my subclass from within the same scope where I instantiate it, it works perfectly fine. If I call activate() from any other scope, it does not work (such as from an event handling function).
Can anyone tell me if I extended ViewSet improperly, or if there is some other restriction I’m unaware of?
My class:

var CyclingViewSet = zebra.Class(zebra.ui.ViewSet, [
* Constructor.
* @param views: A dictionary of view instances to cycle through
* @param wrap: A boolean determining whether this object will wrap around to
* the first view when calling next() on the last view. Likewise, wraps from
* the first view to the last with prev().
function(views, wrap) {
this.keys = Object.keys(views);
this.currentIndex = 0;
this.wrap = wrap;
function(views) {
//Call the other constructor with the wrap parameter defaulted to false:
this.$this(views, false);

/*function activate(id) { //Explicitly overriding the parent function has the same issue.
function next() {
if (this.currentIndex < this.keys.length - 1) {
} else if (this.currentIndex == this.keys.length - 1 && this.wrap == true) {
this.currentIndex = 0;

function prev() {
if (this.currentIndex > 0) {
} else if (this.currentIndex == 0 && this.wrap == true) {
this.currentIndex = this.keys.length - 1;

My test usage:

zebra.ready(function() {
eval(zebra.Import("ui", "layout"));
var view_red = new zebra.ui.View([
function paint(g, x, y, w, h, c) {
g.fillRect(x, y, w, h);
var view_orange = new zebra.ui.View([
function paint(g, x, y, w, h, c) {
g.fillRect(x, y, w, h);
var view_yellow = new zebra.ui.View([
function paint(g, x, y, w, h, c) {
g.fillRect(x, y, w, h);

var canvas = new zebra.ui.zCanvas("avatar");
canvas.root.setLayout(new zebra.layout.BorderLayout());

var bottomPanel = new zebra.ui.Panel();
bottomPanel.setLayout(new zebra.layout.FlowLayout("center", "center", "horizontal", 25));
var prevButton = new zebra.ui.Button("Previous");
var nextButton = new zebra.ui.Button("Next");

var views = {"red":view_red, "orange":view_orange, "yellow":view_yellow};
var viewer = new CyclingViewSet(views);
var viewPanel = new zebra.ui.ViewPan();

prevButton.bind(function(src) {
nextButton.bind(function(src) {
viewer.activate("orange"); //This does not work.
viewer.activate("red"); //This does work.

canvas.root.add(zebra.layout.CENTER, viewPanel);
canvas.root.add(zebra.layout.BOTTOM, bottomPanel);

1 answer

Staff July 22, 2015

First of all you can simplify your views implementation. Try to pass colors directly to zebra.ui.ViewSet. Something like the following should work:

var vset = new ViewSet({red: "red", orange: "orange", yellow: "yellow"});

Or use ready-to use “zebra.util.rgb” color view class:

new zebra.util.rgb("#FF0000"); // red color

// or use constant

The main problem that you have (canvas refreshing) can be solved by calling viewPanel.repaint() method after you call activate(…) method.


Please login or Register to Submit Answer