Best Android App InstaSquare Lite for full-size publication of photos in Instagram, Facebook, Twitter. Run the android application on PC. You can through the android emulator Droid4X.

root/trunk/rapidandroid/org.rapidandroid/src/org/rapidandroid/activity/FormCreator.java @ 134

Revision 134, 19.2 KB (checked in by dmyung, 10 months ago)

added some secret sections for FormReview? for debug data injection

but for real stuff, added a settings file that's generated on startup for the first time, and is persisted in the settings directory to set a preference for ACK replies for parse and no parse events.

Line 
1/*
2 *    rapidandroid - SMS gateway for the android platform
3 *    Copyright (C) 2009 Dimagi Inc., UNICEF
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/**
20 *
21 */
22package org.rapidandroid.activity;
23
24import java.io.File;
25import java.io.FileInputStream;
26import java.io.FileNotFoundException;
27import java.io.FileOutputStream;
28import java.io.IOException;
29import java.io.InputStreamReader;
30import java.util.Vector;
31
32import org.json.JSONException;
33import org.json.JSONObject;
34import org.rapidandroid.R;
35import org.rapidandroid.activity.AddField.ResultConstants;
36import org.rapidandroid.content.translation.ModelTranslator;
37import org.rapidandroid.view.adapter.FieldViewAdapter;
38import org.rapidsms.java.core.model.Field;
39import org.rapidsms.java.core.model.Form;
40import org.rapidsms.java.core.model.SimpleFieldType;
41import org.rapidsms.java.core.parser.service.ParsingService.ParserType;
42import org.rapidsms.java.core.parser.token.ITokenParser;
43
44import android.app.Activity;
45import android.app.AlertDialog;
46import android.app.Dialog;
47import android.content.Context;
48import android.content.DialogInterface;
49import android.content.Intent;
50
51import android.os.Bundle;
52import android.util.Log;
53import android.view.ContextMenu;
54import android.view.Menu;
55import android.view.MenuItem;
56import android.view.View;
57import android.view.Window;
58import android.view.ContextMenu.ContextMenuInfo;
59import android.widget.AdapterView;
60import android.widget.EditText;
61import android.widget.ListView;
62import android.widget.TextView;
63import android.widget.AdapterView.OnItemClickListener;
64
65/**
66 * Activity window for creating a new form.
67 *
68 * Goal is to create all this form in memory for the user to interact with.
69 *
70 * Creation of org.rapidsms.core.model.Form object for insertion into database
71 * is the goal.
72 *
73 * @author Daniel Myung [email protected]
74 * @created Jan 12, 2009
75 *
76 */
77
78public class FormCreator extends Activity {
79        private static final int MENU_SAVE = Menu.FIRST;
80        private static final int MENU_ADD_FIELD = Menu.FIRST + 1;
81        private static final int MENU_CANCEL = Menu.FIRST + 2;
82
83        public static final int ACTIVITY_ADDFIELD_CANCEL = 0;
84        public static final int ACTIVITY_ADDFIELD_ADDED = 1;
85
86        private static final int CONTEXT_MOVE_UP = Menu.FIRST;
87        private static final int CONTEXT_MOVE_DOWN = Menu.FIRST + 1;
88        private static final int CONTEXT_REMOVE = Menu.FIRST + 2;
89        // private static final int CONTEXT_EDIT = ContextMenu.FIRST + 3;
90
91        private static final int DIALOG_FORM_SAVEABLE = -1;
92        private static final int DIALOG_FORM_INVALID_NOFORMNAME = 0;
93        private static final int DIALOG_FORM_INVALID_NOPREFIX = 1;
94        private static final int DIALOG_FORM_INVALID_NOTUNIQUE = 2;
95        private static final int DIALOG_FORM_INVALID_NOFIELDS = 3;
96        private static final int DIALOG_CONFIRM_CLOSURE = 4;
97        private static final int DIALOG_FORM_CREATE_FAIL = 5;
98
99        private static final int DIALOGRESULT_CLOSE_INFORMATIONAL = 0;
100        private static final int DIALOGRESULT_OK_DONT_SAVE = 1;
101        private static final int DIALOGRESULT_CANCEL_KEEP_WORKING = 2;
102
103        private static final String STATE_FORMNAME = "formname";
104        private static final String STATE_PREFIX = "prefix";
105        private static final String STATE_DESC = "desc";
106
107        private Vector<Field> mCurrentFields;
108        private String[] fieldStrings;
109
110        private boolean mClosing = false;
111
112        private int selectedFieldPosition = -1;
113
114        /*
115         * (non-Javadoc)
116         *
117         * @see android.app.Activity#onCreate(android.os.Bundle)
118         */
119        @Override
120        protected void onCreate(Bundle savedInstanceState) {
121                super.onCreate(savedInstanceState);
122                requestWindowFeature(Window.FEATURE_NO_TITLE);
123                setContentView(R.layout.form_create);
124
125                // Required onCreate setup
126                // add some events to the listview
127                ListView lsv = (ListView) findViewById(R.id.lsv_createfields);
128                lsv.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() {
129                        public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
130                                menu.setHeaderTitle("Current Field");
131                                menu.add(0, CONTEXT_MOVE_UP, 0, "Move Up");
132                                menu.add(0, CONTEXT_MOVE_DOWN, 0, "Move Down");
133                                // menu.add(0, CONTEXT_EDIT, 0, "Edit");
134                                menu.add(0, CONTEXT_REMOVE, 0, "Remove").setIcon(android.R.drawable.ic_menu_delete);
135
136                        }
137                });
138
139                lsv.setOnItemClickListener(new OnItemClickListener() {
140
141                        public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
142                                // TODO Auto-generated method stub
143                                selectedFieldPosition = arg2;
144                        }
145
146                });
147                TextView noFields = new TextView(this);
148                noFields.setText("No fields");
149                lsv.setEmptyView(noFields);
150                updateFieldList();
151        }
152
153        @Override
154        protected synchronized void onPause() {
155                // TODO Auto-generated method stub
156                super.onPause();
157                if (!mClosing) {
158                        saveState();
159                } else {
160                        File f = this.getFileStreamPath("FormCreatorSavedState");
161                        if (f.exists()) {
162                                f.delete();
163                        }
164                }
165        }
166
167        // dmyung - since the savestate and onresume rely upon the database, and we
168        // are only doing the formcreate in memory, we will not implement these.
169        private void saveState() {
170                // TODO Auto-generated method stub
171                // this.d
172                JSONObject savedstate = new JSONObject();
173                EditText etxFormName = (EditText) findViewById(R.id.etx_formname);
174                EditText etxFormPrefix = (EditText) findViewById(R.id.etx_formprefix);
175                EditText etxDescription = (EditText) findViewById(R.id.etx_description);
176
177                ListView lsv = (ListView) findViewById(R.id.lsv_createfields);
178
179                try {
180                        savedstate.put(STATE_FORMNAME, etxFormName.getText().toString());
181                        savedstate.put(STATE_PREFIX, etxFormPrefix.getText().toString());
182                        savedstate.put(STATE_DESC, etxDescription.getText().toString());
183
184                        if (mCurrentFields != null) {
185                                int numFields = this.mCurrentFields.size();
186                                for (int i = 0; i < numFields; i++) {
187                                        Field f = mCurrentFields.get(i);
188
189                                        JSONObject fieldobj = new JSONObject();
190
191                                        fieldobj.put(AddField.ResultConstants.RESULT_KEY_FIELDNAME, f.getName());
192                                        fieldobj.put(AddField.ResultConstants.RESULT_KEY_DESCRIPTION, f.getDescription());
193                                        fieldobj.put(AddField.ResultConstants.RESULT_KEY_FIELDTYPE_ID,
194                                                                        ((SimpleFieldType) f.getFieldType()).getId());
195
196                                        savedstate.put("Field" + i, fieldobj);
197                                }
198                        }
199                } catch (JSONException e1) {
200                        // TODO Auto-generated catch block
201                        e1.printStackTrace();
202                        Log.d("FormCreator", e1.getMessage());
203                }
204
205                try {
206                        FileOutputStream fos = this.openFileOutput("FormCreatorSavedState", Context.MODE_PRIVATE);
207                        fos.write(savedstate.toString().getBytes());
208                } catch (FileNotFoundException e) {
209                        // TODO Auto-generated catch block
210                        e.printStackTrace();
211                        Log.d("FormCreator", e.getMessage());
212                } catch (IOException e) {
213                        // TODO Auto-generated catch block
214                        e.printStackTrace();
215                        Log.d("FormCreator", e.getMessage());
216                }
217        }
218
219        @Override
220        protected synchronized void onResume() {
221                super.onResume();
222                try {
223                        File f = this.getFileStreamPath("FormCreatorSavedState");
224                        if (f.exists()) {
225                                // mCurrentFields = new Vector<Field>();
226                                FileInputStream fin = this.openFileInput("FormCreatorSavedState");
227                                InputStreamReader irdr = new InputStreamReader(fin); // promote
228
229                                int size = (int) fin.getChannel().size();
230                                char[] data = new char[size]; // allocate char array of right
231                                // size
232                                irdr.read(data, 0, size); // read into char array
233                                irdr.close();
234
235                                String contents = new String(data);
236                                JSONObject readobject = new JSONObject(contents);
237
238                                EditText etxFormName = (EditText) findViewById(R.id.etx_formname);
239                                EditText etxFormPrefix = (EditText) findViewById(R.id.etx_formprefix);
240                                EditText etxDescription = (EditText) findViewById(R.id.etx_description);
241
242                                etxFormName.setText(readobject.getString(STATE_FORMNAME));
243                                etxFormPrefix.setText(readobject.getString(STATE_PREFIX));
244                                etxDescription.setText(readobject.getString(STATE_DESC));
245                                boolean checkForFields = true;
246                                int i = 0;
247                                do {
248                                        checkForFields = readobject.has("Field" + i);
249                                        if (checkForFields) {
250                                                JSONObject fieldBundle = (JSONObject) readobject.get("Field" + i);
251                                                restoreFieldFromState(fieldBundle);
252                                                i++;
253                                        }
254                                } while (checkForFields);
255                                fin.close();                           
256                                f.delete();
257                        }
258                } catch (Exception ex) {
259                        Log.d("FormCreator", ex.getMessage());
260                }
261        }
262
263        /*
264         * (non-Javadoc)
265         *
266         * @see android.app.Activity#onActivityResult(int, int,
267         * android.content.Intent)
268         */
269        @Override
270        protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
271                // TODO Auto-generated method stub
272                super.onActivityResult(requestCode, resultCode, intent);
273                Bundle extras = null;
274                if (intent != null) {
275                        extras = intent.getExtras();
276                }
277
278                switch (requestCode) {
279                        case ACTIVITY_ADDFIELD_ADDED:
280                                if (extras != null) {
281                                        addNewFieldFromActivity(extras);
282                                }
283                                break;
284                        case ACTIVITY_ADDFIELD_CANCEL:
285                                // do nothing
286                                break;
287                }
288        }
289
290        private void addNewFieldFromActivity(Bundle extras) {
291                if (mCurrentFields == null) {
292                        mCurrentFields = new Vector<Field>();
293                }
294
295                Field newField = new Field();
296                newField.setFieldId(-1);
297                newField.setName(extras.getString(ResultConstants.RESULT_KEY_FIELDNAME));
298                newField.setDescription(extras.getString(ResultConstants.RESULT_KEY_DESCRIPTION));
299                int fieldTypeID = extras.getInt(ResultConstants.RESULT_KEY_FIELDTYPE_ID);
300                ITokenParser fieldtype = ModelTranslator.getFieldType(fieldTypeID);
301                newField.setFieldType(fieldtype);
302
303                int seqId = mCurrentFields.size();
304                if (seqId > 0) {
305                        seqId = seqId - 1;
306                }
307                newField.setSequenceId(seqId);
308                mCurrentFields.add(newField);
309
310                updateFieldList();
311        }
312
313        private void restoreFieldFromState(JSONObject fieldjson) {
314                if (mCurrentFields == null) {
315                        mCurrentFields = new Vector<Field>();
316                }
317                try {
318                        Field newField = new Field();
319                        newField.setFieldId(-1);
320                        newField.setName(fieldjson.getString(ResultConstants.RESULT_KEY_FIELDNAME));
321                        newField.setDescription(fieldjson.getString(ResultConstants.RESULT_KEY_DESCRIPTION));
322                        int fieldTypeID = fieldjson.getInt(ResultConstants.RESULT_KEY_FIELDTYPE_ID);
323                        ITokenParser fieldtype = ModelTranslator.getFieldType(fieldTypeID);
324                        newField.setFieldType(fieldtype);
325
326                        int listSize = mCurrentFields.size();
327
328                        for (int i = 0; i < listSize; i++) {
329                                Field existingField = mCurrentFields.get(i);
330                                if (existingField.getName().equals(newField.getName())) {
331                                        return;
332                                }
333                        }
334                        if (listSize > 0) {
335                                listSize = listSize - 1;
336                        }
337                        newField.setSequenceId(listSize);
338
339                        mCurrentFields.add(newField);
340
341                        updateFieldList();
342                } catch (Exception ex) {
343                        Log.d("FormCreator", ex.getMessage());
344                }
345        }
346
347        /**
348         *
349         */
350        private void updateFieldList() {
351                ListView lsv = (ListView) findViewById(R.id.lsv_createfields);
352                if (mCurrentFields == null) {
353                        mCurrentFields = new Vector<Field>();
354                }
355
356                Field[] fieldArray = this.mCurrentFields.toArray(new Field[mCurrentFields.size()]);
357                lsv.setAdapter(new FieldViewAdapter(this, fieldArray));
358        }
359
360        /*
361         * (non-Javadoc)
362         *
363         * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
364         */
365        @Override
366        public boolean onCreateOptionsMenu(Menu menu) {
367                super.onCreateOptionsMenu(menu);
368                menu.add(0, MENU_SAVE, 0, R.string.formeditor_menu_save).setIcon(android.R.drawable.ic_menu_save);
369                menu.add(0, MENU_ADD_FIELD, 0, R.string.formeditor_menu_add_field).setIcon(android.R.drawable.ic_menu_add);
370                menu.add(0, MENU_CANCEL, 0, R.string.formeditor_menu_cancel)
371                        .setIcon(android.R.drawable.ic_menu_close_clear_cancel);
372                return true;
373        }
374
375        /*
376         * (non-Javadoc)
377         *
378         * @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
379         */
380        @Override
381        public boolean onOptionsItemSelected(MenuItem item) {
382                super.onOptionsItemSelected(item);
383                switch (item.getItemId()) {
384                        case MENU_SAVE:
385                                int formStatus = checkFormIsSaveable();
386                                if (formStatus == FormCreator.DIALOG_FORM_SAVEABLE) {
387                                        doSave();
388                                        setResult(0);
389                                        File f = this.getFileStreamPath("FormCreatorSavedState");
390                                        if (f.exists()) {
391                                                f.delete();
392                                        }
393                                        mClosing = true;
394                                        finish();
395                                } else {
396                                        this.showDialog(formStatus);
397                                }
398                                return true;
399                        case MENU_ADD_FIELD:
400                                Intent intent = new Intent(this, AddField.class);
401                                // mUpdatedFromActivity = true;
402                                if (mCurrentFields != null) {
403                                        int len = this.mCurrentFields.size();
404                                        for (int i = 0; i < len; i++) {
405                                                intent.putExtra(mCurrentFields.get(i).getName(), 0);
406                                        }
407                                }
408                                startActivityForResult(intent, ACTIVITY_ADDFIELD_ADDED);
409                                return true;
410                        case MENU_CANCEL:
411                                mClosing = true;
412                                finish();
413                                return true;
414                }
415
416                return true;
417        }
418
419        private int checkFormIsSaveable() {
420                EditText etxFormName = (EditText) findViewById(R.id.etx_formname);
421                EditText etxFormPrefix = (EditText) findViewById(R.id.etx_formprefix);
422                // EditText etxDescription =
423                // (EditText)findViewById(R.id.etx_description);
424                ListView lsvFields = (ListView) findViewById(R.id.lsv_createfields);
425
426                if (etxFormName.getText().length() == 0) {
427                        return FormCreator.DIALOG_FORM_INVALID_NOFORMNAME;
428                }
429                if (etxFormPrefix.getText().length() == 0) {
430                        return FormCreator.DIALOG_FORM_INVALID_NOPREFIX;
431                }
432
433                if (this.mCurrentFields.size() == 0) {
434                        return FormCreator.DIALOG_FORM_INVALID_NOFIELDS;
435                }
436                String prefixCandidate = etxFormPrefix.getText().toString();
437                String nameCandidate = etxFormName.getText().toString();
438
439                if (ModelTranslator.doesFormExist(this, prefixCandidate, nameCandidate)) {
440                        return FormCreator.DIALOG_FORM_INVALID_NOTUNIQUE;
441                } else {
442                        return FormCreator.DIALOG_FORM_SAVEABLE;
443                }
444        }
445
446        /**
447         * @param prefixCandidate
448         * @param nameCandidate
449         * @return
450         */
451
452        private void doSave() {
453                EditText etxFormName = (EditText) findViewById(R.id.etx_formname);
454                EditText etxFormPrefix = (EditText) findViewById(R.id.etx_formprefix);
455                EditText etxDescription = (EditText) findViewById(R.id.etx_description);
456
457                Form formToSave = new Form();
458                formToSave.setFormName(etxFormName.getText().toString());
459                formToSave.setPrefix(etxFormPrefix.getText().toString());
460                formToSave.setDescription(etxDescription.getText().toString());
461
462                // (Message[])parsedMessages.keySet().toArray(new
463                // Message[parsedMessages.keySet().size()]);
464                Field[] fieldArray = this.mCurrentFields.toArray(new Field[mCurrentFields.size()]);
465                formToSave.setFields(fieldArray);
466
467                formToSave.setParserType(ParserType.SIMPLEREGEX);
468                try {
469                        ModelTranslator.addFormToDatabase(formToSave);
470                } catch (Exception ex) {
471                        showDialog(DIALOG_FORM_CREATE_FAIL);
472                }
473        }
474
475        @Override
476        // http://www.anddev.org/tinytutcontextmenu_for_listview-t4019.html
477        // UGH, things changed from .9 to 1.0
478        public boolean onContextItemSelected(MenuItem item) {
479                // some sanity checks:
480                ListView lsvFields = (ListView) findViewById(R.id.lsv_createfields);
481                if (lsvFields.getCount() == 0 || this.mCurrentFields == null || this.mCurrentFields.size() == 0) {
482                        return true;
483                }
484
485                if (selectedFieldPosition == -1) {
486                        return true;
487                }
488
489                AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
490                switch (item.getItemId()) {
491                        // TODO: IMPLEMENT CONTEXT MENU
492                        case CONTEXT_MOVE_UP:
493
494                                moveFieldUp(selectedFieldPosition);
495
496                                break;
497                        case CONTEXT_MOVE_DOWN:
498
499                                moveFieldDown(selectedFieldPosition);
500
501                                break;
502                        case CONTEXT_REMOVE:
503                                removeField(selectedFieldPosition);
504                                break;
505                        default:
506                                return super.onContextItemSelected(item);
507                }
508                return true;
509        }
510
511        /**
512         * @param position
513         */
514        private void removeField(int position) {
515                mCurrentFields.remove(position);
516                resetFieldSequences();
517        }
518
519        /**
520         *
521         */
522        private void moveFieldDown(int position) {
523                if (position < mCurrentFields.size() - 1) {
524                        Field fieldToMove = mCurrentFields.get(position);
525                        mCurrentFields.remove(position);
526                        int newposition = position + 1;
527                        if (newposition >= mCurrentFields.size()) {
528                                mCurrentFields.add(fieldToMove);
529                        } else {
530                                mCurrentFields.add(newposition, fieldToMove);
531                        }
532                        resetFieldSequences();
533                }
534        }
535
536        /**
537         * @param position
538         */
539        private void moveFieldUp(int position) {
540                // TODO Auto-generated method stub
541                if (position > 0) {
542                        Field fieldToMove = mCurrentFields.get(position);
543                        mCurrentFields.remove(position);
544                        int newposition = position - 1;
545                        if (newposition <= 0) {
546                                mCurrentFields.add(0, fieldToMove);
547                        } else {
548                                mCurrentFields.add(newposition, fieldToMove);
549                        }
550                        resetFieldSequences();
551                }
552        }
553
554        private void resetFieldSequences() {
555                int len = mCurrentFields.size();
556                for (int i = 0; i < len; i++) {
557                        Field f = mCurrentFields.get(i);
558                        f.setSequenceId(i);
559                }
560                updateFieldList();
561        }
562
563        @Override
564        protected Dialog onCreateDialog(int id) {
565                super.onCreateDialog(id);
566                String title = "";
567                String message = "";
568
569                switch (id) {
570                        case DIALOG_FORM_INVALID_NOFIELDS:
571                                title = "Invalid form";
572                                message = "You must have at least one field for this form to save";
573                                break;
574                        case DIALOG_FORM_INVALID_NOFORMNAME:
575                                title = "Invalid form";
576                                message = "You must enter a formname";
577                                break;
578                        case DIALOG_FORM_INVALID_NOPREFIX:
579                                title = "Invalid form";
580                                message = "You must enter a prefix";
581                                break;
582                        case DIALOG_FORM_INVALID_NOTUNIQUE:
583                                title = "Invalid form";
584                                message = "The form of this name and prefix already exists";
585                                break;
586                        case DIALOG_FORM_CREATE_FAIL:
587                                title = "Form creation failed";
588                                message = "Unable to create the form and its support tables.  Check the logs.";
589                                return new AlertDialog.Builder(FormCreator.this).setTitle(title).setMessage(message)
590                                                                                                                                .setPositiveButton("Ok", null).create();
591                        case DIALOG_CONFIRM_CLOSURE:
592                                // for confirm closure, we actually just return the dialog as we
593                                // want it here.
594                                title = "Confirm Closure";
595                                message = "Are you sure you want to close without saving changes?";
596                                return new AlertDialog.Builder(FormCreator.this)
597                                                                                                                                .setTitle(title)
598                                                                                                                                .setMessage(message)
599                                                                                                                                .setPositiveButton(
600                                                                                                                                                                        "Yes",
601                                                                                                                                                                        new DialogInterface.OnClickListener() {
602                                                                                                                                                                                public void onClick(
603                                                                                                                                                                                                DialogInterface dialog,
604                                                                                                                                                                                                int whichButton) {
605                                                                                                                                                                                        finish();
606                                                                                                                                                                                }
607                                                                                                                                                                        })
608                                                                                                                                .setNegativeButton("No, keep working", null).create();
609                        default:
610                                return null;
611
612                }
613                return new AlertDialog.Builder(FormCreator.this).setTitle(title).setMessage(message).setPositiveButton("OK",
614                                                                                                                                                                                                                                null)
615                                                                                                                .create();
616
617        }
618
619}
Note: See TracBrowser for help on using the browser.