/* * Copyright (C) 2011 Virginia Tech Department of Computer Science * * 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 sofia.data; import sofia.app.Screen; import sofia.data.internal.Inspector; import sofia.data.internal.InspectorScreenProxy; import sofia.internal.ReflectiveListWrapper; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.LinearLayout; import android.widget.LinearLayout.LayoutParams; import android.widget.ListView; import android.widget.SimpleAdapter; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; public class InspectorScreen extends Screen { private InspectorScreenProxy proxy; public void initialize(Object object) { if (object instanceof List) { proxy = new ListInspector(); } else if (object.getClass().isArray()) { //proxy = new ListInspector(); } else if (object instanceof Map) { proxy = new MapInspector(); } else { proxy = new ObjectInspector(); } proxy.initialize(object); } private class ObjectInspector implements InspectorScreenProxy { private Object object; private List<PropertyEditor> properties; private List<View> itemViews; private ListView listView; private PropertyListAdapter adapter; public void initialize(Object object) { this.object = object; Inspector inspector = new Inspector(object.getClass()); properties = inspector.getProperties(); getWindow().setSoftInputMode( WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); setContentView(createForm()); } public void resume() { adapter.notifyDataSetChanged(); } public void store() { // TODO only if not canceled for (PropertyEditor editor : properties) { editor.giveValueToObject(object); } } private ViewGroup createForm() { itemViews = new ArrayList<View>(); // TODO need a button bar for Done/Cancel controls listView = new ListView(InspectorScreen.this); adapter = new PropertyListAdapter(); listView.setAdapter(adapter); for (PropertyEditor editor : properties) { View label = editor.createLabel(InspectorScreen.this); View editorView = editor.createEditor(InspectorScreen.this); editor.takeValueFromObject(object); if (label == null) { itemViews.add(editorView); } else { LinearLayout layout = new LinearLayout(InspectorScreen.this); layout.setOrientation(LinearLayout.VERTICAL); layout.addView(label); layout.addView(editorView); itemViews.add(layout); } } return listView; } private class PropertyListAdapter extends BaseAdapter { public int getCount() { return properties.size(); } public Object getItem(int index) { return properties.get(index); } public long getItemId(int paramInt) { return 0; } public View getView(int index, View convertView, ViewGroup parent) { return itemViews.get(index); } } } private class ListInspector implements InspectorScreenProxy { private List<?> list; private ReflectiveListWrapper wrappedList; private SimpleAdapter adapter; private Object pendingNewItem; private Button newButton; private Button deleteButton; private ListView listView; public void initialize(Object object) { this.list = (List<?>) object; this.wrappedList = new ReflectiveListWrapper(list); setContentView(createForm()); } public void resume() { if (pendingNewItem != null) { } adapter.notifyDataSetChanged(); } public void store() { } private ViewGroup createForm() { // TODO do we want a button bar here to add items? Figure out the // best UI for this newButton = new Button(InspectorScreen.this); newButton.setText("New..."); newButton.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { newClicked(); } }); deleteButton = new Button(InspectorScreen.this); deleteButton.setText("Delete"); deleteButton.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { deleteClicked(); } }); LinearLayout buttonBar = createButtonBar(newButton, deleteButton); buttonBar.setId(1001); listView = new ListView(InspectorScreen.this); listView.setId(1000); listView.setOnItemClickListener( new OnItemClickListener() { public void onItemClick(AdapterView<?> adapterView, View itemView, int index, long id) { presentScreen(InspectorScreen.class, list.get(index)); } }); adapter = new SimpleAdapter(InspectorScreen.this, wrappedList, android.R.layout.simple_list_item_1, new String[] { "toString" }, new int[] { android.R.id.text1 }); listView.setAdapter(adapter); return createDualLayout(listView, buttonBar); } private void newClicked() { } private void deleteClicked() { adapter = new SimpleAdapter(InspectorScreen.this, wrappedList, android.R.layout.simple_list_item_checked, new String[] { "toString" }, new int[] { android.R.id.text1 }); listView.setAdapter(adapter); } } private class MapInspector implements InspectorScreenProxy { private Map<?, ?> map; private List<Map.Entry<?, ?>> sortedEntries; private ReflectiveListWrapper wrappedEntries; private SimpleAdapter adapter; public void initialize(Object object) { this.map = (Map<?, ?>) object; sortedEntries = new ArrayList<Map.Entry<?, ?>>(map.entrySet()); Collections.sort(sortedEntries, new Comparator<Map.Entry<?, ?>>() { @SuppressWarnings("unchecked") public int compare(Map.Entry<?, ?> a, Map.Entry<?, ?> b) { if (a.getKey() instanceof Comparable) { return ((Comparable<Object>) a.getKey()).compareTo( b.getKey()); } else { return a.getKey().toString().compareTo( b.getKey().toString()); } } }); this.wrappedEntries = new ReflectiveListWrapper(sortedEntries); setContentView(createForm()); } public void resume() { adapter.notifyDataSetChanged(); } public void store() { } private ViewGroup createForm() { // TODO do we want a button bar here to add items? Figure out the // best UI for this ListView listView = new ListView(InspectorScreen.this); adapter = new SimpleAdapter(InspectorScreen.this, wrappedEntries, android.R.layout.simple_list_item_2, new String[] { "key.toString", "value.toString" }, new int[] { android.R.id.text1, android.R.id.text2 }); listView.setAdapter(adapter); listView.setOnItemClickListener( new OnItemClickListener() { public void onItemClick(AdapterView<?> adapterView, View itemView, int index, long id) { presentScreen(InspectorScreen.class, sortedEntries.get(index).getValue()); } }); return listView; } } private LinearLayout.LayoutParams layoutParams(int h, int v) { return new LinearLayout.LayoutParams(h, v); } @Override protected void onPause() { proxy.store(); super.onPause(); } @Override protected void onResume() { proxy.resume(); super.onResume(); } private LinearLayout createDualLayout(View mainView, View buttonBar) { LinearLayout layout = new LinearLayout(this); layout.setOrientation(LinearLayout.VERTICAL); LinearLayout.LayoutParams mainLp = new LinearLayout.LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, 1.0f); layout.addView(mainView, mainLp); LinearLayout.LayoutParams barLp = new LinearLayout.LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); layout.addView(buttonBar, barLp); return layout; } private LinearLayout createButtonBar(Button... buttons) { LinearLayout bar = new LinearLayout(this); for (Button button : buttons) { LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, 1.0f); bar.addView(button, lp); } return bar; } }