Source code snippets (examples)

This is a list of Alvin Alexander's source code snippets (simple source code examples).

A Java/Scala program to print key code values using java.awt.event.KeyEvent

The following Scala source code shows the value of various keys on the keyboard that I was interested in today:

package com.valleyprogramming.typewriter
 
import java.awt.event.KeyEvent
 
/**
 * This is a series of tests to see what integer values are returned
 * by the following `KeyEvent._` values. This helps me write a match/case
 * expression to handle the keys properly.
 */
object KeyTests extends App {
 
    println("shift:     " + KeyEvent.VK_SHIFT)
    println("control:   " + KeyEvent.VK_CONTROL)
    println("alt:       " + KeyEvent.VK_ALT)
    println("meta:      " + KeyEvent.VK_META)
    println("enter:     " + KeyEvent.VK_ENTER)
    println("backspace: " + KeyEvent.VK_BACK_SPACE)
    println("escape:    " + KeyEvent.VK_ESCAPE)
    println("left:      " + KeyEvent.VK_LEFT)
    println("right:     " + KeyEvent.VK_RIGHT)
    println("up:        " + KeyEvent.VK_UP)
    println("down:      " + KeyEvent.VK_DOWN)
    println("pg_down:   " + KeyEvent.VK_PAGE_DOWN)
    println("pg_up:     " + KeyEvent.VK_PAGE_UP)
 
    println("a:         " + KeyEvent.VK_A)
    println("z:         " + KeyEvent.VK_Z)
    
    println("space:     " + KeyEvent.VK_SPACE)
    println("tab:       " + KeyEvent.VK_TAB)
 
    // KEYS I WANT TO HANDLE
    // ---------------------
    // 32 = space
    // 33-96, 123-126 are standard keyboard characters
    // 97-122 are lowercase a-z (not sure i need them though, as VK_A is 65)
    // tab is 9    (VK_TAB)
    // ENTER
    // -----
    // LF is 10    (VK_ENTER)
    // FF is 12
    // CR is 13
    // OTHER
    // -----
    // BS is 8     (VK_BACK_SPACE)
    // SPACE is 32 (VK_SPACE)
 
/*
    shift:     16
    control:   17
    alt:       18
    meta:      157
    enter:     10
    backspace: 8
    escape:    27
    left:      37
    up:        38
    right:     39
    down:      40
    pg_down:   34
    pg_up:     33
    a:         65
    z:         90
    space:     32
    tab:       9
*/   
}

I just wanted a little program to print out these keystrokes (key codes), and this program did the trick. (I also wanted to know the key code for the Mac OS X Fn key; that turns out to be 63, which I’ve described elsewhere on this site.)

How I emulate pressing the Fn key on a Mac OS X keyboard using AppleScript

As a quick source code example, this is how I emulate pressing the Fn key on a Mac OS X keyboard using AppleScript:

tell application "System Events"
    key code 63
    key code 63
end tell

The key code for the Fn key is 63, so all that code does is emulate pressing that key twice. Doing this triggers the Mac speech-to-text facility, which I use in my Sarah application (like Siri for the Mac).

A Scala Try, Success, and Failure example

Without much introduction or discussion, here’s an example of how to use Scala’s Try, Success, and Failure classes:

package com.devdaily.sarah.tests

import scala.util.{Try, Success, Failure}
import java.io._

object TrySuccessFailure extends App {

    badAdder(3) match {
        case Success(i) => println(s"success, i = $i")
        case Failure(t) =>
            println(s"CLASS = ${t.getClass}")

            // this works, but it's not too useful/readable
            //println(t.getStackTrace.mkString("\n"))

            // this works much better
            val sw = new StringWriter
            t.printStackTrace(new PrintWriter(sw))
            println(sw.toString)
    }
   
    /**
     * This method returns a `Success[Int]` if everything goes well,
     * otherwise it throws an exception wrapped in a `Failure`.
     */
    def badAdder(a: Int): Try[Int] = {
        Try({
            val b = a + 1
            if (b == 3) b else {
                val ioe = new IOException("Boom!")
                throw new AlsException("Bummer!", ioe)
            }
        })
    }
   
    class AlsException(s: String, e: Exception) extends Exception(s: String, e: Exception)
}

I created this example to test how Try/Success/Failure would work with a block of code that returns an Int or throws and Exception.

A semi-transparent popup dialog (JFrame, actually) in Scala (or Java)

I used the following Scala source code to build a semi-transparent dialog (a Java JFrame, actually) for the second version of Sarah:

import java.awt._
import javax.swing._

/**
 * How to use:
 *
 *   val b = new TextWindowBuilder("Hello, world")
 *   b.setVisible(true)
 *  
 *   // later
 *   b.setVisible(false)
 *
 */
class TextWindowBuilder (
        textToDisplay: String,
        windowSize: Dimension = new Dimension(400, 300),
        location: Point = new Point(200, 200),
        textAreaRows: Int = 10,
        textAreaColumns: Int = 40,
        alpha: Float = 0.8f
        ) {

    // textarea and scrollpane
    val textArea = new JTextArea(textAreaRows, textAreaColumns)
    textArea.setFont(new Font("Helvetica Neue", Font.PLAIN, 20))
    textArea.setEditable(false)
    textArea.setMargin(new Insets(12, 12, 12, 12))
    val scrollPane = new JScrollPane(textArea)
    textArea.setText(textToDisplay)
    scrollPane.setPreferredSize(windowSize)
    scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS)
    scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS)
 
    // jframe
    val f = new JFrame
    f.setUndecorated(true)
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
    f.getRootPane.putClientProperty("Window.alpha", alpha)
    f.getContentPane.add(scrollPane, BorderLayout.CENTER)
    f.setLocation(location)
   
    def setText(text: String) {
        val code = textArea.setText(text)
        invokeLater(code)
    }

    def setVisible(makeVisible: Boolean) {
        if (makeVisible) {
            val block = {
                f.pack
                f.setVisible(true)
            }
            invokeLater(block)
        } else {
            val block = f.setVisible(false)
            invokeLater(block)
        }
    }
   
    private def invokeLater[A](blockOfCode: => A) = {
        SwingUtilities.invokeLater(new Runnable {
            def run {
                blockOfCode
            }
        })
    }
 
}

As one example of how to create a semi-transparent popup window with this code, I instantiated a new window in Sarah like this:

// this is the secondary window i use in Sarah2 to display output
val textWindow = new TextWindowBuilder(
    "",
    new Dimension(mainFrame.getWidth, 400),
    new Point(372, 395)
)

This code shows several things, including:

  • How to create and show a JFrame
  • How to put a JTextArea in a JScrollPane
  • How to provide default parameter values in a Scala constructor (or method)
  • How to set various attributes on a JScrollPane
  • How to use SwingUtilities.invokeLater

I hope there’s something in there that might be of use.

Using git with ssh running on a non-standard port

Yesterday I needed to be able to specify a port with a git clone command, because the git server runs ssh on a non-standard port. In short, the solution was to put this text in my ~/.ssh/config file:

Host example.com
HostName example.com
Port 5150
User gituser

Without looking into this deeper, I’m not sure if the HostName is needed, but I can confirm that the Host field needs to match the server you’re attempting to access, because I fat-fingered the Host on my first try, and it didn’t work.

Once that was set, I was able to run my git clone command using a normal ssh URL like this:

$ ssh://user@example.com/path/to/repo

Note that the general form of the git ssh commands looks like the following examples:

$ git clone ssh://user@server/project.git
$ git clone user@server:project.git

I found the first answer here on SO, and I found the last two git clone examples at this URL.

A Python script to get stock quotes

I get stock quotes on my Radio Pi system with this simple Python script:

#!/usr/bin/python

import ystockquote

print "\n\n___ STOCK QUOTES ___\n"

appl = ystockquote.get_price('AAPL')
print 'Apple: ' + appl + "\n"

att = ystockquote.get_price('T')
print 'AT&T: ' + att + "\n"

gtat = ystockquote.get_price('GTAT')
print 'GTAT: ' + gtat + "\n"

jcp = ystockquote.get_price('JCP')
print 'JCP: ' + jcp + "\n"

nuan = ystockquote.get_price('NUAN')
print 'NUAN: ' + nuan + "\n"

tsla = ystockquote.get_price('TSLA')
print 'TSLA: ' + tsla + "\n"

As shown, it relies on the ystockquote module.

A Linux Bash if/or example

Here’s a quick Linux Bash if/else example featuring an or clause:

#!/bin/bash

day_of_week=`date +"%a"`

if [ "$day_of_week" == "Sat" ] || [ "$day_of_week" == "Sat" ]; then
  echo 'Weekend!'
else
  echo 'Not weekend!'
fi

The if/or clause is similar to other if/or expressions, and uses the || syntax shown.

Notes on installing a Play Framework + MongoDB application on a Linux server at A2 Hosting

These are some notes on how I installed a Play Framework + MongoDB application on a Linux server at A2 Hosting. These notes probably won’t make sense to other people, they’re just here for me. (Sorry about that, I don’t have a great way to post things here just for myself.)

Here are the notes:

A2 Hosting
----------

A2 URL: https://my.a2hosting.com/index.php

ssh username@10.1.1.1 -p 22
ssh rootuser@10.1.1.1 -p 22

---++ Enable Firewall, Secure ssh

# vi /etc/ssh/sshd_config
    # ----------------------------------------------------------
    # AJA: see http://wiki.centos.org/HowTos/Network/SecuringSSH
    # AJA: see http://centoshelp.org/security/securing-sshd/
    # ----------------------------------------------------------
    Port 22
    AllowUsers username1
    LoginGraceTime 1m
    PermitRootLogin no
    MaxAuthTries 6
    MaxStartups 4

# service sshd restart

---++ Add Non-root User

# adduser USERNAME
# passwd USERNAME

---++ Add Software

* install java
  yum install java-1.7.0-openjdk-demo.x86_64

* install mongo
  http://docs.mongodb.org/manual/tutorial/install-mongodb-on-red-hat-cento...

* install nginx
  followed these notes:
  http://www.cyberciti.biz/faq/install-nginx-centos-rhel-6-server-rpm-usin...
  (1)
  wget http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0....
  rpm -ivh nginx-release-centos-6-0.el6.ngx.noarch.rpm
  (2)
  yum install nginx

* Play Framework and MongoDB
  http://blog.knoldus.com/2012/08/02/working-with-play-framework-using-sca...
  http://mongodb.github.io/casbah/tutorial.html

* install mysql
  yum install mysql-server
  chkconfig mysqld on
  service mysqld start
  /usr/bin/mysql_secure_installation
  - give it a password

* install php
  yum install php-mysql php-devel php-gd php-xmlrpc

* install apache/httpd
  yum install httpd
  chkconfig httpd on
  chkconfig --list httpd
  
  later: need to install 'rpaf' module to get IP addresses working
  (http://stderr.net/apache/rpaf/)

Next: Configure software


---++ Nginx

Play Config Info: http://www.playframework.com/documentation/2.1.x/HTTPServer

Enable nginx service:

  # chkconfig nginx on

Commands:

  # service nginx start
  # service nginx stop
  # service nginx restart
  # service nginx status
  # service nginx reload

Edit:

  /etc/nginx/nginx.conf

More config:

  # mount the mfoo client, which is served up by apache
  location /mfoo {
      proxy_pass        http://mfooclient:8888/;
      proxy_set_header  X-Real-IP $remote_addr;
  }

  # mount the mfoo server, which is served up by the play framework console
  location /server/notes {
      proxy_pass        http://mfooserver:9000/notes;
      proxy_set_header  X-Real-IP  $remote_addr;
  }


---++ MongoDB

Good URLs:

http://docs.mongodb.org/manual/tutorial/install-mongodb-on-red-hat-cento...
http://docs.mongodb.org/manual/faq/fundamentals/
http://docs.mongodb.org/manual/faq/diagnostics/

* "Uses .rpm packages as the basis of the installation. 10gen publishes packages of the MongoDB releases as .rpm packages for easy installation and management for users of CentOS..."

# Step 1:
# vi /etc/yum.repos.d/10gen.repo
  [10gen]
  name=10gen Repository
  baseurl=http://downloads-distro.mongodb.org/repo/redhat/os/x86_64
  gpgcheck=0
  enabled=1

# Step 2:
# yum install mongo-10gen mongo-10gen-server

# Configuration:

   * configuration file:  /etc/mongod.conf
   * control script:  /etc/rc.d/init.d/mongod
   * This MongoDB instance will store its data files in the /var/lib/mongo and its log files in /var/log/mongo, and run using the mongod user account.

* Commands

   * To start on reboot: chkconfig mongod on
   * service mongod start
   * service mongod restart
   * service mongod stop

* Using/Testing

   * mongo (client command)
   * (starting and stopping is very slow on A2)

   WARNING: You are running in OpenVZ. This is known to be broken!!!

* On the Production server

  ...
  $ mongo
  mongo> use mfoo
  mongo> db.users.save({"email":"EMAIL", "name”:"YOUR "NAME, "password":"PASSWORD"})

  # simple test
  db.test.save( { a: 1 } )
  db.test.find()
  ...

* Debug information on MongoDB

   * tail -f /var/log/mongo/mongod.log
   * sudo grep mongod /var/log/messages
   * sudo grep score /var/log/messages

* Ports

   * Admin web console waiting for connections on port 29000
   * waiting for connections on port 29001


---++ Play Framework - Production Notes

http://www.playframework.com/documentation/2.1.x/Production
http://www.playframework.com/documentation/2.1.x/ProductionConfiguration

* To deploy the app, first update =appVersion= in _project/Build.scala_. Then:

  ...
  $ play clean compile dist
  ...

  That creates _target/scala-2.10/kfoo_2.10-1.0-SNAPSHOT.jar_. =scp= that file to the server.

* Script on the server:

  ...
  # Copy this file to the KFOO folder, then use it to run the app.

  # default Xmx is 64M (http://docs.oracle.com/javase/1.4.2/docs/tooldocs/linux/java.html).
  # 'port 9000' is the default, but i put this here in case i need to change it.
  # start -Dhttp.port=8080 -Xms512M -Xmx1G

  chmod +x start
  nohup ./start -server -Dconfig.resource=application-prod.conf -Dhttp.port=9000 &
  ...

  To use that script:
  
    * Copy this file to the KFOO folder (/opt/kfoo), then use it to run the app.
    * Unzip it in /opt/kfoo
    * cd to its directory
    * cp my startup script to that dir
    * shut down the old instance, start this new one

* More options to use when starting the Play server:

  # port and address
  $ start -Dhttp.port=1234 -Dhttp.address=127.0.0.1

  # additional jvm args
  $ start -Xms128M -Xmx512m -server

  $ start -Dconfig.resource=application-prod.conf

  # look for config file on filesystem
  $ start -Dconfig.file=/opt/conf/prod.conf

Sencha Touch refs - app.js with 'paths' configuration

Until now I haven’t had a Sencha Touch app.js example out here, so here’s one:

Ext.Loader.setConfig({
    enabled: true,
    paths: {
        'VP.util': 'app/util/VP'
    }
});

Ext.application({
    name: 'RadioMobile',

    requires: [
        'Ext.MessageBox'
    ],

    controllers: [
        'RadioMobile.controller.TimeControlsController',
        'RadioMobile.controller.RadioStationsController',
        'RadioMobile.controller.RadioStreamsController',
        'RadioMobile.controller.RecordedStreamsController',
        'RadioMobile.controller.PodcastsController'
    ],

    views: [
        'RadioMobile.view.MainTabPanel',
        'RadioMobile.view.TimeControlsPanel'
    ],

    models: [
        'RadioMobile.model.Podcast',
        'RadioMobile.model.RadioStation',
        'RadioMobile.model.RadioStream',
        'RadioMobile.model.RecordedStream'
    ],

    stores: [
        'RadioMobile.store.Podcasts',
        'RadioMobile.store.RadioStations',
        'RadioMobile.store.RadioStreams',
        'RadioMobile.store.RecordedStreams'
    ],

    icon: {
        '57': 'resources/icons/Icon.png',
        '72': 'resources/icons/Icon~ipad.png',
        '114': 'resources/icons/Icon@2x.png',
        '144': 'resources/icons/Icon~ipad@2x.png'
    },

    isIconPrecomposed: true,

    startupImage: {
        '320x460': 'resources/startup/320x460.jpg',
        '640x920': 'resources/startup/640x920.png',
        '768x1004': 'resources/startup/768x1004.png',
        '748x1024': 'resources/startup/748x1024.png',
        '1536x2008': 'resources/startup/1536x2008.png',
        '1496x2048': 'resources/startup/1496x2048.png'
    },

    launch: function() {
        // Destroy the #appLoadingIndicator element
        Ext.fly('appLoadingIndicator').destroy();

        // Initialize the main view
        Ext.Viewport.add(Ext.create('RadioMobile.view.MainTabPanel'));
    },

    onUpdated: function() {
        Ext.Msg.confirm(
            "Application Update",
            "This application has just successfully been updated to the latest version. Reload now?",
            function(buttonId) {
                if (buttonId === 'yes') {
                    window.location.reload();
                }
            }
        );
    }
});

It shows a number of Sencha app.js concepts. The most important and original code is probably this block:

Ext.Loader.setConfig({
    enabled: true,
    paths: {
        'VP.util': 'app/util/VP'
    }
});

With that block of code I can put my utilities class named Util.js under a directory named app/util/VP, and then later refer to it in my code like this:

Ext.define('RadioMobile.controller.RadioStationsController', {
    extend: 'Ext.app.Controller',

    requires: [
        'VP.util.Util'
    ]
    
    // more code here ...
    
    // in some function ...
    var result = VP.util.Util.decodeJSON(conn.responseText);

Without that path configuration I couldn’t use the code this way.

Sencha Touch refs examples and documentation

I normally don’t like to throw large blocks of code out here, but the following Sencha Touch source code shows how to use the refs config parameter.

refs documentation

Before getting to the source code, here are the refs comments you’ll find in the code:

"In the refs configuration, you can set up references to view instances. This allows you to retrieve and manipulate components on the page inside of your controller’s actions."

and:

"refs create a reference to a component ... basically using Ext.ComponentQuery#down."

and:

"put a reference to a view instance (component) inside of a controller."

refs source code (examples)

Here’s the source code showing some refs in action:

Ext.define('RadioMobile.controller.TimeControlsController', {
    extend: 'Ext.app.Controller',

    requires: [
        'RadioMobile.view.TimeControlsPanel',
        'VP.util.Util'
    ],

    config: {

        views: [
            'TimeControlsPanel'
        ],

        // loginButton: '#loginWindow button[action=login]',

        // "In the refs configuration, you can set up references to view instances. 
        //     This allows you to retrieve and manipulate components on the page inside of your controller’s actions."
        // "refs create a reference to a component ... basically using Ext.ComponentQuery#down."
        // "put a reference to a view instance (component) inside of a controller."
        // localVarName : itemId
        refs: {
            timeControlsPanel:  'timeControlsPanel',
            volumeSlider:       '#timeControlsPanel #volumeSlider',
            btnPlayPause:       '#timeControlsPanel #btnPlayPause',
            btnBack30m:         '#timeControlsPanel #back30m',
            btnBack10m:         '#timeControlsPanel #back10m',
            btnBack5m:          '#timeControlsPanel #back5m',
            btnBack1m:          '#timeControlsPanel #back1m',
            btnBack10s:         '#timeControlsPanel #back10s',
            btnForward10s:      '#timeControlsPanel #forward10s',
            btnForward1m:       '#timeControlsPanel #forward1m',
            btnForward5m:       '#timeControlsPanel #forward5m',
            btnForward10m:      '#timeControlsPanel #forward10m',
            btnForward30m:      '#timeControlsPanel #forward30m'
        },

        // this is different in touch; i use an `init` method in ExtJS
        control: {
            volumeSlider:    { change: 'onVolumeSliderChange' },
            btnPlayPause:    { tap: 'onPlayPauseButtonTapped' },
            btnBack30m:      { tap: 'onBack30mTapped' },
            btnBack10m:      { tap: 'onBack10mTapped' },
            btnBack1m:       { tap: 'onBack1mTapped' },
            btnBack10s:      { tap: 'onBack10sTapped' },
            btnForward10s:   { tap: 'onForward10sTapped' },
            btnForward1m:    { tap: 'onForward1mTapped' },
            btnForward5m:    { tap: 'onForward5mTapped' },
            btnForward10m:   { tap: 'onForward10mTapped' },
            btnForward30m:   { tap: 'onForward30mTapped' }
        }

    },

    onBack30mTapped: function(button, e, eOpts) {
        var encoded = Ext.urlEncode({ value: '-1800' });
        VP.util.Util.callRestUrl('/server/seek?' + encoded, 'GET');
    },

    onBack10mTapped: function(button, e, eOpts) {
        var encoded = Ext.urlEncode({ value: '-600' });
        VP.util.Util.callRestUrl('/server/seek?' + encoded, 'GET');
    },

    onBack5mTapped: function(button, e, eOpts) {
        var encoded = Ext.urlEncode({ value: '-300' });
        VP.util.Util.callRestUrl('/server/seek?' + encoded, 'GET');
    },

    onBack1mTapped: function(button, e, eOpts) {
        var encoded = Ext.urlEncode({ value: '-60' });
        VP.util.Util.callRestUrl('/server/seek?' + encoded, 'GET');
    },

    onBack10sTapped: function(button, e, eOpts) {
        var encoded = Ext.urlEncode({ value: '-10' });
        VP.util.Util.callRestUrl('/server/seek?' + encoded, 'GET');
    },

    onForward10sTapped: function(button, e, eOpts) {
        var encoded = Ext.urlEncode({ value: '+10' });
        VP.util.Util.callRestUrl('/server/seek?' + encoded, 'GET');
    },

    onForward1mTapped: function(button, e, eOpts) {
        var encoded = Ext.urlEncode({ value: '+60' });
        VP.util.Util.callRestUrl('/server/seek?' + encoded, 'GET');
    },

    onForward5mTapped: function(button, e, eOpts) {
        var encoded = Ext.urlEncode({ value: '+300' });
        VP.util.Util.callRestUrl('/server/seek?' + encoded, 'GET');
    },

    onForward10mTapped: function(button, e, eOpts) {
        var encoded = Ext.urlEncode({ value: '+600' });
        VP.util.Util.callRestUrl('/server/seek?' + encoded, 'GET');
    },

    onForward30mTapped: function(button, e, eOpts) {
        var encoded = Ext.urlEncode({ value: '+1800' });
        VP.util.Util.callRestUrl('/server/seek?' + encoded, 'GET');
    },

    onPlayPauseButtonTapped: function(button, e, eOpts) {
        Ext.Ajax.request({
            url: '/server/turnEverythingOff',
            method: 'GET',
            success: function(conn, response, options, eOpts) {
                var result = VP.util.Util.decodeJSON(conn.responseText);
                if (result.success) {
                    // console.log('SUCCESS!');
                } else {
                    // console.log('ERROR!');
                    VP.util.Util.showErrorMsg(result.msg);
                }
            },
            failure: function(conn, response, options, eOpts) {
                // TODO get the 'msg' from the json and display it
                VP.util.Util.showErrorMsg(conn.responseText);
            }
        });
    },

    onVolumeSliderChange: function(slider, thumb, newValue, oldValue, eOpts) {
        Ext.Ajax.request({
            url: '/server/setVolume?volume=' + newValue,
            method: 'GET',
            success: function(conn, response, options, eOpts) {
                var result = VP.util.Util.decodeJSON(conn.responseText);
                if (result.success) {
                    // ignore
                } else {
                    VP.util.Util.showErrorMsg(result.msg);
                }
            },
            failure: function(conn, response, options, eOpts) {
                // TODO get the 'msg' from the json and display it
                VP.util.Util.showErrorMsg(conn.responseText);
            }
        });
    }

});

The refs documentation/comments come from a few different internet queries; sorry I don’t remember the original sources.

The Sencha Touch Panel/view

You can’t understand that refs code without also seeing the Sencha Touch Panel/view that it works with, so here’s that code as well:

Ext.define('RadioMobile.view.TimeControlsPanel', {
    extend: 'Ext.form.Panel',
    alias: 'widget.timeControlsPanel',

    requires: [
        'Ext.TitleBar',
        'Ext.slider.Slider',
        'Ext.dataview.List'
    ],

    // fullscreen: true,
    config: {
        xtype: 'timeControlsPanel',
        itemId: 'timeControlsPanel',
        title: 'Controls',
        iconCls: 'settings',
        scrollable: 'vertical',

        layout: {
            type: 'vbox',
            align: 'stretch',
            pack: 'start'
        },

        // defaults: {
        //     flex: 1
        // },
        items: [
            {
                docked: 'top',
                xtype: 'titlebar',
                title: 'Controls'
            },
            {
                xtype: 'container',
                layout: {
                    type: 'hbox',
                    pack: 'justify'
                },
                flex: 1,     // flex vertical height
                defaults: {
                    xtype: 'button',
                    flex: 1, // flex row width (buttons in the row)
                },
                items: [
                    {
                        text: '-30m',
                        itemId: 'back30m'
                    },
                    {
                        text: '-10m',
                        itemId: 'back10m'
                    },
                    {
                        text: '-5m',
                        itemId: 'back5m',
                    },
                    {
                        text: '-1m',
                        itemId: 'back1m',
                    },
                    {
                        text: '-10s',
                        itemId: 'back10s',
                    },
                ]
            },

            {
                xtype: 'container',
                layout: {
                    type: 'hbox'
                },
                flex: 1,
                defaults: {
                    xtype: 'button',
                    flex: 1, // flex row width (buttons in the row)
                },
                items: [
                    {
                        text: '>',
                        itemId: 'btnPlayPause',
                        tooltip: 'Play/Pause'
                    }
                ]
            },

            {
                xtype: 'container',
                layout: {
                    type: 'hbox'
                },
                flex: 1,
                defaults: {
                    xtype: 'button',
                    flex: 1, // flex row width (buttons in the row)
                },
                items: [
                    {
                        text: '10s',
                        itemId: 'forward10s'
                    },
                    {
                        text: '1m',
                        itemId: 'forward1m',
                    },
                    {
                        text: '5m',
                        itemId: 'forward5m',
                    },
                    {
                        text: '10m',
                        itemId: 'forward10m',
                    },
                    {
                        text: '30m',
                        itemId: 'forward30m',
                    }
                ]
            },
            {
                xtype: 'slider',
                itemId: 'volumeSlider',
                flex: 0.7,
                value: 60,
                increment: 5,
                minValue: 0,
                maxValue: 100,
                style: 'margin-top: 22px;',
            }
        ]
    }

});

That’s a lot of code to just throw out here like this, but if you needed to see a refs example (along with some documentation), I hope this helps.