/* * 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(); } }