/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
package javax.microedition.lcdui;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.internal.extension.Style;
/**
* Class for layouting gauges.
*/
class GaugeLayouter extends ItemLayouter
{
/**
* Key name for selection listener.
*/
private static final String SELECTION_LISTENER = "selection";
/**
* Constructor.
*
* @param aFormLayouter FormLayouter used for layouting.
*/
GaugeLayouter(FormLayouter aFormLayouter)
{
super(aFormLayouter);
}
/**
* Creates the eSWT ProgressBar/Slider for this item.
*/
Control eswtGetControl(Composite parent, Item item)
{
return eswtCreateControl(parent, item);
}
/**
* Construts a gauge control surrounded with composite.
*/
static Control eswtCreateControl(Composite parent, Item item)
{
Gauge gauge = (Gauge) item;
// create an owning composite every time
Composite comp = new Composite(parent, SWT.NONE);
if(gauge.isInteractive())
{
FormLayout layout = new FormLayout();
layout.marginBottom = Style.pixelMetric(Style.QSTYLE_PM_LAYOUTBOTTOMMARGIN);
layout.marginTop = Style.pixelMetric(Style.QSTYLE_PM_LAYOUTTOPMARGIN);
layout.marginLeft = Style.pixelMetric(Style.QSTYLE_PM_LAYOUTLEFTMARGIN);
layout.marginRight = Style.pixelMetric(Style.QSTYLE_PM_LAYOUTRIGHTMARGIN);
layout.spacing = Style.pixelMetric(Style.QSTYLE_PM_LAYOUTVERTICALSPACING);
comp.setLayout(layout);
// Current Value - Mutable Value
Label currentlabel = new Label(comp, SWT.WRAP);
currentlabel.setText(Integer.toString(gauge.getValue()));
currentlabel.setAlignment(SWT.LEAD);
FormData currLabelData = new FormData();
currLabelData.left = new FormAttachment(0);
currentlabel.setLayoutData(currLabelData);
Slider slider = new Slider(comp, SWT.HORIZONTAL);
slider.setMinimum(0);
slider.setMaximum(gauge.getMaxValue() + 1);
slider.setSelection(gauge.getValue());
slider.setIncrement(1);
slider.setPageIncrement(1);
FormData SliderLayoutData = new FormData();
SliderLayoutData.right = new FormAttachment(100);
SliderLayoutData.left = new FormAttachment(currentlabel);
slider.setLayoutData(SliderLayoutData);
// Min Value
Label minlabel = new Label(comp, SWT.WRAP);
minlabel.setText("0");
minlabel.setAlignment(SWT.LEAD);
FormData minLabelData = new FormData();
minLabelData.left = new FormAttachment(slider, 0, SWT.LEFT);
minLabelData.top = new FormAttachment(slider);
minlabel.setLayoutData(minLabelData);
// Max Value
Label maxlabel = new Label(comp, SWT.WRAP);
maxlabel.setText(Integer.toString(gauge.getMaxValue()));
maxlabel.setAlignment(SWT.LEAD);
FormData maxLabelData = new FormData();
maxLabelData.right = new FormAttachment(slider, 0, SWT.RIGHT);
maxLabelData.top = new FormAttachment(slider);
maxlabel.setLayoutData(maxLabelData);
}
else
{
ProgressBar progressBar = null;
if(gauge.isIndefinite())
{
switch(gauge.getValue())
{
case Gauge.CONTINUOUS_IDLE:
// TODO: eSWT support required
// Gauge like busy-state indicator with no activity:
progressBar = new ProgressBar(comp,
SWT.HORIZONTAL | SWT.INDETERMINATE);
break;
case Gauge.CONTINUOUS_RUNNING:
// Gauge like busy-state indicator:
progressBar = new ProgressBar(comp,
SWT.HORIZONTAL | SWT.INDETERMINATE);
break;
case Gauge.INCREMENTAL_IDLE:
// TODO: eSWT support required
// Gauge like INCREMENTAL_UPDATING, but no activity.
progressBar = new ProgressBar(comp,
SWT.HORIZONTAL | SWT.INDETERMINATE);
break;
case Gauge.INCREMENTAL_UPDATING:
// TODO: eSWT support required
// Gauge which is updated on calling Gauge.setValue().
progressBar = new ProgressBar(comp,
SWT.HORIZONTAL | SWT.INDETERMINATE);
break;
default:
// This is error and will cause NullPointerException
// later in this method. Gauge-class takes care that
// this is never executed.
Logger.warning("Unexpected gauge value: " + gauge.getValue());
break;
}
}
else
{
progressBar = new ProgressBar(comp, SWT.HORIZONTAL);
progressBar.setMaximum(gauge.getMaxValue() + 1);
progressBar.setSelection(gauge.getValue());
}
}
return comp;
}
/**
* Set the size of the layouted Control.
*/
void eswtResizeControl(Item item, Control control, int width, int height)
{
super.eswtResizeControl(item, control, width, height);
control.getParent().setSize(width, height);
// This will move gauge to the center of the screen:
control.setLocation((width - control.getBounds().width) / 2,
control.getLocation().y);
}
/**
* Add listeners to Layouter specific control.
*/
void eswtAddSpecificListeners(Item item, Control control)
{
super.eswtAddSpecificListeners(item, control);
Gauge gauge = (Gauge) item;
if(gauge.isInteractive())
{
Slider slider = (Slider) control;
SelectionListener listener = new GaugeSelectionListener(gauge);
slider.addSelectionListener(listener);
slider.setData(SELECTION_LISTENER, listener);
}
}
/**
* Remove listeners from Layouter specific control.
*/
void eswtRemoveSpecificListeners(Item item, Control control)
{
super.eswtRemoveSpecificListeners(item, control);
Gauge gauge = (Gauge) item;
if(gauge.isInteractive())
{
Slider slider = (Slider) control;
SelectionListener listener = (SelectionListener) slider
.getData(SELECTION_LISTENER);
if(listener != null)
{
slider.removeSelectionListener(listener);
slider.setData(SELECTION_LISTENER, null);
}
}
}
/**
* Returns if this eSWT control is Layouter specific.
*/
boolean eswtIsSpecificControl(Item item, Control control)
{
if(((Gauge) item).isInteractive())
{
return (control instanceof Slider);
}
else
{
return (control instanceof ProgressBar);
}
}
/**
* Updates the values of Gauge.
*/
void eswtUpdateItem(Item item, Control control, int reason, Object param)
{
Gauge gauge = (Gauge) item;
if(control instanceof ProgressBar)
{
((ProgressBar) control).setMaximum(gauge.getMaxValue() + 1);
((ProgressBar) control).setSelection(gauge.getValue());
}
else if(control instanceof Slider)
{
((Slider) control).setMaximum(gauge.getMaxValue() + 1);
((Slider) control).setSelection(gauge.getValue());
}
}
/**
* Returns true if that key was consumed by Gauge.
*/
boolean eswtOfferKeyPressed(Item item, int key)
{
Gauge gauge = (Gauge) item;
if(gauge.isInteractive())
{
if(key == SWT.ARROW_RIGHT)
{
gauge.internalSetValue(gauge.getValue() + 1);
gauge.setLayout(gauge.internalGetLayout());
}
else if(key == SWT.ARROW_LEFT)
{
gauge.internalSetValue(gauge.getValue() -1);
gauge.setLayout(gauge.internalGetLayout());
}
return true;
}
return false;
}
/**
* Returns the minimum area needed to display a Gauge.
*
* @param gauge Gauge object.
* @return Minimum area needed to display Gauge.
*/
static Point calculateMinimumBounds(final Gauge gauge)
{
final Point minSize = new Point(0, 0);
ESWTUIThreadRunner.syncExec(new Runnable()
{
public void run()
{
Control comp = eswtCreateControl(eswtGetStaticShell(), gauge);
minSize.x = getMaximumItemWidth(gauge);
minSize.y = ((Composite) comp).computeSize(minSize.x, SWT.DEFAULT).y;
applyMinMargins(gauge, minSize);
comp.dispose();
}
});
return minSize;
}
/**
* Returns the preferred area needed to display an Item.
*
* @param item Item.
* @return Preferred area needed to display Item. x is width
* and y is height.
*/
static Point calculatePreferredBounds(Item item)
{
final Point prefSize = new Point(0, 0);
final Gauge gauge = (Gauge)item;
ESWTUIThreadRunner.syncExec(new Runnable()
{
public void run()
{
Control comp = eswtCreateControl(eswtGetStaticShell(), gauge);
prefSize.x = getMaximumItemWidth(gauge);
prefSize.y = ((Composite) comp).computeSize(prefSize.x, SWT.DEFAULT).y;
applyPrefMargins(gauge, prefSize);
comp.dispose();
}
});
return prefSize;
}
/**
* Class that receives events from slider and updates gauge's value.
*/
class GaugeSelectionListener implements SelectionListener
{
private Gauge gauge;
/**
* Constructor.
* @param gauge Gauge to be updated.
*/
public GaugeSelectionListener(Gauge gauge)
{
this.gauge = gauge;
}
public void widgetDefaultSelected(SelectionEvent e) { }
/**
* Called by eSWT when Slider's value is changed.
* Updates Gauge's value.
*/
public void widgetSelected(SelectionEvent e)
{
int newValue = ((Slider) e.getSource()).getSelection();
// Actions needed only if value is adjusted:
if(newValue != gauge.getValue())
{
// set Gauge value
gauge.internalSetValue(newValue);
gauge.setLayout(gauge.internalGetLayout());
}
}
}
}