Meters

Meters are used to report progress to the user, generally the completion percentage of a background task such as a file load operation. An example is shown below. Clicking the Start button initiates a background task that simulates a long-running operation. Periodically, the task updates the meter to reflect its progress:

The BXML source for the example is shown below:

            
            <progress:Meters title="Meters" maximized="true"
                xmlns:bxml="http://pivot.apache.org/bxml"
                xmlns:progress="org.apache.pivot.tutorials.progress"
                xmlns="org.apache.pivot.wtk">
                <TablePane>
                    <columns>
                        <TablePane.Column width="1*"/>
                    </columns>

                    <TablePane.Row height="1*">
                        <Border styles="{padding:2}">
                            <BoxPane styles="{horizontalAlignment:'center', verticalAlignment:'center'}">
                                <Label text="Progress:"/>
                                <Meter bxml:id="meter" preferredWidth="200" preferredHeight="16"/>
                            </BoxPane>
                        </Border>
                    </TablePane.Row>

                    <TablePane.Row height="-1">
                        <BoxPane styles="{horizontalAlignment:'center', padding:6}">
                            <PushButton bxml:id="progressButton" styles="{minimumAspectRatio:3}"/>
                        </BoxPane>
                    </TablePane.Row>
                </TablePane>
            </progress:Meters>
            
        

The Java source is as follows. The main window class defines an inner class that extends the org.apache.pivot.util.concurrent.Task class to simulate a background operation. This task simply sleeps for 100ms at a time and updates the meter when it wakes up to reflect the current count. Since all UI updates must be performed on the UI thread, the task queues a callback to set the meter's percent complete; a org.apache.pivot.wtk.TaskAdapter is used to process the task notifications for the same reason:

            
            package org.apache.pivot.tutorials.progress;

            import java.net.URL;

            import org.apache.pivot.beans.Bindable;
            import org.apache.pivot.collections.Map;
            import org.apache.pivot.util.Resources;
            import org.apache.pivot.util.concurrent.Task;
            import org.apache.pivot.util.concurrent.TaskExecutionException;
            import org.apache.pivot.util.concurrent.TaskListener;
            import org.apache.pivot.wtk.ApplicationContext;
            import org.apache.pivot.wtk.Button;
            import org.apache.pivot.wtk.ButtonPressListener;
            import org.apache.pivot.wtk.Meter;
            import org.apache.pivot.wtk.PushButton;
            import org.apache.pivot.wtk.TaskAdapter;
            import org.apache.pivot.wtk.Window;

            public class Meters extends Window implements Bindable {
                public class SampleTask extends Task<Void> {
                    private int percentage = 0;

                    @Override
                    public Void execute() throws TaskExecutionException {
                        // Simulate a long-running operation
                        percentage = 0;

                        while (percentage < 100
                            && !abort) {
                            try {
                                Thread.sleep(100);
                                percentage++;

                                // Update the meter on the UI thread
                                ApplicationContext.queueCallback(new Runnable() {
                                    @Override
                                    public void run() {
                                        meter.setPercentage((double)percentage / 100);
                                    }
                                });
                            } catch(InterruptedException exception) {
                                throw new TaskExecutionException(exception);
                            }
                        }

                        return null;
                    }
                }

                private Meter meter = null;
                private PushButton progressButton = null;

                private SampleTask sampleTask = null;

                @Override
                public void initialize(Map<String, Object> namespace, URL location, Resources resources) {
                    meter = (Meter)namespace.get("meter");
                    progressButton = (PushButton)namespace.get("progressButton");

                    progressButton.getButtonPressListeners().add(new ButtonPressListener() {
                        @Override
                        public void buttonPressed(Button button) {
                            if (sampleTask == null) {
                                // Create and start the simulated task; wrap it in a
                                // task adapter so the result handlers are called on the
                                // UI thread
                                sampleTask = new SampleTask();
                                sampleTask.execute(new TaskAdapter<Void>(new TaskListener<Void>() {
                                    @Override
                                    public void taskExecuted(Task<Void> task) {
                                        reset();
                                    }

                                    @Override
                                    public void executeFailed(Task<Void> task) {
                                        reset();
                                    }

                                    private void reset() {
                                        // Reset the meter and button
                                        sampleTask = null;
                                        meter.setPercentage(0);
                                        updateProgressButton();
                                    }
                                }));
                            } else {
                                // Cancel the task
                                sampleTask.abort();
                            }

                            updateProgressButton();
                        }
                    });

                    updateProgressButton();
                }

                private void updateProgressButton() {
                    if (sampleTask == null) {
                        progressButton.setButtonData("Start");
                    } else {
                        progressButton.setButtonData("Cancel");
                    }
                }
            }
            
        

Next: Activity Indicators