Example 1
Screenshot

Source code
import buw.*;
/**
* example 1: form with reset button
* using: VBox, HBox, TextButton, Input, Label, RadioBox, TextCheckBox & Separator
*/
class Example1 {
public static function main() {
new Example1();
}
var first : Input;
var last : Input;
var adult : TextCheckBox;
var gender : RadioBox;
function new() {
//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 ";
}
Sys.println(prefix + first.value + " " + last.value); //access inputs values
if (adult.checked) { //access check box checked value (boolean)
Sys.println("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

Source code
import buw.*;
/**
* example 2: form in a grid (aligned controls)
* using: Grid (HBoxColumn), TextButton, Input, Label, PasswordInput, Separator & SpinBox
*/
class Example2 {
public static function main() {
new Example2();
}
var first : Input;
var last : Input;
var age : TextSpinBox;
var password : PasswordInput;
function new() {
//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 Separator());
password = new PasswordInput("", 20);
form.pack(new Label("Password:"));
form.pack(password);
form.pack(new Separator());
form.pack(new TextButton(onClick, "OK"));
Screen.display(form);
}
function onClick(w : TextButton) {
Sys.println(first.value + " " + last.value + " " + age.value + "yo; password=" + password.value); //access inputs and spinboxes values
}
}
Example 3a
Screenshot

Source code
import buw.*;
/**
* example 3a: list view without renderer (using toString)
* using: VBox, ListView, Separator, Label & TextButton
*/
class Book {
public var author : String;
public var title : String;
public function new(t : String, a : String) {
author = a;
title = t;
}
//the toString method is required to render list view items (when no renderer is provided)
public function toString() : String {
return title + " - " + author;
}
}
class Example3a {
public static function main() {
new Example3a();
}
//a list view is a usefull widget to display collections of items; it is strongly typed:
var booksList : ListView<Book>;
function new() {
var rootWindow = new VBox();
rootWindow.pack(new TextButton(onAddBooksClick, "Add books"));
Screen.display(rootWindow); //enables vertical scrolling if needed
rootWindow.pack(new Separator());
//because a Book has a toString method, no renderer is required; one can provide a callback to tell what to do when an item is clicked:
booksList = new ListView(onBookClick);
rootWindow.pack(booksList);
}
function onAddBooksClick(w : TextButton) {
//list views source can be arrays or lists:
var books : Array<Book> = new Array();
books.push(new Book("Les misérables", "Victor Hugo"));
books.push(new Book("20 000 lieues sous les mers", "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 callback function is given the clicked item as parameter:
function onBookClick(b : Book) {
Sys.println(b.title);
}
}
Example 3b
Screenshot

Source code
import buw.*;
/**
* example 3b: list view using renderer
* using: VBox, ListView, Separator, Label & TextButton
*/
typedef Book = {
var author : String;
var title : String;
//no required toString method this time
}
class Example3b {
public static function main() {
new Example3b();
}
var booksList : ListView<Book>;
function new() {
var rootWindow = new VBox();
rootWindow.pack(new TextButton(onAddBooksClick, "Add books"));
Screen.display(rootWindow);
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) {
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" });
booksList.source = books;
}
//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
}
function onBookClick(b : Book) {
Sys.println(b.title);
}
}
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 {
public static function main() {
new Example4();
}
function new() {
//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) { Sys.println(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

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 {
public static function main() {
new Example5();
}
static inline var WSURI : String = "https://nominatim.openstreetmap.org/search?format=json&q=";
var search : Input;
var resultsList : ListView<Result>;
function new() {
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) {
function handleResponse(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;
}
if (search.value != "") {
var httpRequest = new haxe.Http(WSURI + search.value);
httpRequest.onError = function (msg : String) {
Sys.println(msg);
}
httpRequest.addHeader("User-Agent", "haxe.tuxfamily.org");
//~ httpRequest.onData = handleResponse;
//~ httpRequest.request(); //invalid X509 certificate (issued by Let's Encrypt)
var bytesOutput = new haxe.io.BytesOutput();
var socket = new sys.ssl.Socket();
socket.verifyCert = false;
httpRequest.customRequest(false, bytesOutput, socket, "GET");
handleResponse(bytesOutput.getBytes().toString());
}
}
function renderSearch (r : Result) : Widget {
return new Label(r.display_name);
}
function onResultClick(r : Result) {
Sys.println(r.type);
}
}
Example 6
Screenshot

Source code
import buw.*;
import openfl.Lib;
import openfl.events.Event;
//~ import openfl.events.KeyboardEvent;
import openfl.display.Sprite;
/**
* example 6: list view with detail, displaying both (in an horizontal pane) when screen Width > 600px
* using: HBox, ListView, VBox, Label, TextButton, Paragraph
*/
class Book {
public var author : String;
public var title : String;
public var synopsis : String;
public function new(t : String, a : String, s : String) {
author = a;
title = t;
synopsis = s;
}
public function toString() : String {
return title;
}
}
class Example6 extends Sprite {
static inline var LIST_WIDTH : Float = 0.3; //relative
static inline var MIN_WIDTH : Int = 600; //pixels
var booksList : ListView<Book>;
var bookDetail : VBox;
var currentScreen : Widget; //booksList xor bookDetail
//used (displayed) when screen width < 600px
var hpane : HBox; //the horizontal pane
//displayed when screen width >= 600px
//an horizontal box with 2 children: booksList (30%) & booksDetail (70%)
function new() {
super();
//first initialize the widgets:
var books : Array<Book> = new Array();
for (i in 0...25) { //to demonstrate scrolling on the list
books.push(new Book("Ravage", "René Barjavel", "Ravage présente le naufrage d`une société mature, dans laquelle, un jour, " +
"l`électricité disparaît et plus aucune machine ne peut fonctionner. Les habitants, anéantis par la soudaineté de la " +
"catastrophe, sombrent dans le chaos, privés d`eau courante, de lumière et de moyens de déplacement."));
books.push(new Book("Demain les chiens (City)", "Clifford D. Simak", "Sur plusieurs milliers d`années, l`auteur brosse " +
"un tableau troublant et poétique de l`avenir de l`humanité. Les Hommes perdent petit à petit leur instinct grégaire " +
"après une série de conflits guerriers et font un retour dans les campagnes, puis laissent la place aux Chiens, qu`ils " +
"ont réussi à doter de la parole."));
}
booksList = new ListView(onBookClick);
booksList.source = books;
bookDetail = new VBox(); //empty by default
hpane = new HBox([new HBoxColumn(LIST_WIDTH), new HBoxColumn(1 - LIST_WIDTH, -1)]); //two columns
currentScreen = booksList; //default is to display the list
//listen to resize event to switch between single / dual (horizontal pane) view
Lib.current.stage.addEventListener(Event.RESIZE, onResize);
//~ Lib.current.stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp); //to handle escape key
draw();
}
function onResize(e : Event) {
draw();
}
function draw() {
hpane.clear(); //remove list and detail view from horizontal box to use full width when < 600px
if (Lib.current.stage.stageWidth >= MIN_WIDTH) {
//add list view and detail widget to the horizontal box and display it:
hpane.pack(booksList);
hpane.pack(bookDetail);
Screen.display(hpane);
Screen.setScrollable(booksList); //only the list view is scrollable
//draw a separator line between list and detail:
hpane.graphics.clear();
hpane.graphics.lineStyle(Widget.borderWidth);
hpane.graphics.drawRect(Lib.current.stage.stageWidth * LIST_WIDTH, 0, 1, Lib.current.stage.stageHeight);
hpane.graphics.endFill();
} else { //display only list or detail:
Screen.display(currentScreen);
}
}
function onBookClick(b : Book) { //display detail
bookDetail.clear();
bookDetail.pack(new Title("Title:"));
bookDetail.pack(new Label(b.title));
bookDetail.pack(new Title("Author:"));
bookDetail.pack(new Label(b.author));
bookDetail.pack(new Title("Synopsis:"));
bookDetail.pack(new Paragraph(b.synopsis));
bookDetail.pack(new TextButton(onBackClick, "Back"));
currentScreen = bookDetail;
draw();
}
function onBackClick(w : TextButton) { //display list
bookDetail.clear();
currentScreen = booksList;
draw();
booksList.draw(); //needed if width has changed while displaying detail
}
//~ function onKeyUp(e : KeyboardEvent) {
//~ if (e.keyCode == 27) {
//~ onBackClick(null);
//~ }
//~ }
}