package com.lateensoft.pathfinder.toolkit.views.encounter; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; import android.view.*; import android.widget.*; import com.lateensoft.pathfinder.toolkit.R; import com.lateensoft.pathfinder.toolkit.adapters.SelectableItemAdapter; import com.lateensoft.pathfinder.toolkit.views.BasePageFragment; import com.lateensoft.pathfinder.toolkit.views.MultiSelectActionModeController; import com.lateensoft.pathfinder.toolkit.views.picker.PickerUtil; import com.lateensoft.pathfinder.toolkit.views.widget.DynamicArrayAdapter; import com.lateensoft.pathfinder.toolkit.views.widget.DynamicListView; import java.util.List; import static com.lateensoft.pathfinder.toolkit.views.encounter.EncounterPresenter.EncounterStartMode; import static com.lateensoft.pathfinder.toolkit.views.encounter.EncounterRoller.SkillCheckType; public class EncounterFragment extends BasePageFragment { private static final int ADD_PARTICIPANTS_REQUEST_CODE = 2338; private static final int SELECT_ENCOUNTER_REQUEST_CODE = 8526; private EditText encounterNameEditor; private TextView lastSkillCheckName; private Button nextTurnButton; private DynamicListView participantList; private EncounterPresenter presenter; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); presenter = new EncounterPresenter(getContext()); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { setRootView(inflater.inflate(R.layout.fragment_encounters, container, false)); initializeComponents(); presenter.bind(this); return getRootView(); } private void initializeComponents() { encounterNameEditor = (EditText) getRootView().findViewById(R.id.et_encounter_name); lastSkillCheckName = (TextView) getRootView().findViewById(R.id.tv_last_skill_check); nextTurnButton = (Button) getRootView().findViewById(R.id.button_next); participantList = (DynamicListView) getRootView().findViewById(R.id.listview); participantList.setOnItemClickListener(listItemClickListener); participantList.setOnItemLongClickListener(listItemLongClickListener); encounterNameEditor.addTextChangedListener(encounterNameEditListener); nextTurnButton.setOnClickListener(nextTurnClickListener); } private AdapterView.OnItemClickListener listItemClickListener = new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if (actionModeController.isActionModeStarted()) { actionModeController.toggleListItemSelection(position); } else { presenter.onParticipantSelected(presenter.getModel().get(position)); } } }; private AdapterView.OnItemLongClickListener listItemLongClickListener = new AdapterView.OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { if (!actionModeController.isActionModeStarted()) { actionModeController.startActionModeWithInitialSelection(position); return true; } return false; } }; private TextWatcher encounterNameEditListener = new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} @Override public void onTextChanged(CharSequence s, int start, int before, int count) {} @Override public void afterTextChanged(Editable s) { presenter.onEncounterNameEdited(s); } }; private View.OnClickListener nextTurnClickListener = new View.OnClickListener() { @Override public void onClick(View v) { presenter.onNextTurnSelected(); } }; private MultiSelectActionModeController actionModeController = new MultiSelectActionModeController() { @Override public Activity getActivity() { return EncounterFragment.this.getActivity(); } @Override public int getActionMenuResourceId() { return R.menu.remove_action_mode_menu; } @Override public ListView getListView() { return participantList; } @Override public boolean onActionItemClicked(MultiSelectActionModeController controller, MenuItem item) { if (item.getItemId() == R.id.mi_remove) { showRemoveParticipantsFromEncounterDialog(getSelectedItems(presenter.getModel())); controller.finishActionMode(); return true; } return false; } }; private void showRemoveParticipantsFromEncounterDialog(final List<EncounterParticipantRowModel> participantsToRemove) { AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); builder.setTitle(R.string.membership_remove_dialog_title) .setMessage(String.format(getString(R.string.remove_participants_from_encounter_msg), participantsToRemove.size())); builder.setPositiveButton(R.string.ok_button_text, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { presenter.onParticipantsSelectedForDeletion(participantsToRemove); } }) .setNegativeButton(R.string.cancel_button_text, null) .show(); } @Override public void onPause() { presenter.onViewLostFocus(); super.onPause(); } public void notifyModelChanged() { rebuildParticipantListContent(); updateNonListUI(); } private void rebuildParticipantListContent() { if (actionModeController.isActionModeStarted()) { actionModeController.finishActionMode(); } EncounterParticipantListAdapter adapter = new EncounterParticipantListAdapter(getActivity(), presenter.getModel()); participantList.setDynamicAdapter(adapter); adapter.setDragIconTouchListener(dragIconTouchListener); adapter.setRollsClickListener(rollsClickedListener); adapter.setOnItemsSwappedListener(itemsSwappedListener); adapter.setItemSelectionGetter(new SelectableItemAdapter.ItemSelectionGetter() { @Override public boolean isItemSelected(int position) { return actionModeController.isListItemSelected(position); } }); } public void notifyModelAttributesChanged() { ((ArrayAdapter) participantList.getAdapter()).notifyDataSetChanged(); updateNonListUI(); } private void updateNonListUI() { updateTitle(); EncounterViewModel model = presenter.getModel(); encounterNameEditor.setText(model != null ? model.getName() : ""); SkillCheckType lastSkillCheck = presenter.getLastSkillCheck(); lastSkillCheckName.setText(lastSkillCheck != null ? getString(lastSkillCheck.getDisplayNameResId()) : "-"); nextTurnButton.setEnabled(presenter.isEncounterOngoing()); getActivity().invalidateOptionsMenu(); } private EncounterParticipantListAdapter.RowTouchListener dragIconTouchListener = new EncounterParticipantListAdapter.RowTouchListener() { @Override public void onTouch(View v, MotionEvent event, int position) { if (event.getAction() == MotionEvent.ACTION_DOWN && participantList.canHoverRows() && !actionModeController.isActionModeStarted()) { participantList.hoverRow(position); } } }; private EncounterParticipantListAdapter.RowComponentClickListener rollsClickedListener = new EncounterParticipantListAdapter.RowComponentClickListener() { @Override public void onClick(View v, int position) { new InitiativeEditorDialog(presenter.getModel().get(position)).show(); } }; private class InitiativeEditorDialog { private AlertDialog dialog; private EditText initiativeEditor; private EncounterParticipantRowModel row; public InitiativeEditorDialog(EncounterParticipantRowModel row) { this.row = row; AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); LayoutInflater inflater = LayoutInflater.from(getContext()); View dialogView = inflater.inflate(R.layout.edit_value_dialog, null); initiativeEditor = (EditText) dialogView.findViewById(R.id.editor); initiativeEditor.setHint(R.string.initiative_editor_hint); builder.setTitle(R.string.initiative_editor_title); initiativeEditor.append(Integer.toString(row.getParticipant().getInitiativeScore())); builder.setView(dialogView) .setPositiveButton(R.string.ok_button_text, okListener) .setNegativeButton(R.string.cancel_button_text, null); dialog = builder.create(); } private DialogInterface.OnClickListener okListener = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { presenter.onInitiativeEdited(initiativeEditor.getText(), row); hideKeyboardDelayed(0); } }; private void show() { dialog.show(); } } private DynamicArrayAdapter.ItemSwapListener itemsSwappedListener = new DynamicArrayAdapter.ItemSwapListener() { @Override public void onHoverEventFinished(DynamicListView.HoverEvent event) { presenter.onParticipantOrderChangeConfirmed(event.getStart(), event.getEnd()); } @Override public void onItemsSwapped(int pos1, int pos2) { presenter.onParticipantOrdersChanged(); } }; @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.encounters_menu, menu); super.onCreateOptionsMenu(menu, inflater); } @Override protected void onPreparePageOptionsMenu(Menu menu) { boolean isEncounterOngoing = presenter.isEncounterOngoing(); menu.findItem(R.id.mi_reset).setVisible(isEncounterOngoing); menu.findItem(R.id.mi_start).setVisible(!isEncounterOngoing); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.mi_start: showMenuPopup(R.menu.encounters_start_menu, getActivity().findViewById(R.id.mi_start), startEncounterPopupListener); break; case R.id.mi_reset: presenter.onEncounterResetSelected(); break; case R.id.mi_check_skill: showMenuPopup(R.menu.encounters_check_menu, getActivity().findViewById(R.id.mi_check_skill), checkSkillPopupListener); break; case R.id.mi_select_encounter: showChooseEncounterPicker(); break; case R.id.mi_add_participant: showAddCharactersPicker(); break; case R.id.mi_new_encounter: showNewEncounterDialog(); break; case R.id.mi_delete_encounter: showConfirmDeleteDialog(); break; } return super.onOptionsItemSelected(item); } private void showMenuPopup(int menuResource, View anchor, PopupMenu.OnMenuItemClickListener listener) { if (anchor == null) { anchor = getActivity().findViewById(R.id.overflow_popup_anchor); } PopupMenu popup = new PopupMenu(getActivity(), anchor); popup.setOnMenuItemClickListener(listener); popup.inflate(menuResource); popup.show(); } private PopupMenu.OnMenuItemClickListener startEncounterPopupListener = new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { EncounterStartMode mode = null; switch (item.getItemId()) { case R.id.mi_roll_init: mode = EncounterStartMode.AUTO_ROLL; break; case R.id.mi_manual_start: mode = EncounterStartMode.MANUAL; break; } presenter.onEncounterStarted(mode); return true; } }; private PopupMenu.OnMenuItemClickListener checkSkillPopupListener = new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { SkillCheckType checkType = null; switch (item.getItemId()) { case R.id.mi_fort_check: checkType = SkillCheckType.FORT; break; case R.id.mi_reflex_check: checkType = SkillCheckType.REFLEX; break; case R.id.mi_will_check: checkType = SkillCheckType.WILL; break; case R.id.mi_bluff_check: checkType = SkillCheckType.BLUFF; break; case R.id.mi_disguise_check: checkType = SkillCheckType.DISGUISE; break; case R.id.mi_perception_check: checkType = SkillCheckType.PERCEPTION; break; case R.id.mi_sense_check: checkType = SkillCheckType.SENSE; break; case R.id.mi_stealth_check: checkType = SkillCheckType.STEALTH; break; } presenter.onSkillCheckSelected(checkType); return true; } }; private static final String ENCOUNTER_PICKER_ITEM_KEY = "encounters"; private void showChooseEncounterPicker() { Intent pickerIntent = new PickerUtil.Builder(getContext()) .setTitle(R.string.encounter_picker_title) .setSingleChoice(true) .addPickableItems(ENCOUNTER_PICKER_ITEM_KEY, getString(R.string.title_fragment_encounters), presenter.getSelectableEncounters(), presenter.getModel().idNamePair()) .build(); startActivityForResult(pickerIntent, SELECT_ENCOUNTER_REQUEST_CODE); } private void showAddCharactersPicker() { Intent pickerIntent = new PickerUtil.Builder(getContext()) .setTitle(R.string.add_participants_to_encounter_picker_title) .setSingleChoice(false) .setPickableCharacters(presenter.getCharactersAvailableToAddToEncounter()) .setPickableParties(presenter.getPartiesAvailableToAddToEncounter()) .build(); startActivityForResult(pickerIntent, ADD_PARTICIPANTS_REQUEST_CODE); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (data == null) { return; } if (requestCode == ADD_PARTICIPANTS_REQUEST_CODE) { PickerUtil.ResultData result = new PickerUtil.ResultData(data); presenter.onCharactersAndPartiesSelectedToAddToEncounter( result.getCharacters(), result.getParties()); } else if (requestCode == SELECT_ENCOUNTER_REQUEST_CODE) { PickerUtil.ResultData result = new PickerUtil.ResultData(data); presenter.onEncounterSelected( result.getSelectedItemForKey(ENCOUNTER_PICKER_ITEM_KEY)); } } private void showConfirmDeleteDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); builder.setTitle(R.string.delete_alert_title) .setMessage(String.format(getString(R.string.delete_encounter_dialog_title), presenter.getModel().getName())); builder.setPositiveButton(R.string.cancel_button_text, null) .setNegativeButton(R.string.delete_button_text, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { presenter.onDeleteCurrentEncounterSelected(); } }) .show(); } private void showNewEncounterDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); builder.setTitle(R.string.menu_item_new_encounter) .setMessage(R.string.new_encounter_dialog_msg); builder.setPositiveButton(R.string.ok_button_text, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { presenter.onNewEncounterSelected(); } }) .setNegativeButton(R.string.cancel_button_text, null) .show(); } @Override public void updateTitle() { setTitle(R.string.title_fragment_encounters); setSubtitle(null); } }