@Getter
@EqualsAndHashCode
@RequiredArgsConstructor(suppressConstructorProperties = true)
public class Category implements Comparable<Category> {
    private final String name;

    public static Category all(Context context) {
        return new Category(context.getString(R.string.category_all));
    }

    @Override
    public int compareTo(Category that) {
        return this.name.compareTo(that.name);
    }
} public class AddCategoryDrawerItem extends DrawerItem {
    private final BaseActivity activity;

    protected DefaultPrefs defaultPrefs;

    public AddCategoryDrawerItem(BaseActivity activity) {
        super(DrawerItemType.SETTING);
        this.activity = activity;
        defaultPrefs = Esperandro.getPreferences(DefaultPrefs.class, activity);
    }

    @Override
    public View getView(Context context, ViewGroup root) {
        LayoutInflater inflater = LayoutInflater.from(context);
        return inflater.inflate(R.layout.drawer_item_addcategory, root, false);
    }

    @Override
    public void onClick(Context context) {
        AddCategoryDialog addCategoryDialog = new AddCategoryDialog();
        addCategoryDialog.show(activity.getSupportFragmentManager(), null);
    }

    @SuppressLint("ValidFragment")
    public static class AddCategoryDialog extends DialogFragment {

        @NonNull
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            final DefaultPrefs defaultPrefs = Esperandro.getPreferences(DefaultPrefs.class, getActivity());
            AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
            builder.setNegativeButton(android.R.string.cancel, null);
            builder.setCancelable(false);
            builder.setTitle(R.string.title_addCategory);
            View dialogView = View.inflate(getActivity(), R.layout.dialog_addcategory, null);
            final EditText category = ButterKnife.findById(dialogView,
                    R.id.editText_category);
            builder.setView(dialogView);
            builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    String categoryText = category.getText().toString();
                    if (!Strings.isNullOrEmpty(categoryText)) {
                        List<Category> categories = defaultPrefs.categories();
                        categories.add(new Category(categoryText));
                        defaultPrefs.categories(categories);
                        App.get().getBus().post(new ReloadDrawerEvent());
                    }
                }
            });

            return builder.create();
        }
    }
} public class AllCategoryDrawerItem extends CategoryDrawerItem {
    public AllCategoryDrawerItem(Context context) {
        super(Category.all(context));
        this.firstLetter = "A";
    }

    @Override
    public View getView(Context context, ViewGroup root) {
        View view = super.getView(context, root);
        deleteCategory.setVisibility(View.GONE);
        return view;
    }

    @Subscribe
    @Override
    public void activeCategoryChanged(CategoryChangeEvent event) {
        super.activeCategoryChanged(event);
    }
} public class CategoryDrawerItem extends DrawerItem {

    protected final Category category;
    protected String firstLetter;

    protected Bus bus;
    protected DefaultPrefs defaultPrefs;

    protected View rootView;
    @BindView(R.id.textView_categoryLetter)
    protected TextView categoryLetter;
    @BindView(R.id.textView_settingsItem)
    protected TextView headerText;
    @BindView(R.id.imageView_deleteCategory)
    protected ImageView deleteCategory;

    protected boolean active = false;

    public CategoryDrawerItem(Category category) {
        super(DrawerItemType.CATEGORY);
        this.category = category;
        this.firstLetter = Strings.isNullOrEmpty(category.getName()) ? "" : category.getName().substring(0, 1);
        bus = App.get().getBus();
        bus.register(this);
        defaultPrefs = Esperandro.getPreferences(DefaultPrefs.class, App.get());
    }

    @Override
    protected void finalize() throws Throwable {
        bus.unregister(this);
        super.finalize();
    }

    @Override
    public View getView(Context context, ViewGroup root) {
        LayoutInflater inflater = LayoutInflater.from(context);
        rootView = inflater.inflate(R.layout.drawer_item_category, root, false);
        updateActiveState();
        ButterKnife.bind(this, rootView);
        deleteCategory.setVisibility(defaultPrefs.lockCategories() ? View.GONE : View.VISIBLE);
        headerText.setText(category.getName());
        categoryLetter.setText(firstLetter);
        return rootView;
    }

    private void updateActiveState() {
        if (rootView != null) {
            if (active) {
                rootView.setBackgroundResource(R.color.drawer_item_active);
            } else {
                rootView.setBackgroundResource(R.color.drawer_background);
            }
        }
    }

    @Override
    public void onClick(Context context) {
        bus.post(new CategoryChangeEvent(category));
    }

    @Subscribe
    public void activeCategoryChanged(CategoryChangeEvent event) {
        active = category.equals(event.getCategory());
        updateActiveState();
    }

    @OnClick(R.id.imageView_deleteCategory)
    public void onDeleteCategory() {
        List<Category> categories = defaultPrefs.categories();
        categories.remove(category);
        defaultPrefs.categories(categories);
        if (active) {
            bus.post(new CategoryChangeEvent(Category.all(App.get())));
        }
        bus.post(new ReloadDrawerEvent());

    }
} @RequiredArgsConstructor(suppressConstructorProperties = true)
public abstract class DrawerItem {

    @Getter
    private final DrawerItemType type;

    public abstract View getView(Context context, ViewGroup root);

    public abstract void onClick(Context context);

} public class DrawerItemAdapter extends ArrayAdapter<DrawerItem> {
    public DrawerItemAdapter(Context context, List<DrawerItem> objects) {
        super(context, 0, objects);
    }

    @Override
    public int getViewTypeCount() {
        return DrawerItemType.values().length;
    }

    @Override
    public int getItemViewType(int position) {
        return getItem(position).getType().ordinal();
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        DrawerItem item = getItem(position);

        return item.getView(getContext(), parent);
    }
} @RequiredArgsConstructor(suppressConstructorProperties = true)
public class ExportDrawerItem extends SettingsDrawerItem {
    private final BaseActivity activity;
    private final DrawerLayout drawerLayout;

    @Override
    public int getImageRes() {
        return R.drawable.ic_drawer_export;
    }

    @Override
    public int getHeaderRes() {
        return R.string.caption_export;
    }

    @Override
    public void onClick(Context context) {
        if (drawerLayout != null) {
            drawerLayout.closeDrawers();
        }
        FileFormatDialog dialog = new FileFormatDialog();
        dialog.show(activity.getSupportFragmentManager(), null);
    }

    @SuppressLint("ValidFragment")
    public static class FileFormatDialog extends DialogFragment {
        @NonNull
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
            View dialogView = View.inflate(getActivity(), R.layout.dialog_fileformat, null);
            final RadioButton jsonRadio = ButterKnife.findById(dialogView, R.id.radioButton_json);
            final RadioButton mpsitesRadio = ButterKnife
                    .findById(dialogView, R.id.radioButton_mpsites);
            jsonRadio.setChecked(true);
            builder.setView(dialogView);
            builder.setTitle(R.string.title_exportFormat);
            builder.setNegativeButton(android.R.string.cancel, null);
            int okButtonTextResource = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
                    ? android.R.string.ok
                    : R.string.caption_selectFolder;
            builder.setPositiveButton(okButtonTextResource, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    Exporter exporter = new Exporter();
                    ExportType exportType = ExportType.JSON;
                    if (mpsitesRadio.isChecked()) {
                        exportType = ExportType.MPSITES;
                    }
                    exporter.startExportIntent(getActivity(), exportType);
                    dismiss();
                }
            });

            return builder.create();
        }
    }
} @RequiredArgsConstructor(suppressConstructorProperties = true)
public class ImportDrawerItem extends SettingsDrawerItem {
    public static final int REQUEST_CODE_IMPORT = 1234;

    private final BaseActivity activity;
    private final DrawerLayout drawerLayout;

    @Override
    public int getImageRes() {
        return R.drawable.ic_drawer_import;
    }

    @Override
    public int getHeaderRes() {
        return R.string.caption_import;
    }

    @Override
    public void onClick(Context context) {
        if (drawerLayout != null) {
            drawerLayout.closeDrawers();
        }

        ImportTypeDialog dialog = new ImportTypeDialog();
        dialog.show(activity.getSupportFragmentManager(), null);
    }

    @SuppressLint("ValidFragment")
    public static class ImportTypeDialog extends DialogFragment {
        @NonNull
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
            View dialogView = View.inflate(getActivity(), R.layout.dialog_importtype, null);
            final RadioButton appendRadio = ButterKnife
                    .findById(dialogView, R.id.radioButton_append);
            final RadioButton overrideRadio = ButterKnife
                    .findById(dialogView, R.id.radioButton_override);
            final RadioButton mergeRadio = ButterKnife
                    .findById(dialogView, R.id.radioButton_merge);
            mergeRadio.setChecked(true);
            builder.setView(dialogView);
            builder.setTitle(R.string.title_importType);
            builder.setNegativeButton(android.R.string.cancel, null);
            builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    Importer importer = new Importer();
                    ImportType importType = ImportType.APPEND;
                    if (overrideRadio.isChecked()) {
                        importType = ImportType.OVERRIDE;
                    } else if  (mergeRadio.isChecked()) {
                        importType = ImportType.MERGE;
                    } else if (appendRadio.isChecked()) {
                        importType = ImportType.APPEND;
                    }
                    importer.startImportIntent((AppCompatActivity) getActivity(), importType);
                    dismiss();
                }
            });

            return builder.create();
        }
    }
} @RequiredArgsConstructor(suppressConstructorProperties = true)
public class LogoutDrawerItem extends SettingsDrawerItem {

    public final Activity activity;

    @Override
    public int getImageRes() {
        return R.drawable.ic_drawer_logout;
    }

    @Override
    public int getHeaderRes() {
        return R.string.caption_logout;
    }

    @Override
    public void onClick(Context context) {
        activity.finish();
        MasterPasswordHolder.INSTANCE.clear();
        Intent intent = new Intent(context, LoginActivity.class);
        context.startActivity(intent);
    }
} @RequiredArgsConstructor(suppressConstructorProperties = true)
public class PreferencesDrawerItem extends SettingsDrawerItem {

    private final DrawerLayout drawerLayout;

    @Override
    public int getImageRes() {
        return R.drawable.ic_action_settings;
    }

    @Override
    public int getHeaderRes() {
        return R.string.title_activity_settings;
    }

    @Override
    public void onClick(Context context) {
        if (drawerLayout != null) {
            drawerLayout.closeDrawers();
        }
        Intent intent = new Intent(context, SettingsActivity.class);
        context.startActivity(intent);
    }
} @Getter
@RequiredArgsConstructor(suppressConstructorProperties = true)
public class CategoryChangeEvent {
    private final Category category;
} public class ReloadDrawerEvent {
}
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import com.squareup.otto.Subscribe;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import de.devland.masterpassword.R;
import de.devland.masterpassword.model.Category;
import de.devland.masterpassword.ui.drawer.AddCategoryDrawerItem;
import de.devland.masterpassword.ui.drawer.AllCategoryDrawerItem;
import de.devland.masterpassword.ui.drawer.CategoryDrawerItem;
import de.devland.masterpassword.ui.drawer.DrawerItem;
import de.devland.masterpassword.ui.drawer.DrawerItemAdapter;
import de.devland.masterpassword.ui.drawer.ExportDrawerItem;
import de.devland.masterpassword.ui.drawer.ImportDrawerItem;
import de.devland.masterpassword.ui.drawer.LogoutDrawerItem;
import de.devland.masterpassword.ui.drawer.PreferencesDrawerItem;
import de.devland.masterpassword.util.event.CategoryChangeEvent;
import de.devland.masterpassword.util.event.ReloadDrawerEvent;
package de.devland.masterpassword.ui;






public class PasswordViewActivity extends LoginRequiringActivity implements
        AdapterView.OnItemClickListener {

    private DrawerLayout drawerLayout;
    private ActionBarDrawerToggle drawerToggle;
    private DrawerItemAdapter drawerItemAdapter;

    private ListView drawerList;
    private Fragment fragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_password_view);
        if (savedInstanceState == null) {
            fragment = new PasswordViewFragment();
            getSupportFragmentManager().beginTransaction()
                                       .add(R.id.container, fragment)
                                       .commit();
        } else {
            fragment = getSupportFragmentManager().getFragment(
                    savedInstanceState, "fragment");
        }
        drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawerList = (ListView) findViewById(R.id.left_drawer);
        if (drawerLayout != null) {
            drawerToggle = new ActionBarDrawerToggle(
                    this,                  /* host Activity */
                    drawerLayout,         /* DrawerLayout object */
                    R.string.drawer_open,  /* "open drawer" description */
                    R.string.drawer_close  /* "close drawer" description */
            ) {

                /**
                 * Called when a drawer has settled in a completely closed state.
                 */
                public void onDrawerClosed(View view) {
                    super.onDrawerClosed(view);
                    //getActionBar().setTitle(mTitle);
                }

                /**
                 * Called when a drawer has settled in a completely open state.
                 */
                public void onDrawerOpened(View drawerView) {
                    super.onDrawerOpened(drawerView);
                    //getActionBar().setTitle(mDrawerTitle);
                }
            };

            // Set the drawer toggle as the DrawerListener
            drawerLayout.setDrawerListener(drawerToggle);
            getSupportActionBar().setDisplayHomeAsUpEnabled(true);
            getSupportActionBar().setHomeButtonEnabled(true);
        }

        drawerList.setOnItemClickListener(this);

        getSupportActionBar().setTitle(R.string.title_passwords);
    }

    @Override
    protected void onResume() {
        super.onResume();
        initializeDrawerItems(null);
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        getSupportFragmentManager().putFragment(outState, "fragment", fragment);
    }

    @Subscribe
    public void initializeDrawerItems(ReloadDrawerEvent event) {
        List<DrawerItem> drawerItems = new ArrayList<>();
        ImportDrawerItem importDrawerItem = new ImportDrawerItem(this, drawerLayout);
        ExportDrawerItem exportDrawerItem = new ExportDrawerItem(this, drawerLayout);
        List<Category> categories = defaultPrefs.categories();
        Collections.sort(categories);

        drawerItems.add(new AllCategoryDrawerItem(this));
        for (Category category : categories) {
            drawerItems.add(new CategoryDrawerItem(category));
        }
        if (!defaultPrefs.lockCategories()) {
            drawerItems.add(new AddCategoryDrawerItem(this));