/*
* $Id$
* This file is a part of the Arakhne Foundation Classes, http://www.arakhne.org/afc
*
* Copyright (c) 2000-2012 Stephane GALLAND.
* Copyright (c) 2005-10, Multiagent Team, Laboratoire Systemes et Transports,
* Universite de Technologie de Belfort-Montbeliard.
* Copyright (c) 2013-2016 The original authors, and other authors.
*
* 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 org.arakhne.afc.ui.android.property;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.arakhne.afc.references.SoftValueHashMap;
import org.arakhne.afc.ui.undo.AbstractUndoable;
import org.arakhne.afc.ui.undo.UndoManager;
import org.arakhne.afc.util.PropertyOwner;
import org.arakhne.afc.vmutil.ReflectionUtil;
import android.R;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.DialogInterface.OnClickListener;
import android.util.Pair;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.ScrollView;
/** Editors of properties.
*
* @author $Author: sgalland$
* @version $Name$ $Revision$ $Date$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
* @deprecated see JavaFX API
*/
@Deprecated
public class PropertyEditors {
/** Stored the mapping between type of object and type of property editor.
*/
private static final Map<Class<? extends PropertyOwner>,Class<? extends PropertyEditorView>> mapping = new HashMap<>();
/** Use to accelerate the queries.
*/
private static final Map<Class<? extends PropertyOwner>,Class<? extends PropertyEditorView>> buffer = new SoftValueHashMap<>();
/** Display the dialog that permits to edit the properties.
*
* @param context
* @param isEditable indicates if the dialog box allows editions.
* @param undoManager is the undo manager to use.
* @param editedObjects are the edited objects.
*/
@SuppressWarnings("unchecked")
public static void showDialog(final Context context, final boolean isEditable, final UndoManager undoManager, final Collection<? extends PropertyOwner> editedObjects) {
//Detect the common type of the given objects
Class<? extends PropertyOwner> type = null;
if (!editedObjects.isEmpty()) {
for(PropertyOwner obj : editedObjects) {
if (type==null) {
type = obj.getClass();
}
else {
type = (Class<? extends PropertyOwner>)ReflectionUtil.getCommonType(type, obj.getClass());
}
}
}
// Create the views
ScrollView scrollView = new ScrollView(context);
LayoutParams layoutParams = new LinearLayout.LayoutParams(
android.view.ViewGroup.LayoutParams.MATCH_PARENT,
android.view.ViewGroup.LayoutParams.MATCH_PARENT);
scrollView.setLayoutParams(layoutParams);
LinearLayout linearLayout = new LinearLayout(context);
linearLayout.setVerticalScrollBarEnabled(true);
linearLayout.setHorizontalScrollBarEnabled(false);
linearLayout.setScrollbarFadingEnabled(true);
layoutParams = new LinearLayout.LayoutParams(
android.view.ViewGroup.LayoutParams.MATCH_PARENT,
android.view.ViewGroup.LayoutParams.MATCH_PARENT);
linearLayout.setLayoutParams(layoutParams);
scrollView.addView(linearLayout);
final PropertyEditorView fragment = PropertyEditors.createFragmentFor(context, type);
fragment.setId(123456);
fragment.setEditable(isEditable);
fragment.setEditedObjects(editedObjects);
linearLayout.addView(fragment);
// Initialize the alert dialog builder
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.dialog_alert_title);
builder.setPositiveButton(
android.R.string.ok,
new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (isEditable) {
Undo undo = new Undo(context.getString(R.string.cancel), editedObjects, fragment);
undo.doEdit();
if (undoManager!=null) {
undoManager.add(undo);
}
}
}
});
builder.setNegativeButton(android.R.string.cancel, new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builder.setOnCancelListener(new OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
dialog.dismiss();
}
});
builder.setView(scrollView);
// Create and show the dialog
AlertDialog alert = builder.create();
alert.show();
}
/** Register a property editor fragment.
*
* @param fragmentType is the type of the fragment to create for editing the properties of an object of the given type.
* @param objectType is the type of the object to edit.
*/
public static void registerEditorFragment(Class<? extends PropertyEditorView> fragmentType, Class<? extends PropertyOwner> objectType) {
mapping.put(objectType, fragmentType);
}
/** Create a fragment that permits to edit the properties for
* the given object.
*
* @param context
* @param editedObjectType
* @return a fragment or <code>null</code> if there is no known fragment.
*/
static PropertyEditorView createFragmentFor(Context context, Class<? extends PropertyOwner> editedObjectType) {
assert(editedObjectType!=null);
Class<?> objectType = editedObjectType;
Class<? extends PropertyEditorView> fragmentType = buffer.get(objectType);
while (fragmentType==null && objectType!=null) {
fragmentType = mapping.get(objectType);
if (fragmentType==null) {
Class<?>[] interfaces = objectType.getInterfaces();
int i=0;
while (fragmentType==null && i<interfaces.length) {
fragmentType = mapping.get(interfaces[i]);
++i;
}
}
objectType = objectType.getSuperclass();
}
if (fragmentType!=null) {
try {
Constructor<? extends PropertyEditorView> cons = fragmentType.getConstructor(Context.class);
PropertyEditorView fragment = cons.newInstance(context);
buffer.put(editedObjectType,fragmentType);
return fragment;
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
return null;
}
/**
* @author $Author: sgalland$
* @version $Name$ $Revision$ $Date$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
*/
private static class Undo extends AbstractUndoable {
private static final long serialVersionUID = -7759672095147438168L;
private final String label;
private final Collection<Pair<PropertyOwner,Map<String,Object>>> originalProperties = new ArrayList<>();
private final PropertyEditorView fragment;
private final Map<String,Object> newProperties;
/**
* @param label
* @param editedObjects
* @param fragment
*/
public Undo(String label, Collection<? extends PropertyOwner> editedObjects, PropertyEditorView fragment) {
this.label = label;
this.fragment = fragment;
this.newProperties = this.fragment.getEditedProperties();
for(PropertyOwner owner : editedObjects) {
this.originalProperties.add(new Pair<>(
owner,
owner.getProperties()));
}
}
@Override
public String getPresentationName() {
return this.label;
}
@Override
protected void doEdit() {
for(Pair<PropertyOwner,Map<String,Object>> object : this.originalProperties) {
this.fragment.setPropertiesOf(object.first, this.newProperties);
}
}
@Override
protected void undoEdit() {
for(Pair<PropertyOwner,Map<String,Object>> object : this.originalProperties) {
this.fragment.setPropertiesOf(object.first, object.second);
}
}
}
}