• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.android.ide.eclipse.adt.internal.editors.layout.configuration;
2 
3 import com.android.ide.eclipse.adt.internal.editors.IconFactory;
4 import com.android.ide.eclipse.adt.internal.resources.configurations.FolderConfiguration;
5 import com.android.ide.eclipse.adt.internal.resources.configurations.LanguageQualifier;
6 import com.android.ide.eclipse.adt.internal.resources.configurations.RegionQualifier;
7 import com.android.ide.eclipse.adt.internal.resources.configurations.ResourceQualifier;
8 import com.android.ide.eclipse.adt.internal.resources.configurations.VersionQualifier;
9 import com.android.ide.eclipse.adt.internal.sdk.LayoutDevice;
10 import com.android.ide.eclipse.adt.internal.ui.ConfigurationSelector;
11 import com.android.ide.eclipse.adt.internal.ui.ConfigurationSelector.ConfigurationState;
12 import com.android.ide.eclipse.adt.internal.ui.ConfigurationSelector.IQualifierFilter;
13 import com.android.sdkuilib.ui.GridDialog;
14 
15 import org.eclipse.jface.dialogs.Dialog;
16 import org.eclipse.jface.dialogs.IDialogConstants;
17 import org.eclipse.swt.SWT;
18 import org.eclipse.swt.events.ModifyEvent;
19 import org.eclipse.swt.events.ModifyListener;
20 import org.eclipse.swt.events.VerifyEvent;
21 import org.eclipse.swt.events.VerifyListener;
22 import org.eclipse.swt.graphics.Image;
23 import org.eclipse.swt.layout.GridData;
24 import org.eclipse.swt.layout.GridLayout;
25 import org.eclipse.swt.widgets.Composite;
26 import org.eclipse.swt.widgets.Control;
27 import org.eclipse.swt.widgets.Group;
28 import org.eclipse.swt.widgets.Label;
29 import org.eclipse.swt.widgets.Shell;
30 import org.eclipse.swt.widgets.Text;
31 
32 import java.util.regex.Pattern;
33 
34 /**
35  * Dialog to edit both a {@link LayoutDevice}, and a {@link FolderConfiguration} at the same time.
36  */
37 public class ConfigEditDialog extends GridDialog {
38 
39     private static final Pattern FLOAT_PATTERN = Pattern.compile("\\d*(\\.\\d?)?");
40 
41 
42     private final FolderConfiguration mConfig = new FolderConfiguration();
43 
44     private ConfigurationSelector mConfigSelector;
45     private Composite mStatusComposite;
46     private Label mStatusLabel;
47     private Label mStatusImage;
48 
49     private Image mError;
50 
51     private String mDeviceName;
52     private String mConfigName;
53     private float mXDpi = Float.NaN;
54     private float mYDpi = Float.NaN;
55 
56 
ConfigEditDialog(Shell parentShell, FolderConfiguration config)57     public ConfigEditDialog(Shell parentShell, FolderConfiguration config) {
58         super(parentShell, 1, false);
59         mConfig.set(config);
60     }
61 
setDeviceName(String name)62     public void setDeviceName(String name) {
63         mDeviceName = name;
64     }
65 
getDeviceName()66     public String getDeviceName() {
67         return mDeviceName;
68     }
69 
setXDpi(float xdpi)70     public void setXDpi(float xdpi) {
71         mXDpi = xdpi;
72     }
73 
getXDpi()74     public float getXDpi() {
75         return mXDpi;
76     }
77 
setYDpi(float ydpi)78     public void setYDpi(float ydpi) {
79         mYDpi = ydpi;
80     }
81 
getYDpi()82     public float getYDpi() {
83         return mYDpi;
84     }
85 
setConfigName(String name)86     public void setConfigName(String name) {
87         mConfigName = name;
88     }
89 
getConfigName()90     public String getConfigName() {
91         return mConfigName;
92     }
93 
setConfig(FolderConfiguration config)94     public void setConfig(FolderConfiguration config) {
95         mConfig.set(config);
96     }
97 
getConfig(FolderConfiguration config)98     public void getConfig(FolderConfiguration config) {
99         config.set(mConfig);
100     }
101 
102     @Override
createDialogContent(Composite parent)103     public void createDialogContent(Composite parent) {
104         mError = IconFactory.getInstance().getIcon("error"); //$NON-NLS-1$
105 
106         Group deviceGroup = new Group(parent, SWT.NONE);
107         deviceGroup.setText("Device");
108         deviceGroup.setLayoutData(new GridData(GridData.FILL_BOTH));
109         deviceGroup.setLayout(new GridLayout(2, false));
110 
111         Label l = new Label(deviceGroup, SWT.None);
112         l.setText("Name");
113 
114         final Text deviceNameText = new Text(deviceGroup, SWT.BORDER);
115         deviceNameText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
116         if (mDeviceName != null) {
117             deviceNameText.setText(mDeviceName);
118         }
119         deviceNameText.addModifyListener(new ModifyListener() {
120             public void modifyText(ModifyEvent e) {
121                 mDeviceName = deviceNameText.getText().trim();
122                 validateOk();
123             }
124         });
125 
126 
127         VerifyListener floatVerifier = new VerifyListener() {
128             public void verifyText(VerifyEvent event) {
129                 // combine the current content and the new text
130                 String text = ((Text)event.widget).getText();
131                 text = text.substring(0, event.start) + event.text + text.substring(event.end);
132 
133                 // now make sure it's a match for the regex
134                 event.doit = FLOAT_PATTERN.matcher(text).matches();
135             }
136         };
137 
138         l = new Label(deviceGroup, SWT.None);
139         l.setText("x dpi");
140 
141         final Text deviceXDpiText = new Text(deviceGroup, SWT.BORDER);
142         deviceXDpiText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
143         if (Float.isNaN(mXDpi) == false) {
144             deviceXDpiText.setText(String.format("%.1f", mXDpi)); //$NON-NLS-1$
145         }
146         deviceXDpiText.addVerifyListener(floatVerifier);
147         deviceXDpiText.addModifyListener(new ModifyListener() {
148             public void modifyText(ModifyEvent e) {
149                 String value = deviceXDpiText.getText();
150                 if (value.length() == 0) {
151                     mXDpi = Float.NaN;
152                 } else {
153                     mXDpi = Float.parseFloat(value);
154                 }
155             }
156         });
157 
158         l = new Label(deviceGroup, SWT.None);
159         l.setText("y dpi");
160 
161         final Text deviceYDpiText = new Text(deviceGroup, SWT.BORDER);
162         deviceYDpiText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
163         if (Float.isNaN(mYDpi) == false) {
164             deviceYDpiText.setText(String.format("%.1f", mYDpi)); //$NON-NLS-1$
165         }
166         deviceYDpiText.addVerifyListener(floatVerifier);
167         deviceYDpiText.addModifyListener(new ModifyListener() {
168             public void modifyText(ModifyEvent e) {
169                 String value = deviceYDpiText.getText();
170                 if (value.length() == 0) {
171                     mYDpi = Float.NaN;
172                 } else {
173                     mYDpi = Float.parseFloat(value);
174                 }
175             }
176         });
177 
178         Group configGroup = new Group(parent, SWT.NONE);
179         configGroup.setText("Configuration");
180         configGroup.setLayoutData(new GridData(GridData.FILL_BOTH));
181         configGroup.setLayout(new GridLayout(2, false));
182 
183         l = new Label(configGroup, SWT.None);
184         l.setText("Name");
185 
186         final Text configNameText = new Text(configGroup, SWT.BORDER);
187         configNameText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
188         if (mConfigName != null) {
189             configNameText.setText(mConfigName);
190         }
191         configNameText.addModifyListener(new ModifyListener() {
192             public void modifyText(ModifyEvent e) {
193                 mConfigName = configNameText.getText().trim();
194                 validateOk();
195             }
196         });
197 
198         mConfigSelector = new ConfigurationSelector(configGroup, true /*deviceMode*/);
199         // configure the selector to be in "device mode" and not accept language/region/version
200         // since those are selected from a different combo
201         // FIXME: add version combo.
202         mConfigSelector.setQualifierFilter(new IQualifierFilter() {
203             public boolean accept(ResourceQualifier qualifier) {
204                 if (qualifier instanceof LanguageQualifier ||
205                         qualifier instanceof RegionQualifier ||
206                         qualifier instanceof VersionQualifier) {
207                     return false;
208                 }
209 
210                 return true;
211             }
212         });
213         mConfigSelector.setConfiguration(mConfig);
214         GridData gd;
215         mConfigSelector.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
216         gd.horizontalSpan = 2;
217         gd.widthHint = ConfigurationSelector.WIDTH_HINT;
218         gd.heightHint = ConfigurationSelector.HEIGHT_HINT;
219 
220         // add a listener to check on the validity of the FolderConfiguration as
221         // they are built.
222         mConfigSelector.setOnChangeListener(new Runnable() {
223             public void run() {
224                 if (mConfigSelector.getState() == ConfigurationState.OK) {
225                     mConfigSelector.getConfiguration(mConfig);
226                 }
227 
228                 validateOk();
229             }
230         });
231 
232         mStatusComposite = new Composite(parent, SWT.NONE);
233         mStatusComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
234         GridLayout gl = new GridLayout(2, false);
235         mStatusComposite.setLayout(gl);
236         gl.marginHeight = gl.marginWidth = 0;
237 
238         mStatusImage = new Label(mStatusComposite, SWT.NONE);
239         mStatusLabel = new Label(mStatusComposite, SWT.NONE);
240         mStatusLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
241         resetStatus();
242     }
243 
244     @Override
createContents(Composite parent)245     protected Control createContents(Composite parent) {
246         Control c = super.createContents(parent);
247         validateOk();
248         return c;
249     }
250 
251     /**
252      * resets the status label to show the file that will be created.
253      */
resetStatus()254     private void resetStatus() {
255         String displayString = Dialog.shortenText(
256                 String.format("Config: %1$s", mConfig.toString()),
257                 mStatusLabel);
258         mStatusLabel.setText(displayString);
259     }
260 
setError(String text)261     private void setError(String text) {
262         String displayString = Dialog.shortenText(text, mStatusLabel);
263         mStatusLabel.setText(displayString);
264         mStatusImage.setImage(mError);
265         getButton(IDialogConstants.OK_ID).setEnabled(false);
266     }
267 
validateOk()268     private void validateOk() {
269         // check the device name
270         if (mDeviceName == null || mDeviceName.length() == 0) {
271             setError("Device name must not be empty");
272             return;
273         }
274 
275         // check the config name
276         if (mConfigName == null || mConfigName.length() == 0) {
277             setError("Configuration name must not be empty");
278             return;
279         }
280 
281         // and check the config itself
282         ConfigurationState state = mConfigSelector.getState();
283 
284         switch (state) {
285             case INVALID_CONFIG:
286                 ResourceQualifier invalidQualifier = mConfigSelector.getInvalidQualifier();
287                 setError(String.format(
288                         "Invalid Configuration: %1$s has no filter set.",
289                         invalidQualifier.getName()));
290                 return;
291             case REGION_WITHOUT_LANGUAGE:
292                 setError("The Region qualifier requires the Language qualifier.");
293                 return;
294         }
295 
296         // no error
297         mStatusImage.setImage(null);
298         resetStatus();
299         getButton(IDialogConstants.OK_ID).setEnabled(true);
300 
301         // need to relayout, because of the change in size in mErrorImage.
302         mStatusComposite.layout();
303     }
304 }
305