Skip to content

Commit

Permalink
[android] confirm dialog retains checkbox after rotation. proper dial…
Browse files Browse the repository at this point in the history
…og creation.
  • Loading branch information
gubatron committed Mar 23, 2016
1 parent d9413ad commit ae69dc5
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

package com.frostwire.android.gui.dialogs;

import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface.OnCancelListener;
Expand Down Expand Up @@ -63,13 +64,23 @@ public abstract class AbstractConfirmListDialog<T> extends AbstractDialog implem
public enum SelectionMode {
NO_SELECTION,
SINGLE_SELECTION, // still work to do, crashes on rotate, won't auto select 0
MULTIPLE_SELECTION,
MULTIPLE_SELECTION;

public static SelectionMode fromInt(int n) {
SelectionMode selectionMode = SelectionMode.NO_SELECTION;
if (n == SelectionMode.MULTIPLE_SELECTION.ordinal()) {
selectionMode = SelectionMode.MULTIPLE_SELECTION;
} else if (n == SelectionMode.SINGLE_SELECTION.ordinal()) {
selectionMode = SelectionMode.SINGLE_SELECTION;
}
return selectionMode;
}
}

private final static String TAG = "confirm_list_dialog";
protected final static String TAG = "confirm_list_dialog";
private String title;
private String dialogText;
private final SelectionMode selectionMode;
private SelectionMode selectionMode;
private Dialog dlg;
private OnCancelListener onCancelListener;
private OnClickListener onYesListener;
Expand All @@ -80,22 +91,13 @@ public enum SelectionMode {
/** rebuilds list of objects from json and does listView.setAdapter(YourAdapter(theObjectList)) */
abstract public List<T> deserializeData(String listDataInJSON);

public AbstractConfirmListDialog(Context context, List<T> list, SelectionMode selectionMode, Bundle bundle) {
public AbstractConfirmListDialog() {
super(TAG, R.layout.dialog_confirm_list);
final ConfirmListDialogDefaultAdapter<T> adapter = createAdapter(context, list, selectionMode, bundle);
this.adapter = adapter;
this.selectionMode = adapter.getSelectionMode();
}

public AbstractConfirmListDialog(ConfirmListDialogDefaultAdapter customAdapter) {
super(TAG, R.layout.dialog_confirm_list);
if (customAdapter != null) {
this.adapter = customAdapter;
this.selectionMode = customAdapter.getSelectionMode();
} else {
this.adapter = null;
this.selectionMode = SelectionMode.MULTIPLE_SELECTION;
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
}

public SelectionMode getSelectionMode() {
Expand All @@ -113,13 +115,10 @@ protected void prepareArguments(int dialogIcon,
bundle.putString("dialogText", dialogText);
bundle.putString("listData", listDataInJSON);
bundle.putInt("selectionMode", selectionMode.ordinal());
this.selectionMode = selectionMode;
setArguments(bundle);
}

protected void prepareArguments(int dialogIcon, String dialogTitle, String dialogText, String listDataInJSON){
prepareArguments(dialogIcon, dialogTitle, dialogText, listDataInJSON, selectionMode);
}

@Override
protected void initComponents(Dialog dlg, Bundle savedInstanceState) {
this.dlg = dlg;
Expand Down Expand Up @@ -193,6 +192,11 @@ private void initListViewAndAdapter(Bundle bundle) {
ListView listView = findView(dlg, R.id.dialog_confirm_list_list);
String listDataString = bundle.getString("listData");
List<T> listData = deserializeData(listDataString);

if (selectionMode == null) {
selectionMode = SelectionMode.fromInt(bundle.getInt("selectionMode"));
}

if (adapter == null &&
listData != null &&
!listData.isEmpty()) {
Expand Down Expand Up @@ -266,16 +270,14 @@ public boolean[] getSelected() {
if (checked == null || checked.isEmpty()) {
return result;
}
result = new boolean[checked.size()];
result = new boolean[adapter.getCount()];
List<T> all = adapter.getList();
Iterator<T> iterator = checked.iterator();
while (iterator.hasNext()) {
T item = iterator.next();
int i = all.indexOf(item);
if (i >= 0 && i < result.length) {
if (i >= 0) {
result[i]=true;
} else {
LOGGER.warn("getSelected() is not finding the checked items on the list. Verify your classes implement equals() and hashCode()");
}
}
}
Expand All @@ -287,17 +289,18 @@ public int getLastSelected(){
}

public void updateSelectedCount() {
if (selectionMode != SelectionMode.MULTIPLE_SELECTION) {
return;
}

if (adapter == null) {
if (adapter == null || selectionMode != SelectionMode.MULTIPLE_SELECTION) {
return;
}

int selected = adapter.getCheckedCount();
updatedSelectedCount(selected);
autoToggleSelectAllCheckbox(selected);

final Bundle arguments = getArguments();
if (arguments != null) {
arguments.putBooleanArray("checkedOffsets", getSelected());
}
}

private void updatedSelectedCount(int selected) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,26 @@
import java.util.List;

public class ConfirmSoundcloudDownloadDialog extends AbstractConfirmListDialog<SoundcloudSearchResult> {
private ConfirmSoundcloudDownloadDialog(Context context, List<SoundcloudSearchResult> listData, SelectionMode selectionMode) {
super(context, listData, selectionMode, null);
}

public static ConfirmSoundcloudDownloadDialog newInstance(
Context ctx,
String dialogTitle,
String dialogText,
List<SoundcloudSearchResult> listData) {
ConfirmSoundcloudDownloadDialog dlg = new ConfirmSoundcloudDownloadDialog(ctx, listData, SelectionMode.MULTIPLE_SELECTION);
ConfirmSoundcloudDownloadDialog dlg = new ConfirmSoundcloudDownloadDialog();
SoundcloudSearchResultList srList = new SoundcloudSearchResultList();
srList.listData = listData;
dlg.prepareArguments(R.drawable.download_icon, dialogTitle, dialogText, JsonUtils.toJson(srList));

// this creates a bundle that gets passed to setArguments(). It's supposed to be ready
// before the dialog is attached to the underlying activity, after we attach to it, then
// we are able to use such Bundle to create our adapter.
dlg.prepareArguments(R.drawable.download_icon, dialogTitle, dialogText, JsonUtils.toJson(srList), SelectionMode.MULTIPLE_SELECTION);

dlg.setOnYesListener(new OnStartDownloadsClickListener(ctx, dlg));
return dlg;
}

public static void startDownloads(Context ctx, List<? extends SearchResult> srs) {
private static void startDownloads(Context ctx, List<? extends SearchResult> srs) {
if (srs != null && !srs.isEmpty()) {
for (SearchResult sr : srs) {
StartDownloadTask task = new StartDownloadTask(ctx, sr);
Expand Down Expand Up @@ -73,7 +75,7 @@ private static class OnStartDownloadsClickListener implements View.OnClickListen
private final WeakReference<Context> ctxRef;
private WeakReference<AbstractConfirmListDialog> dlgRef;

public OnStartDownloadsClickListener(Context ctx, AbstractConfirmListDialog dlg) {
OnStartDownloadsClickListener(Context ctx, AbstractConfirmListDialog dlg) {
ctxRef = new WeakReference<>(ctx);
dlgRef = new WeakReference<>(dlg);
}
Expand All @@ -86,27 +88,27 @@ public void setDialog(AbstractConfirmListDialog dlg) {
public void onClick(View v) {
if (Ref.alive(ctxRef) && Ref.alive(dlgRef)) {
final AbstractConfirmListDialog dlg = dlgRef.get();
try {
final AbstractConfirmListDialog.SelectionMode selectionMode = dlg.getSelectionMode();
List<SoundcloudSearchResult> results = (selectionMode == AbstractConfirmListDialog.SelectionMode.NO_SELECTION) ?
(List<SoundcloudSearchResult>) dlg.getList() :
new ArrayList<SoundcloudSearchResult>();

if (selectionMode == AbstractConfirmListDialog.SelectionMode.MULTIPLE_SELECTION) {
results.addAll(dlg.getChecked());
} else if (selectionMode == AbstractConfirmListDialog.SelectionMode.SINGLE_SELECTION) {
if (results == null || results.isEmpty()) {
return;
}
SoundcloudSearchResult selected = results.get(dlg.getLastSelected());
if (selected == null) {

return;
}
results.add(selected);

final AbstractConfirmListDialog.SelectionMode selectionMode = dlg.getSelectionMode();
List<SoundcloudSearchResult> results = (selectionMode == AbstractConfirmListDialog.SelectionMode.NO_SELECTION) ?
(List<SoundcloudSearchResult>) dlg.getList() :
new ArrayList<SoundcloudSearchResult>();

if (selectionMode == AbstractConfirmListDialog.SelectionMode.MULTIPLE_SELECTION) {
results.addAll(dlg.getChecked());
} else if (selectionMode == AbstractConfirmListDialog.SelectionMode.SINGLE_SELECTION) {
if (results.isEmpty()) {
return;
}
SoundcloudSearchResult selected = results.get(dlg.getLastSelected());
if (selected == null) {
return;
}
results.add(selected);
}

if (!results.isEmpty()) {
startDownloads(ctxRef.get(), results);
} finally {
dlg.dismiss();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,8 @@ public boolean equals(Object o) {
}
SoundcloudSearchResult other = (SoundcloudSearchResult) o;
return this.getDetailsUrl().equals(other.getDetailsUrl()) &&
this.getDisplayName().equals(other.getDisplayName()) &&
this.getDownloadUrl().equals(other.getDownloadUrl());
this.getDisplayName().equals(other.getDisplayName()) &&
this.getDownloadUrl().equals(other.getDownloadUrl());
}

@Override
Expand Down

1 comment on commit ae69dc5

@gubatron
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @aldenml you're the man.
Now I understand how setArguments(Bundle bundle) (can only be called once) works and how you can use that Bundle and alter the contents of its inner map anytime later with getArguments() and then being able to use the context only after the onAttach().

It all makes sense now.

Please sign in to comment.