Basic and Usefull Widgets - Examples

Example 1

Screenshot

Example 1 screenshot

Source code

import buw.*;

/**
 * example 1: form with reset button
 * using: VBox, HBox, TextButton, Input, Label, RadioBox, TextCheckBox & Separator
 */

class Example1 extends openfl.display.Sprite {
  var first : Input;
  var last : Input;
  var adult : TextCheckBox;
  var gender : RadioBox;

  function new() {
    super();

    //create the vertical box container:
    var form = new VBox(1, -1); //use 100% (1) of the screen width, with alignement set to the left (-1)

    //one can add a separator at the top of the form:
    form.pack(new Separator());

    //create an horizontal (cf false) radio box, with two buttons:
    gender = new RadioBox(false).add(new TextRadioButton("M.")).add(new TextRadioButton("Ms."));
    //the widget is stored in a class field to allow callback functions to access the properties of this object (the selected item)

    //stack the radio box into the vertical container:
    form.pack(gender);

    //create then stack two inputs (with labels):
    first = new Input(20); //by default, inputs use 100% of available width
    last = new Input(20);
    form.pack(new Label("Firstname:"));
    form.pack(first);
    form.pack(new Label("Lastname:"));
    form.pack(last);

    //create and stack a check box:
    adult = new TextCheckBox("I am over 18");
    form.pack(adult);

    form.pack(new Separator());

    //add two buttons in an horizontal box:
    var buttons = new HBox(); //by default, the horizontal box will use 100% of the width of its parent
    buttons.pack(new TextButton(onOkClick, "OK", 0.5)); //will use 50% (0.5) of the horizontal box width
    buttons.pack(new TextButton(onResetClick, "Reset", 0.5));
    form.pack(buttons);

    //display the form (vertical box)
    Screen.display(form);
  }

  //the callbacks function receive the clicked widget as parameter:
  function onOkClick(w : TextButton) {
    var prefix : String;
    if (gender.selected == 0) { //access radio box selected item (integer, [0..n-1])
      prefix = "Mister ";
    } else {
      prefix = "Misses ";
    }
    trace(prefix + first.value + " " + last.value); //access inputs values
    if (adult.checked) { //access check box checked value (boolean)
      trace("Ok, You are over 18.");
    }
  }

  function onResetClick(w : TextButton) {
    first.value = ""; //change (reset) input value
    last.value = "";
    adult.checked = false; //change check box state
    gender.selected = 0; //change radio box selected item
  }
}

Example 2

Screenshot

Example 2 screenshot

Source code

import buw.*;

/**
 * example 2: form in a grid (aligned controls)
 * using: Grid (HBoxColumn), TextButton, Input, Label & SpinBox
 */

class Example2 extends openfl.display.Sprite {
  var first : Input;
  var last : Input;
  var age : TextSpinBox;

  function new() {
    super();
    
    //this time, the form is a grid with two columns; it is a usefull container for widgets alignement;
    //the first column uses 30% of screen width and is left aligned (cf -1),
    //the second column uses 70% of the screen width (and centered by default):
    var form = new Grid([new HBoxColumn(0.3, -1), new HBoxColumn(0.7)]);
    
    //by default, inputs use 100% of available width (70% of screen width, since they are put in the second column)
    first = new Input(20); 
    last = new Input(20);
    
    //widgets are stacked line by line, from left to right:
    form.pack(new Label("Firstname:"));
    form.pack(first);
    //third packing is for the second line (since there are two columns):
    form.pack(new Label("Lastname:"));
    form.pack(last);
    
    age = new TextSpinBox("yo", 18, 1, 99); //label, value, min, max
    age.value = 100; //to demonstrate how to change spinbox value; will be set to 50 because 100 is off limits
    form.pack(age);
    
    form.pack(new TextButton(onClick, "OK"));
    Screen.display(form);
  }

  function onClick(w : TextButton) {
    trace(first.value + " " + last.value + " " + age.value + "yo"); //access inputs and spinboxes values
  }
}

Example 3

Screenshot

Example 3 screenshot

Source code

import buw.*;

/**
 * example 3: list view
 * using: VBox, ListView, Separator, Label & TextButton
 */

typedef Book = {
  var author : String;
  var title : String;
}

class Example3 extends openfl.display.Sprite {
  //a list view is a usefull widget to display collections of items; it is strongly typed:
  var booksList : ListView<Book>;

  function new() {
    super();
    var rootWindow = new VBox();
    rootWindow.pack(new TextButton(onAddBooksClick, "Add books"));
    Screen.display(rootWindow); //enables vertical scrolling if needed
    rootWindow.pack(new Separator());

    //to create a list view, one must tell how to render an item, and eventually tell what to do when an item is clicked:
    booksList = new ListView(renderBook, onBookClick);
    rootWindow.pack(booksList);
  }

  function onAddBooksClick(w : TextButton) {
    //list views source can be arrays or lists:
    var books : Array<Book> = new Array();
    books.push({title : "Les misérables", author : "Victor Hugo"});
    books.push({title : "20 000 lieues sous les mers", author : "Jules Verne"});
    
    //first time the button is clicked, source is set:
    if (booksList.source == null) {
      booksList.source = books;
    } else {
      //then, for demonstration purpose, the same books are added to the existing source:
      for (b in books) {
        booksList.push(b);
      }
    }
  }

  //the render function is given an item as a parameter; the returned widget will be displayed by the list view;
  //this function is called once per widget in the item collection:
  function renderBook (b : Book) : Widget {
    //the returned widget is here a label:
    return new Label(b.title + " - " + b.author);
    //it could be something more complex like an horizontal box with an image and a label for example
  }

  //the callback function is givent the clicked item as parameter:
  function onBookClick(b : Book) {
    trace(b.title);
  }
}

Example 4

Screenshot

Example 4 screenshot

Source code

import buw.*;

/**
 * example 3: table view
 * using: Table (TableColumn), Image, HBox & Label
 */

typedef Book = {
  var author : String;
  var title : String;
  var alive : Bool;
}

class Example4 extends openfl.display.Sprite {
  function new() {
    super();
    //in this example, a collection of books is displayed in a table;
    //a table has columns that have a (relative) width, a title and the field name to display or a rendering function for the cell:
    var booksTable : Table<Book> = new Table(
      function (o : Book) { trace(o.title); }, 
      [
        new TableColumn(0.6, "Title", "title"), //for the first colum, the book title is displayed (in a Label)
        new TableColumn(0.4, "Author", renderAuthorColumn) //for the second one, the cell is rendered by a function
      ]);
    Screen.display(booksTable);

    var books : Array<Book> = new Array();
    books.push({title : "La Horde du contrevent", author : "Alain Damasio", alive : true});
    books.push({title : "La fraternité du Panca", author : "Pierre Bordage", alive : true});
    books.push({title : "Ravage", author : "René Barjavel", alive : false});
    
    booksTable.source = books;
  }

  function renderAuthorColumn (b : Book) : Widget {
    //the author column is rendered in an horizontal box:
    var hbox = new HBox();
    //containing the authors name:
    hbox.pack(new Label(b.author));
    if (! b.alive) {
      //and an image if dead:
      hbox.pack(new Image("assets/rip.jpg", Widget.controlsFontSize));
    }
    return hbox;
  }
}

Example 5

Screenshot

Example 5 screenshot

Source code

import buw.*;

/**
 * example 5: querying a web service
 * using: VBox, ListView, Separator, Label, TextButton & Input
 * nothing new with BUW here, it is only a demonstration of its interoperability with haxe.Http class
 */

typedef Result = {
  var type : String;
  var display_name : String;
  var lat : Float;
  var lon : Float;
}

class Example5 extends openfl.display.Sprite {
  static inline var WSURI : String = "http://nominatim.openstreetmap.org/search?format=json&q=";
  var search : Input;
  var resultsList : ListView<Result>;

  function new() {
    super();
    var rootWindow = new VBox();
    rootWindow.pack(new Label("Enter search location:"));
    search = new Input(40);
    rootWindow.pack(search);
    rootWindow.pack(new TextButton(onSearchClick, "Search"));
    Screen.display(rootWindow);
    rootWindow.pack(new Separator());
    resultsList = new ListView(renderSearch, onResultClick);
    rootWindow.pack(resultsList);
  }

  function onSearchClick(w : TextButton) {
    if (search.value != "") {
      var httpRequest = new haxe.Http(WSURI + search.value);
      httpRequest.onError = function (msg : String) {
        trace(msg);
      }
      httpRequest.onData = function (jsonData : String) {
        var results : List<Result> = Lambda.filter(haxe.Json.parse(jsonData), 
                        
                        function (r: Result) { return r.type == "city"; });
        Lambda.iter(results, function (r : Result) {
          var parts : Array<String> = r.display_name.split(", ");
          r.display_name = parts[0] + ", " + parts[2];
        });
        resultsList.source = results;
      }
      httpRequest.addHeader("User-Agent", "haxe.tuxfamily.org");
      httpRequest.request();
    }
  }

  function renderSearch (r : Result) : Widget {
    return new Label(r.display_name);
  }

  function onResultClick(r : Result) {
    trace(r.type);
  }
}