VaadinTunesLayout.java
package com.vaadin.demo;

import com.vaadin.Application;
import com.vaadin.terminal.Sizeable;
import com.vaadin.terminal.ThemeResource;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.Embedded;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.HorizontalSplitPanel;
import com.vaadin.ui.Label;
import com.vaadin.ui.NativeButton;
import com.vaadin.ui.NativeSelect;
import com.vaadin.ui.Slider;
import com.vaadin.ui.Table;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;
import com.vaadin.ui.Window.Notification;

/**
 * Sample application layout, similar (almost identical) to Apple iTunes.
 
 @author IT Mill Ltd.
 
 */
@SuppressWarnings("serial")
public class VaadinTunesLayout extends Application {

    @Override
    public void init() {

        /*
         * We'll build the whole UI here, since the application will not contain
         * any logic. Otherwise it would be more practical to separate parts of
         * the UI into different classes and methods.
         */

        // Main (browser) window, needed in all Vaadin applications
        VerticalLayout rootLayout = new VerticalLayout();
        final Window root = new Window("VaadinTunes", rootLayout);

        /*
         * We'll attach the window to the browser view already here, so we won't
         * forget it later.
         */
        setMainWindow(root);

        root.showNotification(
                "This is an example of how you can do layouts in Vaadin.<br/>It is not a working sound player.",
                Notification.TYPE_HUMANIZED_MESSAGE);

        // Our root window contains one VerticalLayout, let's make
        // sure it's 100% sized, and remove unwanted margins
        rootLayout.setSizeFull();
        rootLayout.setMargin(false);

        // Top area, containing playback and volume controls, play status, view
        // modes and search
        HorizontalLayout top = new HorizontalLayout();
        top.setWidth("100%");
        top.setMargin(false, true, false, true)// Enable horizontal margins
        top.setSpacing(true);

        // Let's attach that one straight away too
        root.addComponent(top);

        // Create the placeholders for all the components in the top area
        HorizontalLayout playback = new HorizontalLayout();
        HorizontalLayout volume = new HorizontalLayout();
        HorizontalLayout status = new HorizontalLayout();
        HorizontalLayout viewmodes = new HorizontalLayout();
        ComboBox search = new ComboBox();

        // Add the components and align them properly
        top.addComponent(playback);
        top.addComponent(volume);
        top.addComponent(status);
        top.addComponent(viewmodes);
        top.addComponent(search);
        top.setComponentAlignment(playback, Alignment.MIDDLE_LEFT);
        top.setComponentAlignment(volume, Alignment.MIDDLE_LEFT);
        top.setComponentAlignment(status, Alignment.MIDDLE_CENTER);
        top.setComponentAlignment(viewmodes, Alignment.MIDDLE_LEFT);
        top.setComponentAlignment(search, Alignment.MIDDLE_LEFT);

        /*
         * We want our status area to expand if the user resizes the root
         * window, and we want it to accommodate as much space as there is
         * available. All other components in the top layout should stay fixed
         * sized, so we don't need to specify any expand ratios for them (they
         * will automatically revert to zero after the following line).
         */
        top.setExpandRatio(status, 1.0F);

        // Playback controls
        Button prev = new NativeButton("Previous");
        Button play = new NativeButton("Play/pause");
        Button next = new NativeButton("Next");
        playback.addComponent(prev);
        playback.addComponent(play);
        playback.addComponent(next);
        // Set spacing between the buttons
        playback.setSpacing(true);

        // Volume controls
        Button mute = new NativeButton("mute");
        Slider vol = new Slider();
        vol.setOrientation(Slider.ORIENTATION_HORIZONTAL);
        vol.setWidth("100px");
        Button max = new NativeButton("max");
        volume.addComponent(mute);
        volume.addComponent(vol);
        volume.addComponent(max);

        // Status area
        status.setWidth("80%");
        status.setSpacing(true);

        Button toggleVisualization = new NativeButton("Mode");
        Label timeFromStart = new Label("0:00");

        // We'll need another layout to show currently playing track and
        // progress
        VerticalLayout trackDetails = new VerticalLayout();
        trackDetails.setWidth("100%");
        Label track = new Label("Track Name");
        Label album = new Label("Album Name - Artist");
        track.setWidth(null);
        album.setWidth(null);
        Slider progress = new Slider();
        progress.setOrientation(Slider.ORIENTATION_HORIZONTAL);
        progress.setWidth("100%");
        trackDetails.addComponent(track);
        trackDetails.addComponent(album);
        trackDetails.addComponent(progress);
        trackDetails.setComponentAlignment(track, Alignment.TOP_CENTER);
        trackDetails.setComponentAlignment(album, Alignment.TOP_CENTER);

        Label timeToEnd = new Label("-4:46");
        Button jumpToTrack = new NativeButton("Show");

        // Place all components to the status layout and align them properly
        status.addComponent(toggleVisualization);
        status.setComponentAlignment(toggleVisualization, Alignment.MIDDLE_LEFT);
        status.addComponent(timeFromStart);
        status.setComponentAlignment(timeFromStart, Alignment.BOTTOM_LEFT);
        status.addComponent(trackDetails);
        status.addComponent(timeToEnd);
        status.setComponentAlignment(timeToEnd, Alignment.BOTTOM_LEFT);
        status.addComponent(jumpToTrack);
        status.setComponentAlignment(jumpToTrack, Alignment.MIDDLE_LEFT);

        // Then remember to specify the expand ratio
        status.setExpandRatio(trackDetails, 1.0F);

        // View mode buttons
        Button viewAsTable = new NativeButton("Table");
        Button viewAsGrid = new NativeButton("Grid");
        Button coverflow = new NativeButton("Coverflow");
        viewmodes.addComponent(viewAsTable);
        viewmodes.addComponent(viewAsGrid);
        viewmodes.addComponent(coverflow);

        /*
         * That covers the top bar. Now let's move on to the sidebar and track
         * listing
         */

        // We'll need one splitpanel to separate the sidebar and track listing
        HorizontalSplitPanel bottom = new HorizontalSplitPanel();
        root.addComponent(bottom);

        // The splitpanel is by default 100% x 100%, but we'll need to adjust
        // our main window layout to accomodate the height
        ((VerticalLayoutroot.getContent()).setExpandRatio(bottom, 1.0F);

        // Give the sidebar less space than the listing
        bottom.setSplitPosition(200, Sizeable.UNITS_PIXELS);

        // Let's add some content to the sidebar
        // First, we need a layout to but all components in
        VerticalLayout sidebar = new VerticalLayout();
        sidebar.setSizeFull();
        bottom.setFirstComponent(sidebar);

        /*
         * Then we need some labels and buttons, and an album cover image The
         * labels and buttons go into their own vertical layout, since we want
         * the 'sidebar' layout to be expanding (cover image in the bottom).
         * VerticalLayout is by default 100% wide.
         */
        VerticalLayout selections = new VerticalLayout();
        Label library = new Label("Library");
        Button music = new NativeButton("Music");
        music.setWidth("100%");

        Label store = new Label("Store");
        Button vaadinTunesStore = new NativeButton("VaadinTunes Store");
        vaadinTunesStore.setWidth("100%");
        Button purchased = new NativeButton("Purchased");
        purchased.setWidth("100%");

        Label playlists = new Label("Playlists");
        Button genius = new NativeButton("Geniues");
        genius.setWidth("100%");
        Button recent = new NativeButton("Recently Added");
        recent.setWidth("100%");

        // Lets add them to the 'selections' layout
        selections.addComponent(library);
        selections.addComponent(music);
        selections.addComponent(store);
        selections.addComponent(vaadinTunesStore);
        selections.addComponent(purchased);
        selections.addComponent(playlists);
        selections.addComponent(genius);
        selections.addComponent(recent);

        // Then add the selections to the sidebar, and set it expanding
        sidebar.addComponent(selections);
        sidebar.setExpandRatio(selections, 1.0F);

        // Then comes the cover artwork (we'll add the actual image in the
        // themeing section)
        Embedded cover = new Embedded("Currently Playing");
        sidebar.addComponent(cover);

        /*
         * And lastly, we need the track listing table It should fill the whole
         * left side of our bottom layout
         */
        Table listing = new Table();
        listing.setSizeFull();
        listing.setSelectable(true);
        bottom.setSecondComponent(listing);

        // Add the table headers
        listing.addContainerProperty("Name", String.class, "");
        listing.addContainerProperty("Time", String.class, "0:00");
        listing.addContainerProperty("Artist", String.class, "");
        listing.addContainerProperty("Album", String.class, "");
        listing.addContainerProperty("Genre", String.class, "");
        listing.addContainerProperty("Rating", NativeSelect.class,
                new NativeSelect());

        // Lets populate the table with random data
        String[] tracks = new String[] { "Red Flag""Millstone",
                "Not The Sun""Breath""Here We Are""Deep Heaven",
                "Her Voice Resides""Natural Tan""End It All""Kings",
                "Daylight Slaving""Mad Man""Resolve""Teargas",
                "African Air""Passing Bird" };
        String[] times = new String[] { "4:12""6:03""5:43""4:32""3:42",
                "4:45""2:56""9:34""2:10""3:44""5:49""6:30""5:18",
                "7:42""3:13""2:52" };
        String[] artists = new String[] { "Billy Talent""Brand New",
                "Breaking Benjamin""Becoming The Archetype",
                "Bullet For My Valentine""Chasing Victory""Chimaira",
                "Danko Jones""Deadlock""Deftones""From Autumn To Ashes",
                "Haste The Day""Four Year Strong""In Flames""Kemopetrol",
                "John Legend" };
        String[] albums = new String[] { "Once Again""The Caitiff Choir",
                "The Devil And God""Light Grenades""Dicthonomy",
                "Back In Black""Dreamer""Come Clarity""Year Zero",
                "Frames""Fortress""Phobia""The Poison""Manifesto",
                "White Pony""The Big Dirty" };
        String[] genres = new String[] { "Rock""Metal""Hardcore""Indie",
                "Pop""Alternative""Blues""Jazz""Hip Hop",
                "Electronica""Punk""Hard Rock""Dance""R'n'B""Gospel",
                "Country" };
        for (int i = 0; i < 1000; i++) {
            NativeSelect s = new NativeSelect();
            s.addItem("1 star");
            s.addItem("2 stars");
            s.addItem("3 stars");
            s.addItem("4 stars");
            s.addItem("5 stars");
            s.select(i % " stars");
            final int index = i % 16;
            listing.addItem(new Object[] { tracks[index], times[index],
                    artists[index], albums[index], genres[index], s }, i);
        }

        // We'll align the track time column to right as well
        listing.setColumnAlignment("Time", Table.ALIGN_RIGHT);

        // TODO the footer

        // Now what's left to do? Themeing of course.
        setTheme("vaadintunes");

        /*
         * Let's give a namespace to our application window. This way, if
         * someone uses the same theme for different applications, we don't get
         * unwanted style conflicts.
         */
        root.setStyleName("tTunes");

        top.setStyleName("top");
        top.setHeight("75px")// Same as the background image height

        playback.setStyleName("playback");
        playback.setMargin(false, true, false, false)// Add right-side margin
        play.setStyleName("play");
        next.setStyleName("next");
        prev.setStyleName("prev");
        playback.setComponentAlignment(prev, Alignment.MIDDLE_LEFT);
        playback.setComponentAlignment(next, Alignment.MIDDLE_LEFT);

        volume.setStyleName("volume");
        mute.setStyleName("mute");
        max.setStyleName("max");
        vol.setWidth("78px");

        status.setStyleName("status");
        status.setMargin(true);
        status.setHeight("46px")// Height of the background image

        toggleVisualization.setStyleName("toggle-vis");
        jumpToTrack.setStyleName("jump");

        viewAsTable.setStyleName("viewmode-table");
        viewAsGrid.setStyleName("viewmode-grid");
        coverflow.setStyleName("viewmode-coverflow");

        sidebar.setStyleName("sidebar");

        music.setStyleName("selected");

        cover.setSource(new ThemeResource("images/album-cover.jpg"));
        // Because this is an image, it will retain it's aspect ratio
        cover.setWidth("100%");
    }

}