package net.coding.program.project.detail; import android.content.DialogInterface; import android.content.Intent; import android.graphics.Color; import android.graphics.drawable.GradientDrawable; import android.support.v7.app.AlertDialog; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.WindowManager; import android.widget.EditText; import android.widget.ImageView; import android.widget.LinearLayout; import net.coding.program.R; import net.coding.program.common.ui.BackActivity; import net.coding.program.model.RequestData; import net.coding.program.model.TopicLabelObject; import net.coding.program.model.TopicObject; import org.androidannotations.annotations.AfterViews; import org.androidannotations.annotations.Click; import org.androidannotations.annotations.EActivity; import org.androidannotations.annotations.Extra; import org.androidannotations.annotations.InstanceState; import org.androidannotations.annotations.OnActivityResult; import org.androidannotations.annotations.OptionsItem; import org.androidannotations.annotations.ViewById; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.Random; /** * Created by Neutra on 2015/4/25. * 标签编辑 */ @EActivity(R.layout.activity_topic_label) public class TopicLabelActivity extends BackActivity { private static final int RESULT_PICK_COLOR = 1; private static final int RESULT_MODIFY = 2; private static String COLOR = "#701035"; @Extra LabelType labelType = LabelType.Topic; @Extra String projectPath; // 必填 @Extra int id = 0; // 必填 @Extra ArrayList<TopicLabelObject> checkedLabels; // 必填 TopicObject.LabelUrl labelUrl; @ViewById LinearLayout labelsList; @ViewById EditText editText; @ViewById View action_add, container; @ViewById ImageView colorPreview; int generateColor = 0; @InstanceState String currentLabelName; @InstanceState int currentLabelId; private LinkedHashMap<Integer, TopicLabelObject> allLabels = new LinkedHashMap<>(); private LinkedHashSet<Integer> checkedIds = new LinkedHashSet<>(); private boolean saveTopicLabels = false; private boolean isBuzy; private MenuItem menuActionSave; public static void removeEmptyLabel(ArrayList<TopicLabelObject> list) { for (int i = 0; i < list.size(); ++i) { if (list.get(i).isEmpty()) { list.remove(i); --i; } } } @AfterViews protected final void initTopicLabelActivity() { generateColor = getRandomColor(); updateColorPreview(); if (labelType == LabelType.Topic) { labelUrl = new TopicObject.TopicLabelUrl(projectPath, id); } else { labelUrl = new TopicObject.TaskLabelUrl(projectPath, id); } checkedIds.clear(); if (checkedLabels == null) checkedLabels = new ArrayList<>(); for (TopicLabelObject item : checkedLabels) { checkedIds.add(item.id); } beginLoadLabels(); } private void updateColorPreview() { GradientDrawable bgDrawable = (GradientDrawable) colorPreview.getBackground(); if (bgDrawable != null) { bgDrawable.setColor(generateColor); } } @Click void colorPreview() { PickLabelColorActivity_.intent(this) .generateColor(generateColor) .startForResult(RESULT_PICK_COLOR); } @Click void action_add() { if (lockViews()) { String name = editText.getText().toString().trim(); if (TextUtils.isEmpty(name)) { showButtomToast("名字不能为空"); unlockViews(); return; } action_add.setEnabled(false); editText.setEnabled(false); beginAddLebel(name); } } @OnActivityResult(RESULT_PICK_COLOR) void onResultPickColor(int result, @OnActivityResult.Extra int resultData) { if (result == RESULT_OK) { generateColor = resultData; updateColorPreview(); } } @OnActivityResult(RESULT_MODIFY) void onResultModify(int result, @OnActivityResult.Extra TopicLabelObject resultData) { if (result == RESULT_OK) { if (allLabels.containsKey(currentLabelId)) { TopicLabelObject topicLabelObject = allLabels.get(currentLabelId); topicLabelObject.name = resultData.name; topicLabelObject.color = resultData.color; } updateList(); } unlockViews(); } @OptionsItem void action_save() { if (id != 0) { beginSaveTopicLabels(); } else { saveTopicLabels = true; finish(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater menuInflater = getMenuInflater(); menuInflater.inflate(R.menu.topic_label, menu); menuActionSave = menu.findItem(R.id.action_save); menuActionSave.setEnabled(false); return super.onCreateOptionsMenu(menu); } private void updateMenuActionSave() { if (isLabelsChanged(false)) { menuActionSave.setEnabled(true); menuActionSave.setIcon(R.drawable.ic_menu_ok); } else { menuActionSave.setEnabled(false); menuActionSave.setIcon(R.drawable.ic_menu_ok_unable); } } private boolean lockViews() { if (!isBuzy) { editText.setEnabled(false); action_add.setEnabled(false); isBuzy = true; showDialogLoading(); return true; } return false; } private void unlockViews() { hideProgressDialog(); isBuzy = false; editText.setEnabled(true); action_add.setEnabled(true); } @Override public void parseJson(int code, JSONObject respanse, String tag, int pos, Object data) throws JSONException { // 不同操作可能URI一样,METHOD不一样 if ("URI_GET_LABEL".equals(tag)) { endLoadLabels(code, respanse); } else if ("URI_ADD_LABEL".equals(tag)) { endAddLabel(code, respanse); } else if ("URI_REMOVE_LABEL".equals(tag)) { endRemoveLabel(code, respanse); } else if ("URI_RENAME_LABEL".equals(tag)) { endRenameLabel(code, respanse); } else if ("URI_SAVE_TOPIC_LABELS".equals(tag)) { endSaveTopicLabels(code, respanse); } } private void beginLoadLabels() { if (lockViews()) { getNetwork(labelUrl.getLabels(), "URI_GET_LABEL"); } } private void endLoadLabels(int code, JSONObject json) throws JSONException { if (code == 0) { allLabels.clear(); JSONArray array = json.getJSONArray("data"); for (int i = 0, n = array.length(); i < n; i++) { TopicLabelObject data = new TopicLabelObject(array.optJSONObject(i)); if (!data.isEmpty()) { allLabels.put(data.id, data); } } updateList(); } else { showErrorMsg(code, json); } unlockViews(); } private void beginAddLebel(String name) { currentLabelName = name.trim(); COLOR = String.format("#%06X", generateColor & 0x00FFFFFF); RequestData post = labelUrl.addLabel(currentLabelName, COLOR); postNetwork(post.url, post.params, "URI_ADD_LABEL"); } public static int getRandomColor() { return 0xFF000000 | new Random().nextInt(0xFFFFFF); } private void endAddLabel(int code, JSONObject json) throws JSONException { if (code == 0) { currentLabelId = json.getInt("data"); editText.setText(""); allLabels.put(currentLabelId, new TopicLabelObject(currentLabelId, currentLabelName, Color.parseColor(COLOR))); updateList(); showButtomToast("添加标签成功^^"); endAddTopicLabel(); updateMenuActionSave(); } else { showErrorMsg(code, json); } unlockViews(); } private void beginRemoveLabel() { deleteNetwork(labelUrl.removeLabel(currentLabelId), "URI_REMOVE_LABEL"); } private void endRemoveLabel(int code, JSONObject json) { if (code != 0) { showErrorMsg(code, json); } else { allLabels.remove(currentLabelId); updateList(); } unlockViews(); } private void beginRenameLabel(String newName) { currentLabelName = newName; RequestData postRename = labelUrl.renameLabel(currentLabelId, newName, COLOR); putNetwork(postRename.url, postRename.params, "URI_RENAME_LABEL"); } private void endRenameLabel(int code, JSONObject json) { if (code != 0) { showErrorMsg(code, json); } else { if (allLabels.containsKey(currentLabelId)) { allLabels.get(currentLabelId).name = currentLabelName; } updateList(); } unlockViews(); } private void beginSaveTopicLabels() { if (!isLabelsChanged(false)) { endSaveTopicLabels(); } else { if (lockViews()) { RequestData postSave = labelUrl.saveTopic(checkedIds); postNetwork(postSave.url, postSave.params, "URI_SAVE_TOPIC_LABELS"); } } } private void endSaveTopicLabels() { saveTopicLabels = true; finish(); } private boolean isLabelsChanged(boolean checkNames) { if (checkedIds.size() != checkedLabels.size()) return true; for (TopicLabelObject oldItem : checkedLabels) { if (!checkedIds.contains(oldItem.id)) return true; if (checkNames) { TopicLabelObject newItem = allLabels.get(oldItem.id); if (newItem == null || !newItem.name.equals(oldItem.name)) return true; } } return false; } @Override public void finish() { if (saveTopicLabels) { // 保存时直接返回新标签列表 ArrayList<TopicLabelObject> result = new ArrayList<>(); for (int id : checkedIds) { TopicLabelObject labelObject = allLabels.get(id); if (labelObject != null) result.add(labelObject); } Intent data = new Intent(); data.putExtra("labels", result); setResult(RESULT_OK, data); } else { // 不保存时(后退),返回原选中的标签列表的最新状态(可能被删除或者重命名) if (isLabelsChanged(true)) { ArrayList<TopicLabelObject> result = new ArrayList<>(); if (checkedLabels != null) { for (TopicLabelObject item : checkedLabels) { TopicLabelObject newItem = allLabels.get(item.id); if (newItem != null) result.add(newItem); } } Intent data = new Intent(); data.putExtra("labels", result); setResult(RESULT_OK, data); } } super.finish(); } private void endSaveTopicLabels(int code, JSONObject json) { if (code != 0) { showErrorMsg(code, json); } else { endSaveTopicLabels(); } unlockViews(); } private void endAddTopicLabel() { checkedIds.add(currentLabelId); onTopicLabelsChange(); } private void endRemoveTopicLabel() { checkedIds.remove(currentLabelId); onTopicLabelsChange(); } public void showPop(View view) { AlertDialog dialog = new AlertDialog.Builder(this) .setItems(R.array.topic_label_action, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { switch (which) { case 0: // doRename(); for (TopicLabelObject item : allLabels.values()) { if (item.id == currentLabelId) { ModifyLabelActivity_.intent(TopicLabelActivity.this) .labelObject(item) .projectPath(projectPath) .startForResult(RESULT_MODIFY); } } break; case 1: doDelete(); updateMenuActionSave(); break; } } }).show(); } private void doDelete() { new AlertDialog.Builder(this) .setTitle("删除标签").setMessage(String.format("确定要删除标签“%s”么?", currentLabelName)) .setPositiveButton("确定", (dialog1, which) -> { if (lockViews()) { beginRemoveLabel(); } }) .setNegativeButton("取消", null) .show(); } private void doRename() { LayoutInflater inflater = LayoutInflater.from(this); View view = inflater.inflate(R.layout.dialog_input, null); final EditText input = (EditText) view.findViewById(R.id.value); input.setText(currentLabelName); new AlertDialog.Builder(this) .setTitle("重命名") .setView(view) .setPositiveButton("确定", (dialog1, which) -> { String newName = input.getText().toString().trim(); if (TextUtils.isEmpty(newName)) { showButtomToast("名字不能为空"); return; } if (lockViews()) { beginRenameLabel(newName); } getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); }) .setNegativeButton("取消", null) .show(); input.requestFocus(); } private void updateCheckState() { for (int i = 0, n = labelsList.getChildCount(); i < n; i++) { View view = labelsList.getChildAt(i); if (view instanceof TopicLabelItemView) { TopicLabelItemView itemView = (TopicLabelItemView) view; itemView.setChecked(checkedIds.contains(itemView.data.id)); } } } private void updateList() { LinkedList<View> cachedDividers = new LinkedList<>(); LinkedList<TopicLabelItemView> cachedViews = new LinkedList<>(); for (int i = 0, n = labelsList.getChildCount(); i < n; i++) { View view = labelsList.getChildAt(i); if (view instanceof TopicLabelItemView) { cachedViews.add((TopicLabelItemView) view); } else { cachedDividers.add(view); } } labelsList.removeAllViews(); boolean isFirst = true; LayoutInflater inflater = LayoutInflater.from(this); for (TopicLabelObject item : allLabels.values()) { if (isFirst) { isFirst = false; } else { addDivider(inflater, cachedDividers.poll()); } addLabel(item, cachedViews.poll()); } container.setVisibility(labelsList.getChildCount() > 0 ? View.VISIBLE : View.GONE); } private void addLabel(final TopicLabelObject data, TopicLabelItemView view) { if (view == null) { view = TopicLabelItemView_.build(this); view.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { TopicLabelItemView view = (TopicLabelItemView) v; currentLabelId = view.data.id; currentLabelName = view.data.name; showPop(v); return true; } }); view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { TopicLabelItemView view = (TopicLabelItemView) v; currentLabelId = view.data.id; if (checkedIds.contains(view.data.id)) { endRemoveTopicLabel(); } else { endAddTopicLabel(); } updateMenuActionSave(); } }); } view.bind(data); view.setChecked(checkedIds.contains(data.id)); labelsList.addView(view); } private void addDivider(LayoutInflater inflater, View view) { if (view == null) view = inflater.inflate(R.layout.activity_topic_label_divider, labelsList, false); labelsList.addView(view); } private void onTopicLabelsChange() { updateCheckState(); } public enum LabelType { Topic, Task } }