~ubuntu-branches/ubuntu/vivid/drmips/vivid-backports

« back to all changes in this revision

Viewing changes to src/android/DrMIPS/src/org/feup/brunonova/drmips/gui/DrMIPS.java

  • Committer: Package Import Robot
  • Author(s): Bruno Nova
  • Date: 2014-09-27 12:24:17 UTC
  • Revision ID: package-import@ubuntu.com-20140927122417-2gadkwt9k0u7j4zu
Tags: upstream-1.2.3
Import upstream version 1.2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    DrMIPS - Educational MIPS simulator
 
3
    Copyright (C) 2013-2014 Bruno Nova <ei08109@fe.up.pt>
 
4
 
 
5
    This program is free software: you can redistribute it and/or modify
 
6
    it under the terms of the GNU General Public License as published by
 
7
    the Free Software Foundation, either version 3 of the License, or
 
8
    (at your option) any later version.
 
9
 
 
10
    This program is distributed in the hope that it will be useful,
 
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
    GNU General Public License for more details.
 
14
 
 
15
    You should have received a copy of the GNU General Public License
 
16
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
17
*/
 
18
 
 
19
package org.feup.brunonova.drmips.gui;
 
20
 
 
21
import java.io.BufferedReader;
 
22
import java.io.BufferedWriter;
 
23
import java.io.File;
 
24
import java.io.FileWriter;
 
25
import java.io.InputStreamReader;
 
26
 
 
27
import org.feup.brunonova.drmips.R;
 
28
import org.feup.brunonova.drmips.simulator.mips.CPU;
 
29
 
 
30
import android.app.Application;
 
31
import android.content.Context;
 
32
import android.content.SharedPreferences;
 
33
import android.content.pm.PackageInfo;
 
34
import android.content.pm.PackageManager.NameNotFoundException;
 
35
import android.os.Build;
 
36
import android.os.Environment;
 
37
import android.util.Log;
 
38
import android.util.TypedValue;
 
39
import android.widget.Toast;
 
40
 
 
41
/**
 
42
 * Global object that represents the application.
 
43
 * <p>It also contains some global constants and parameters.</p>
 
44
 * 
 
45
 * @author Bruno Nova
 
46
 */
 
47
public class DrMIPS extends Application {
 
48
        /** The key of the preference with the version of the last app launch. */
 
49
        public static final String LAST_VERSION_PREF = "last_version";
 
50
        /** The key of the preference with the name of the last code file opened. */
 
51
        public static final String LAST_FILE_PREF = "last_file";
 
52
        /** The key of the preference with the name of the last CPU opened. */
 
53
        public static final String LAST_CPU_PREF = "last_cpu";
 
54
        /** The name of the default CPU to load at startup. */
 
55
        public static final String DEFAULT_CPU = "unicycle.cpu";
 
56
        /** The key of the registers display format preference. */
 
57
        public static final String REGISTER_FORMAT_PREF = "reg_format";
 
58
        /** The key of the datapath display data format preference. */
 
59
        public static final String DATAPATH_DATA_FORMAT_PREF = "datapath_format";
 
60
        /** The key of the assembled code display data format preference. */
 
61
        public static final String ASSEMBLED_CODE_FORMAT_PREF = "assembled_code_format";
 
62
        /** The key of the data memory display data format preference. */
 
63
        public static final String DATA_MEMORY_FORMAT_PREF = "data_memory_format";
 
64
        /** The default performance mode type. */
 
65
        public static final int DEFAULT_PERFORMANCE_TYPE = Util.CPU_PERFORMANCE_TYPE_INDEX;
 
66
        /** The key of the show control path preference. */
 
67
        public static final String THEME_PREF = "theme";
 
68
        /** The key of the show arrows preference. */
 
69
        public static final String SHOW_CONTROL_PATH_PREF = "show_control_path";
 
70
        /** The key of the theme preference. */
 
71
        public static final String SHOW_ARROWS_PREF = "show_arrows";
 
72
        /** The key of the performance mode preference. */
 
73
        public static final String PERFORMANCE_MODE_PREF = "performance_mode";
 
74
        /** The key of the performance mode type preference. */
 
75
        public static final String PERFORMANCE_TYPE_PREF = "performance_type";
 
76
        /** The key of the overlayed data preference. */
 
77
        public static final String OVERLAYED_DATA_PREF = "overlayed_data";
 
78
        /** The default format with which the registers are displayed. */
 
79
        public static final int DEFAULT_REGISTER_FORMAT = Util.DECIMAL_FORMAT_INDEX;
 
80
        /** The default format with which the datapath data is displayed. */
 
81
        public static final int DEFAULT_DATAPATH_DATA_FORMAT = Util.DECIMAL_FORMAT_INDEX;
 
82
        /** The default format with which the assembled code data is displayed. */
 
83
        public static final int DEFAULT_ASSEMBLED_CODE_FORMAT = Util.DECIMAL_FORMAT_INDEX;
 
84
        /** The default format with which the data memory values are displayed. */
 
85
        public static final int DEFAULT_DATA_MEMORY_FORMAT = Util.DECIMAL_FORMAT_INDEX;
 
86
        /** Whether the control path is shown by default. */
 
87
        public static final boolean DEFAULT_SHOW_CONTROL_PATH = true;
 
88
        /** Whether arrows are shown on the wires by default. */
 
89
        public static final boolean DEFAULT_SHOW_ARROWS = true;
 
90
        /** Whether the performance mode is enabled by default. */
 
91
        public static final boolean DEFAULT_PERFORMANCE_MODE = false;
 
92
        /** Whether the in/out tips are shown by default. */
 
93
        public static final boolean DEFAULT_OVERLAYED_DATA = true;
 
94
        
 
95
        /** The current application. */
 
96
        private static DrMIPS app = null;
 
97
        /** The context of the application. */
 
98
        private Context context = null;
 
99
        /** File representation that points to the app's files directory (preferably on the external memory). */
 
100
        private File filesDir = null;
 
101
        /** File representation that points to the CPU directory. */
 
102
        private File cpuDir = null;
 
103
        /** File representation that points to the user created assembly code files directory. */
 
104
        private File codeDir = null;
 
105
        /** The application's version code. */
 
106
        private int versionCode = 0;
 
107
        /** The application's version name. */
 
108
        private String versionName = "";
 
109
        /** The currently loaded CPU. */
 
110
        private CPU cpu = null;
 
111
        
 
112
        @Override
 
113
        public void onCreate() {
 
114
                super.onCreate();
 
115
                app = this;
 
116
                context = getApplicationContext();
 
117
                
 
118
                try { // Find application's version
 
119
                        PackageInfo info = getPackageManager().getPackageInfo(getPackageName(), 0);
 
120
                        versionCode = info.versionCode;
 
121
                        versionName = info.versionName;
 
122
                } catch (NameNotFoundException e) {
 
123
                        Log.e(getClass().getName(), "Failed to get app version!", e);
 
124
                }
 
125
                
 
126
                createDefaultFiles();
 
127
        }
 
128
        
 
129
        /**
 
130
         * Returns a reference to the application.
 
131
         * @return The application.
 
132
         */
 
133
        public static DrMIPS getApplication() {
 
134
                return app;
 
135
        }
 
136
        
 
137
        /**
 
138
         * Returns the default theme of the application
 
139
         * <p>For Android 3.0 and higher the default theme is LightTheme.<br />
 
140
         * For versions below 3.0 the default theme is DarkTheme.</p>
 
141
         * @return Application's default theme.
 
142
         */
 
143
        public static int getDefaultTheme() {
 
144
                return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) ? R.style.LightTheme : R.style.DarkTheme;
 
145
        }
 
146
        
 
147
        /**
 
148
         * Returns the currently loaded CPU.
 
149
         * @return The currently loaded CPU.
 
150
         */
 
151
        public CPU getCPU() {
 
152
                return cpu;
 
153
        }
 
154
        
 
155
        /**
 
156
         * Updates the currently loaded CPU.
 
157
         * @param cpu New CPU.
 
158
         */
 
159
        public void setCPU(CPU cpu) {
 
160
                this.cpu = cpu;
 
161
        }
 
162
        
 
163
        /**
 
164
         * Returns whether there is a CPU loaded.
 
165
         * @return <tt>True</tt> if the is a CPU loaded.
 
166
         */
 
167
        public boolean hasCPU() {
 
168
                return cpu != null;
 
169
        }
 
170
        
 
171
        /**
 
172
         * Returns the context of the application.
 
173
         * @return Context of the application.
 
174
         */
 
175
        public Context getContext() {
 
176
                return context;
 
177
        }
 
178
        
 
179
        /**
 
180
         * Returns the ID of the current theme (from the preferences).
 
181
         * @return ID of the current theme.
 
182
         */
 
183
        public int getCurrentTheme() {
 
184
                return DrMIPS.getApplication().getPreferences().getInt(DrMIPS.THEME_PREF, getDefaultTheme());
 
185
        }
 
186
        
 
187
        /**
 
188
         * Converts the given size in dips to pixels.
 
189
         * @param dip Size in dips.
 
190
         * @return Size in pixels
 
191
         */
 
192
        public int dipToPx(float dip) {
 
193
                // getResources().getDisplayMetrics().density
 
194
                return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, getResources().getDisplayMetrics());
 
195
        }
 
196
        
 
197
        /**
 
198
         * Returns the file representation that points to the app's files directory (preferably on the external memory).
 
199
         * @return File representation that points to the app's files directory (preferably on the external memory).
 
200
         */
 
201
        public File getFilesDir() {
 
202
                return filesDir;
 
203
        }
 
204
        
 
205
        /**
 
206
         * Returns the file representation that points to the CPU directory.
 
207
         * @return File representation that points to the CPU directory.
 
208
         */
 
209
        public File getCPUDir() {
 
210
                return cpuDir;
 
211
        }
 
212
        
 
213
        /**
 
214
         * Returns the file representation that points to the user created assembly code files directory.
 
215
         * @return File representation that points to the user created assembly code files directory.
 
216
         */
 
217
        public File getCodeDir() {
 
218
                return codeDir;
 
219
        }
 
220
        
 
221
        /**
 
222
         * Returns the application's version code.
 
223
         * @return The application's version code.
 
224
         */
 
225
        public int getVersionCode() {
 
226
                return versionCode;
 
227
        }
 
228
        
 
229
        /**
 
230
         * Returns the application's preferences.
 
231
         * @return App's preferences.
 
232
         */
 
233
        public SharedPreferences getPreferences() {
 
234
                return getSharedPreferences("prefs", MODE_PRIVATE);
 
235
        }
 
236
        
 
237
        /**
 
238
         * Creates the default .cpu and .set files on the sdcard if they don't exist yet.
 
239
         * <p>Also sets the path to the application files directory.</p>
 
240
         */
 
241
        private void createDefaultFiles() { 
 
242
                // Find if the (preferred) external memory is available
 
243
                if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) // external memory available?
 
244
                        filesDir = getExternalFilesDir(null);
 
245
                else { // external memory not available! (use internal memory)
 
246
                        filesDir = context.getFilesDir(); // Apparently can return null, at least in the emulator
 
247
                        Toast.makeText(getContext(), R.string.sdcard_not_available, Toast.LENGTH_SHORT).show();
 
248
                }
 
249
                
 
250
                // Create internal directories
 
251
                cpuDir = new File(filesDir.getAbsoluteFile() + File.separator + "cpu");
 
252
                codeDir = new File(filesDir.getAbsolutePath()+ File.separator + "code");
 
253
                if(!cpuDir.exists() && !cpuDir.mkdir()) Log.e(getClass().getName(), "Failed to create CPUs directory!");
 
254
                if(!codeDir.exists() && !codeDir.mkdir()) Log.e(getClass().getName(), "Failed to create code directory!");
 
255
                
 
256
                // Find if the app was upgraded (because the default files could have been upgraded too)
 
257
                boolean upgraded = versionCode > getPreferences().getInt(LAST_VERSION_PREF, -1);
 
258
                SharedPreferences.Editor editor = getPreferences().edit();
 
259
                editor.putInt(LAST_VERSION_PREF, versionCode); // save new "last version"
 
260
                editor.commit();
 
261
                
 
262
                // Copy default CPU files to the memory
 
263
                File unicycleCPU = new File(cpuDir.getAbsoluteFile() + File.separator + "unicycle.cpu");
 
264
                File unicycleNoJumpCPU = new File(cpuDir.getAbsoluteFile() + File.separator + "unicycle-no-jump.cpu");
 
265
                File unicycleNoJumpBranchCPU = new File(cpuDir.getAbsoluteFile() + File.separator + "unicycle-no-jump-branch.cpu");
 
266
                File unicycleExtendedCPU = new File(cpuDir.getAbsoluteFile() + File.separator + "unicycle-extended.cpu");
 
267
                File pipelineCPU = new File(cpuDir.getAbsoluteFile() + File.separator + "pipeline.cpu");
 
268
                File pipelineNoHazardDetectionCPU = new File(cpuDir.getAbsoluteFile() + File.separator + "pipeline-no-hazard-detection.cpu");
 
269
                File pipelineOnlyForwardingCPU = new File(cpuDir.getAbsoluteFile() + File.separator + "pipeline-only-forwarding.cpu");
 
270
                File pipelineExtendedCPU = new File(cpuDir.getAbsoluteFile() + File.separator + "pipeline-extended.cpu");
 
271
                File defaultSet = new File(cpuDir.getAbsoluteFile() + File.separator + "default.set");
 
272
                File defaultNoJumpSet = new File(cpuDir.getAbsoluteFile() + File.separator + "default-no-jump.set");
 
273
                File defaultNoJumpBranchSet = new File(cpuDir.getAbsoluteFile() + File.separator + "default-no-jump-branch.set");
 
274
                File defaultExtendedSet = new File(cpuDir.getAbsoluteFile() + File.separator + "default-extended.set");
 
275
                File defaultExtendedNoJumpSet = new File(cpuDir.getAbsoluteFile() + File.separator + "default-extended-no-jump.set");
 
276
                if(upgraded || !unicycleCPU.exists()) copyResourceFile(R.raw.unicycle_cpu, unicycleCPU);
 
277
                if(upgraded || !unicycleNoJumpCPU.exists()) copyResourceFile(R.raw.unicycle_no_jump_cpu, unicycleNoJumpCPU);
 
278
                if(upgraded || !unicycleNoJumpBranchCPU.exists()) copyResourceFile(R.raw.unicycle_no_jump_branch_cpu, unicycleNoJumpBranchCPU);
 
279
                if(upgraded || !unicycleExtendedCPU.exists()) copyResourceFile(R.raw.unicycle_extended_cpu, unicycleExtendedCPU);
 
280
                if(upgraded || !pipelineCPU.exists()) copyResourceFile(R.raw.pipeline_cpu, pipelineCPU);
 
281
                if(upgraded || !pipelineOnlyForwardingCPU.exists()) copyResourceFile(R.raw.pipeline_only_forwarding_cpu, pipelineOnlyForwardingCPU);
 
282
                if(upgraded || !pipelineNoHazardDetectionCPU.exists()) copyResourceFile(R.raw.pipeline_no_hazard_detection_cpu, pipelineNoHazardDetectionCPU);
 
283
                if(upgraded || !pipelineExtendedCPU.exists()) copyResourceFile(R.raw.pipeline_extended_cpu, pipelineExtendedCPU);
 
284
                if(upgraded || !defaultSet.exists()) copyResourceFile(R.raw.default_set, defaultSet);
 
285
                if(upgraded || !defaultNoJumpSet.exists()) copyResourceFile(R.raw.default_no_jump_set, defaultNoJumpSet);
 
286
                if(upgraded || !defaultNoJumpBranchSet.exists()) copyResourceFile(R.raw.default_no_jump_branch_set, defaultNoJumpBranchSet);
 
287
                if(upgraded || !defaultExtendedSet.exists()) copyResourceFile(R.raw.default_extended_set, defaultExtendedSet);
 
288
                if(upgraded || !defaultExtendedNoJumpSet.exists()) copyResourceFile(R.raw.default_extended_no_jump_set, defaultExtendedNoJumpSet);
 
289
        }
 
290
        
 
291
        /**
 
292
         * Copies the raw file with the given id to the specified path.
 
293
         * @param resource The resource identifier of the file to copy.
 
294
         * @param dest The File representation with the full path to the destination (including the file name).
 
295
         */
 
296
        private void copyResourceFile(int resource, File dest) {
 
297
                BufferedReader in = null;
 
298
                BufferedWriter out = null;
 
299
                String line;
 
300
                
 
301
                try {
 
302
                        in = new BufferedReader(new InputStreamReader(getContext().getResources().openRawResource(resource)));
 
303
                        out = new BufferedWriter(new FileWriter(dest));
 
304
                        while((line = in.readLine()) != null)
 
305
                                out.write(line + "\n");
 
306
                }
 
307
                catch(Exception e) {
 
308
                        Log.e(getClass().getName(), "Failed to copy default file to " + dest.getAbsolutePath() + "!", e);
 
309
                }
 
310
                finally {
 
311
                        try {
 
312
                                if(in != null) in.close();
 
313
                                if(out != null) out.close();
 
314
                        } catch(Exception ex) { }
 
315
                }
 
316
        }
 
317
}