All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.czyzby.autumn.mvc.component.preferences.dto.ReflectionPreference Maven / Gradle / Ivy

Go to download

MVC framework based on LibGDX using Autumn for components management and LML as view templates.

There is a newer version: 1.9.1.9.6
Show newest version
package com.github.czyzby.autumn.mvc.component.preferences.dto;

import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.ui.Button;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.List;
import com.badlogic.gdx.scenes.scene2d.ui.SelectBox;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.TextField;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.badlogic.gdx.utils.reflect.Field;
import com.badlogic.gdx.utils.reflect.ReflectionException;
import com.github.czyzby.kiwi.util.common.Strings;
import com.github.czyzby.kiwi.util.gdx.reflection.Reflection;

/** Reflected field wrapper. Treats a field as a preference.
 *
 * @author MJ */
public class ReflectionPreference implements Preference {
    private final Object owner;
    private final Field field;
    private final Type type;

    public ReflectionPreference(final Object owner, final Field field) throws GdxRuntimeException {
        this.owner = owner;
        this.field = field;
        type = Type.getType(field);
        if (type == null) {
            throw new GdxRuntimeException("Invalid field annotated with @Property: unable to handle: " + field.getType()
                    + " in field: " + field + " of component: " + owner);
        }
    }

    @Override
    public void read(final String name, final Preferences preferences) throws Exception {
        Reflection.setFieldValue(field, owner, type.convert(preferences.getString(name)));
    }

    @Override
    public Object getDefault() {
        return type.getDefault();
    }

    @Override
    public Object extractFromActor(final Actor actor) {
        return type.extractFromActor(actor);
    }

    @Override
    public Object get() {
        try {
            return Reflection.getFieldValue(field, owner);
        } catch (final ReflectionException exception) {
            throw new GdxRuntimeException("Unable to extract field value from component: " + owner, exception);
        }
    }

    @Override
    public void set(final Object preference) {
        try {
            Reflection.setFieldValue(field, owner, preference);
        } catch (final ReflectionException exception) {
            throw new GdxRuntimeException("Unable to set field value in component: " + owner, exception);
        }
    }

    @Override
    public void save(final String name, final Preferences preferences) {
        preferences.putString(name, String.valueOf(get()));
    }

    /** Contains all supported types.
     *
     * @author MJ */
    private static enum Type {
        BOOLEAN(boolean.class, Boolean.class) {
            @Override
            public Object convert(final String raw) {
                return Boolean.valueOf(raw);
            }

            @Override
            public Object getDefault() {
                return Boolean.TRUE;
            }

            @Override
            public Object extractFromActor(final Actor actor) {
                if (actor instanceof Button) {
                    return ((Button) actor).isChecked();
                }
                throw new GdxRuntimeException("Cannot use default setter of boolean preference with actor: " + actor);
            }
        },
        INT(int.class, Integer.class) {
            @Override
            public Object convert(final String raw) {
                return Integer.valueOf(raw);
            }

            @Override
            public Object getDefault() {
                return Integer.valueOf(0);
            }

            @Override
            public Object extractFromActor(final Actor actor) {
                if (actor instanceof TextField) {
                    return Integer.valueOf(((TextField) actor).getText());
                } else if (actor instanceof List) {
                    return ((List) actor).getSelectedIndex();
                } else if (actor instanceof SelectBox) {
                    return ((SelectBox) actor).getSelectedIndex();
                }
                throw new GdxRuntimeException("Cannot use default setter of int preference with actor: " + actor);
            }
        },
        FLOAT(float.class, Float.class) {
            @Override
            public Object convert(final String raw) {
                return Float.valueOf(raw);
            }

            @Override
            public Object getDefault() {
                return Float.valueOf(0f);
            }

            @Override
            public Object extractFromActor(final Actor actor) {
                if (actor instanceof TextField) {
                    return Float.valueOf(((TextField) actor).getText());
                }
                throw new GdxRuntimeException("Cannot use default setter of float preference with actor: " + actor);
            }
        },
        LONG(long.class, Long.class) {
            @Override
            public Object convert(final String raw) {
                return Long.valueOf(raw);
            }

            @Override
            public Object getDefault() {
                return Long.valueOf(0L);
            }

            @Override
            public Object extractFromActor(final Actor actor) {
                if (actor instanceof TextField) {
                    return Long.valueOf(((TextField) actor).getText());
                }
                throw new GdxRuntimeException("Cannot use default setter of long preference with actor: " + actor);
            }
        },
        STRING(String.class, Object.class) {
            @Override
            public Object convert(final String raw) {
                return raw;
            }

            @Override
            public Object getDefault() {
                return Strings.EMPTY_STRING;
            }

            @Override
            public Object extractFromActor(final Actor actor) {
                if (actor instanceof Label) {
                    return ((Label) actor).getText().toString();
                } else if (actor instanceof TextButton) {
                    return ((TextButton) actor).getText();
                } else if (actor instanceof TextField) {
                    return ((TextField) actor).getText();
                } else if (actor instanceof List) {
                    return Strings.toString(((List) actor).getSelected(), Strings.EMPTY_STRING);
                } else if (actor instanceof SelectBox) {
                    return Strings.toString(((SelectBox) actor).getSelected(), Strings.EMPTY_STRING);
                }
                return Strings.toString(actor);
            }
        };

        private final Class[] supportedClasses;

        private Type(final Class... supportedClasses) {
            this.supportedClasses = supportedClasses;
        }

        /** @return default field value for the selected field type. */
        public abstract Object getDefault();

        /** @param field contains a preference.
         * @return type ready to handle field's value or null. */
        public static Type getType(final Field field) {
            for (final Type type : values()) {
                if (type.matches(field)) {
                    return type;
                }
            }
            return null;
        }

        /** @param field contains the preference.
         * @return true if this type can handle the field. */
        public boolean matches(final Field field) {
            for (final Class supportedClass : supportedClasses) {
                if (supportedClass.equals(field.getType())) {
                    return true;
                }
            }
            return false;
        }

        /** @param raw preference value in the map.
         * @return converted preference value, ready to be stored in the field. */
        public abstract Object convert(String raw);

        /** @param actor used to set up the preference.
         * @return value extracted from the actor. */
        public abstract Object extractFromActor(final Actor actor);
    }
}