/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.motorola.studio.android.emulator.device.ui;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.util.ArrayList;
import java.util.Collection;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import com.motorola.studio.android.common.log.StudioLogger;
import com.motorola.studio.android.emulator.core.exception.SkinException;
import com.motorola.studio.android.emulator.core.skin.IAndroidSkin;
import com.motorola.studio.android.emulator.core.skin.ISkinKeyXmlTags;
import com.motorola.studio.android.emulator.i18n.EmulatorNLS;
public class DpiScaleCalculatorDialog extends Dialog
{
private Text screenSizeValue;
private Button monitorDpiValueButton;
private Text monitorDpiValue;
private Text monitorSizeText;
private Text resultDpivalueText;
private Integer resultDpiValue;
private Label resultScaleText;
private Double resultScaleValue;
private Text resultScaleValueText;
private Label errorLabel;
private final IAndroidSkin skin;
private final Collection<String> errors = new ArrayList<String>();
int size1 = -1;
int size2 = -1;
/**
* The Dialog constructor
*
* @param parentShell The shell
* @param skin The selected skin of the AVD being created/edited
*/
protected DpiScaleCalculatorDialog(Shell parentShell, IAndroidSkin skin)
{
super(parentShell);
this.skin = skin;
}
/*
* (non-Javadoc)
* @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
*/
@Override
protected void configureShell(Shell newShell)
{
super.configureShell(newShell);
newShell.setText(EmulatorNLS.DPISCALECALCULATOR_Title);
}
/*
* (non-Javadoc)
* @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite)
*/
@Override
protected Control createDialogArea(Composite parent)
{
//Main Composite
Composite mainComposite = new Composite(parent, SWT.FILL);
mainComposite.setLayout(new GridLayout(2, false));
GridData data;
//Error Area
errorLabel = new Label(mainComposite, SWT.READ_ONLY);
errorLabel.setForeground(new Color(null, 255, 0, 0));
data = new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1);
errorLabel.setLayoutData(data);
//Screen Size
Label screenSizeLabel = new Label(mainComposite, SWT.READ_ONLY);
screenSizeLabel.setText(EmulatorNLS.DPISCALECALCULATOR_ScreenSize_Label);
data = new GridData(SWT.LEFT, SWT.CENTER, false, false);
screenSizeLabel.setLayoutData(data);
screenSizeValue = new Text(mainComposite, SWT.BORDER);
data = new GridData(SWT.FILL, SWT.NULL, true, false);
screenSizeValue.setLayoutData(data);
screenSizeValue.addModifyListener(new ModifyListener()
{
public void modifyText(ModifyEvent e)
{
validate();
}
});
//Monitor DPI Group
Group monitorDpiGroup = new Group(mainComposite, SWT.SHADOW_OUT);
monitorDpiGroup.setText(EmulatorNLS.DPISCALECALCULATOR_MonitorDpi_Label);
data = new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1);
monitorDpiGroup.setLayoutData(data);
monitorDpiGroup.setLayout(new GridLayout(3, false));
//Insert Monitor DPI value Option
monitorDpiValueButton = new Button(monitorDpiGroup, SWT.RADIO);
monitorDpiValueButton.setText(EmulatorNLS.DPISCALECALCULATOR_MonitorDpivalue_Label);
monitorDpiValueButton.setSelection(true);
monitorDpiValueButton.addSelectionListener(new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent e)
{
monitorDpiValue.setEnabled(monitorDpiValueButton.getSelection());
validate();
}
});
data = new GridData(SWT.LEFT, SWT.TOP, false, false, 1, 1);
monitorDpiValueButton.setLayoutData(data);
monitorDpiValue = new Text(monitorDpiGroup, SWT.SINGLE | SWT.BORDER);
data = new GridData(SWT.FILL, SWT.TOP, true, false, 2, 1);
data.widthHint = 100;
monitorDpiValue.setLayoutData(data);
monitorDpiValue.setEnabled(monitorDpiValueButton.getSelection());
monitorDpiValue.addModifyListener(new ModifyListener()
{
public void modifyText(ModifyEvent e)
{
validate();
}
});
//Calculate Monitor DPI Option
final Button calculateMonitorDpiButton = new Button(monitorDpiGroup, SWT.RADIO);
calculateMonitorDpiButton.setText(EmulatorNLS.DPISCALECALCULATOR_MonitorDpiSize_Label);
calculateMonitorDpiButton.setSelection(false);
calculateMonitorDpiButton.addSelectionListener(new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent e)
{
monitorSizeText.setEnabled(calculateMonitorDpiButton.getSelection());
validate();
}
});
monitorSizeText = new Text(monitorDpiGroup, SWT.SINGLE | SWT.BORDER);
data = new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1);
monitorSizeText.setLayoutData(data);
monitorSizeText.setEnabled(calculateMonitorDpiButton.getSelection());
monitorSizeText.addModifyListener(new ModifyListener()
{
public void modifyText(ModifyEvent e)
{
validate();
}
});
//Result Group
Group resultGroup = new Group(mainComposite, SWT.SHADOW_OUT);
resultGroup.setText(EmulatorNLS.DPISCALECALCULATOR_ResultGroup_Title);
data = new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1);
resultGroup.setLayoutData(data);
resultGroup.setLayout(new GridLayout(4, false));
//Moitor DPI
Label resultDpi = new Label(resultGroup, SWT.READ_ONLY);
resultDpi.setText(EmulatorNLS.DPISCALECALCULATOR_ResultMonitorDpi_Label);
data = new GridData(SWT.LEFT, SWT.CENTER, false, false);
resultDpi.setLayoutData(data);
resultDpivalueText = new Text(resultGroup, SWT.WRAP | SWT.READ_ONLY);
data = new GridData(SWT.FILL, SWT.NULL, true, false);
resultDpivalueText.setLayoutData(data);
//Scale
resultScaleText = new Label(resultGroup, SWT.READ_ONLY);
resultScaleText.setText(EmulatorNLS.DPISCALECALCULATOR_ResultScale_Label);
data = new GridData(SWT.LEFT, SWT.CENTER, false, false);
resultScaleText.setLayoutData(data);
resultScaleValueText = new Text(resultGroup, SWT.WRAP | SWT.READ_ONLY);
data = new GridData(SWT.FILL, SWT.NULL, true, false);
resultScaleValueText.setLayoutData(data);
mainComposite.layout();
mainComposite.pack();
return null;
}
/**
* Updates the Monitor DPI and Scale results
*
*/
private void updateResult()
{
if (monitorDpiValueButton.getSelection())
{
resultDpiValue = Integer.parseInt(monitorDpiValue.getText());
}
else
{
resultDpiValue = calculateMonitorDpi();
}
resultDpivalueText.setText(resultDpiValue.toString());
resultScaleValue = calculateScale();
resultScaleValueText.setText(resultScaleValue.toString());
}
/**
* Calculates the Monitor DPI using the user monitor size and the resolution
*
* @return int The calculated Monitor DPI
*/
private int calculateMonitorDpi()
{
float monitorSize = Float.parseFloat(monitorSizeText.getText());
Dimension b = Toolkit.getDefaultToolkit().getScreenSize();
float width = b.width;
float height = b.height;
float ratio = width / height;
double dpi =
Math.round((width / (ratio * (Math.sqrt((Math.pow(monitorSize, 2))
/ (1f + Math.pow(ratio, 2)))))));
return (int) dpi;
}
/**
* Calculates the scale to be used using the monitor dpi, the device screen size and the skin main display dimensions
*
* @return
*/
private double calculateScale()
{
double dpi = resultDpiValue;
if ((skin != null) && (size1 == -1) && (size2 == -1))
{
try
{
Collection<String> layouts = skin.getAvailableLayouts();
String defLayout = layouts.toArray()[0].toString();
size1 =
skin.getSkinBean(defLayout).getSkinPropertyValue(
ISkinKeyXmlTags.SKIN_INTERNAL_VIEW_WIDTH);
size2 =
skin.getSkinBean(defLayout).getSkinPropertyValue(
ISkinKeyXmlTags.SKIN_INTERNAL_VIEW_HEIGHT);
}
catch (SkinException e)
{
StudioLogger.error(DpiScaleCalculatorDialog.class, "Error while calculating scale", //$NON-NLS-1$
e);
}
}
if ((size1 > 0) && (size2 > 0))
{
double diagonalPx = Math.sqrt(Math.pow(size1, 2) + Math.pow(size2, 2));
double screenSize = Double.parseDouble(screenSizeValue.getText());
double scale = (screenSize * dpi) / diagonalPx;
return (Math.round((scale * 100.0))) / 100.0;
}
else
{
getButton(IDialogConstants.OK_ID).setEnabled(false);
}
return 1;
}
/**
* Validates all the calculator fields
*/
public void validate()
{
final String REGEX_1 = EmulatorNLS.DPISCALECALCULATOR_Regex_TwoDigits;
final String REGEX_2 = "\\d+"; //$NON-NLS-1$
final String ERROR_SCREEN_SIZE = EmulatorNLS.DPISCALECALCULATOR_Error_ScreenSize;
final String ERROR_DPI_VALUE = EmulatorNLS.DPISCALECALCULATOR_Error_MonitorDpi;
final String ERROR_MONITOR_SIZE = EmulatorNLS.DPISCALECALCULATOR_Error_MonitorSize;
errors.clear();
errorLabel.setText(""); //$NON-NLS-1$
if (!screenSizeValue.getText().matches(REGEX_1))
{
errors.add(ERROR_SCREEN_SIZE);
}
if (monitorDpiValueButton.getSelection() && !monitorDpiValue.getText().matches(REGEX_2))
{
errors.add(ERROR_DPI_VALUE);
}
if (!monitorDpiValueButton.getSelection() && !monitorSizeText.getText().matches(REGEX_1))
{
errors.add(ERROR_MONITOR_SIZE);
}
if (errors.size() > 0)
{
getButton(OK).setEnabled(false);
errorLabel.setText((String) errors.toArray()[0]);
errorLabel.pack();
resultDpivalueText.setText(""); //$NON-NLS-1$
resultScaleValueText.setText(""); //$NON-NLS-1$
}
else
{
getButton(OK).setEnabled(true);
updateResult();
}
}
/**
* Gets the calculated device dpi
*
* @return the device dpi to be used
*/
public String getResultDpivalue()
{
return resultDpiValue.toString();
}
/**
* Gets the calculated scale
*
* @return the scale to be used
*/
public String getResultScaleValue()
{
return resultScaleValue.toString();
}
}