/* * Catroid: An on-device visual programming system for Android devices * Copyright (C) 2010-2016 The Catrobat Team * (<http://developer.catrobat.org/credits>) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * An additional term exception under section 7 of the GNU Affero * General Public License, version 3, is available at * http://developer.catrobat.org/license_additional_term * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.catrobat.catroid.ui.fragment; import android.app.ActionBar; import android.app.Activity; import android.app.Fragment; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.content.Context; import android.content.res.Resources; import android.os.Bundle; import android.util.Log; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.Menu; import android.view.View; import android.view.View.OnKeyListener; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.Button; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; import org.catrobat.catroid.ProjectManager; import org.catrobat.catroid.R; import org.catrobat.catroid.content.Sprite; import org.catrobat.catroid.content.bricks.UserBrick; import org.catrobat.catroid.content.bricks.UserScriptDefinitionBrick; import org.catrobat.catroid.content.bricks.UserScriptDefinitionBrickElement; import org.catrobat.catroid.formulaeditor.DataContainer; import org.catrobat.catroid.formulaeditor.UserVariable; import org.catrobat.catroid.ui.BottomBar; import org.catrobat.catroid.ui.BrickLayout; import org.catrobat.catroid.ui.DragAndDropBrickLayoutListener; import org.catrobat.catroid.ui.DragNDropBrickLayout; import org.catrobat.catroid.ui.LineBreakListener; import org.catrobat.catroid.ui.ScriptActivity; import org.catrobat.catroid.ui.dialogs.UserBrickEditElementDialog; import java.util.ArrayList; import java.util.List; public class UserBrickElementEditorFragment extends Fragment implements OnKeyListener, DragAndDropBrickLayoutListener, UserBrickEditElementDialog.DialogListener, LineBreakListener { private static final String TAG = UserBrickElementEditorFragment.class.getSimpleName(); public static final String BRICK_DATA_EDITOR_FRAGMENT_TAG = "brick_data_editor_fragment"; private static final String BRICK_BUNDLE_ARGUMENT = "current_brick"; private Context context; private UserScriptDefinitionBrick currentBrick; private int indexOfCurrentlyEditedElement; private LinearLayout editorBrickSpace; private View brickView; private View fragmentView; private String actionBarTitleToRestore; public UserBrickElementEditorFragment() { } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); ActionBar actionBar = getActivity().getActionBar(); if (actionBar != null) { actionBarTitleToRestore = actionBar.getTitle().toString(); actionBar.setTitle(getString(R.string.brick_data_editor_title)); } currentBrick = (UserScriptDefinitionBrick) getArguments().getSerializable(BRICK_BUNDLE_ARGUMENT); } public static void showFragment(View view, UserScriptDefinitionBrick brick) { Activity activity = (Activity) view.getContext(); UserBrickElementEditorFragment dataEditorFragment = (UserBrickElementEditorFragment) activity .getFragmentManager().findFragmentByTag(BRICK_DATA_EDITOR_FRAGMENT_TAG); FragmentManager fragmentManager = activity.getFragmentManager(); FragmentTransaction fragTransaction = fragmentManager.beginTransaction(); fragTransaction.addToBackStack(null); if (dataEditorFragment == null) { dataEditorFragment = new UserBrickElementEditorFragment(); Bundle bundle = new Bundle(); bundle.putSerializable(BRICK_BUNDLE_ARGUMENT, brick); dataEditorFragment.setArguments(bundle); fragTransaction.add(R.id.fragment_container, dataEditorFragment, BRICK_DATA_EDITOR_FRAGMENT_TAG); fragTransaction.hide(fragmentManager.findFragmentByTag(ScriptFragment.TAG)); fragTransaction.show(dataEditorFragment); BottomBar.hideBottomBar(activity); } else if (dataEditorFragment.isHidden()) { dataEditorFragment.updateBrickView(); fragTransaction.hide(fragmentManager.findFragmentByTag(ScriptFragment.TAG)); fragTransaction.show(dataEditorFragment); BottomBar.hideBottomBar(activity); } fragTransaction.commit(); } private void onUserDismiss() { Activity activity = getActivity(); FragmentManager fragmentManager = activity.getFragmentManager(); fragmentManager.popBackStack(); if (activity instanceof ScriptActivity) { ((ScriptActivity) activity).setupActionBar(); ((ScriptActivity) activity).redrawBricks(); } else { Log.e(TAG, "UserBrickDataEditor.onUserDismiss() called when the parent activity is not a UserBrickScriptActivity!\n" + "This should never happen, afaik. I don't know how to correctly reset the action bar..."); } ActionBar actionBar = activity.getActionBar(); if (actionBar != null) { actionBar.setTitle(actionBarTitleToRestore); } BottomBar.showBottomBar(getActivity()); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { fragmentView = inflater.inflate(R.layout.fragment_brick_data_editor, container, false); fragmentView.setFocusableInTouchMode(true); fragmentView.requestFocus(); context = getActivity(); brickView = View.inflate(context, R.layout.brick_user_editable, null); updateBrickView(); editorBrickSpace = (LinearLayout) fragmentView.findViewById(R.id.brick_data_editor_brick_space); editorBrickSpace.addView(brickView); ListView buttonList = (ListView) fragmentView.findViewById(R.id.button_list); buttonList.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Resources resources = getResources(); String[] actions = resources.getStringArray(R.array.data_editor_buttons); String action = actions[position]; if (action.equals(resources.getString(R.string.add_text))) { addTextDialog(); } if (action.equals(resources.getString(R.string.add_variable))) { addVariableDialog(); } if (action.equals(resources.getString(R.string.add_line_break))) { addLineBreak(); } if (action.equals(resources.getString(R.string.close))) { onUserDismiss(); } } }); return fragmentView; } public void addTextDialog() { int indexOfNewText = currentBrick.addUIText(""); editElementDialog("", false, R.string.add_text, R.string.text_hint); indexOfCurrentlyEditedElement = indexOfNewText; updateBrickView(); } public void addLineBreak() { currentBrick.addUILineBreak(); updateBrickView(); } public void addVariableDialog() { DataContainer dataContainer = ProjectManager.getInstance().getCurrentScene().getDataContainer(); String variableName = dataContainer.getUniqueVariableName(getActivity()); int indexOfNewVariableText = currentBrick.addUILocalizedVariable(variableName); editElementDialog(variableName, false, R.string.add_variable, R.string.variable_hint); indexOfCurrentlyEditedElement = indexOfNewVariableText; updateBrickView(); } public void editElementDialog(CharSequence text, boolean editMode, int title, int defaultText) { DataContainer dataContainer = ProjectManager.getInstance().getCurrentScene().getDataContainer(); Sprite currentSprite = ProjectManager.getInstance().getCurrentSprite(); UserBrick currentUserBrick = ProjectManager.getInstance().getCurrentUserBrick(); List<UserVariable> spriteVariables = dataContainer.getOrCreateVariableListForSprite(currentSprite); List<UserVariable> globalVariables = dataContainer.getProjectVariables(); List<UserVariable> userBrickVariables = dataContainer.getOrCreateVariableListForUserBrick(currentUserBrick); ArrayList<String> takenVariables = new ArrayList<>(); for (UserVariable variable : userBrickVariables) { takenVariables.add(variable.getName()); } for (UserVariable variable : spriteVariables) { takenVariables.add(variable.getName()); } for (UserVariable variable : globalVariables) { takenVariables.add(variable.getName()); } UserBrickEditElementDialog dialog = new UserBrickEditElementDialog(fragmentView); dialog.addDialogListener(this); dialog.show(getActivity().getFragmentManager(), UserBrickEditElementDialog.DIALOG_FRAGMENT_TAG); UserBrickEditElementDialog.setTakenVariables(takenVariables); UserBrickEditElementDialog.setTitle(title); UserBrickEditElementDialog.setText(text); UserBrickEditElementDialog.setHintText(defaultText); UserBrickEditElementDialog.setEditMode(editMode); dialog.setUserBrickElementEditorFragment(this); } @Override public void onFinishDialog(CharSequence text, boolean editMode) { UserScriptDefinitionBrickElement element = currentBrick.getUserScriptDefinitionBrickElements().get(indexOfCurrentlyEditedElement); if (element != null) { if (text != null) { String oldString = element.getText(); String newString = text.toString(); currentBrick.renameUIElement(element, oldString, newString, getActivity()); } else if (element.getText().toString().isEmpty()) { currentBrick.getUserScriptDefinitionBrickElements().remove(element); } } updateUserBrickParameters(currentBrick); updateBrickView(); } private void updateUserBrickParameters(UserScriptDefinitionBrick definitionBrick) { Sprite sprite = ProjectManager.getInstance().getCurrentSprite(); List<UserBrick> userBricks = sprite.getUserBricksByDefinitionBrick(definitionBrick, true, true); for (UserBrick userBrick : userBricks) { userBrick.updateUserBrickParametersAndVariables(); } } @Override public void reorder(int from, int to) { currentBrick.reorderUIData(from, to); updateBrickView(); } @Override public void click(int id) { UserScriptDefinitionBrickElement element = currentBrick.getUserScriptDefinitionBrickElements().get(id); if (element != null && !element.isLineBreak()) { int title = element.isVariable() ? R.string.edit_variable : R.string.edit_text; int defaultText = element.isVariable() ? R.string.variable_hint : R.string.text_hint; editElementDialog(element.getText(), true, title, defaultText); indexOfCurrentlyEditedElement = id; } } private void deleteButtonClicked(View theView) { DragNDropBrickLayout layout = (DragNDropBrickLayout) brickView.findViewById(R.id.brick_user_flow_layout); int found = -1; for (int i = 0; i < layout.getChildCount(); i++) { if (layout.getChildAt(i) == theView) { found = i; } } if (found > -1) { currentBrick.removeDataAt(found, theView.getContext()); updateUserBrickParameters(currentBrick); updateBrickView(); } } public void updateBrickView() { Context context = brickView.getContext(); DragNDropBrickLayout layout = (DragNDropBrickLayout) brickView.findViewById(R.id.brick_user_flow_layout); layout.setListener(this); if (layout.getChildCount() > 0) { layout.removeAllViews(); } for (UserScriptDefinitionBrickElement element : currentBrick.getUserScriptDefinitionBrickElements()) { View dataView; if (element.isLineBreak()) { dataView = View.inflate(context, R.layout.brick_user_data_line_break, null); } else { if (element.isVariable()) { dataView = View.inflate(context, R.layout.brick_user_data_variable, null); } else { dataView = View.inflate(context, R.layout.brick_user_data_text, null); } } TextView textView = (TextView) dataView.findViewById(R.id.text_view); if (textView != null) { textView.setText(element.getText()); } Button button = (Button) dataView.findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { deleteButtonClicked((View) view.getParent()); } }); layout.addView(dataView); if (element.isLineBreak()) { BrickLayout.LayoutParams params = (BrickLayout.LayoutParams) dataView.getLayoutParams(); params.setNewLine(true); } layout.registerLineBreakListener(this); } } @Override public void setBreaks(List<Integer> breaks) { for (UserScriptDefinitionBrickElement data : currentBrick.getUserScriptDefinitionBrickElements()) { data.setNewLineHint(false); } for (int breakIndex : breaks) { currentBrick.getUserScriptDefinitionBrickElements().get(breakIndex).setNewLineHint(true); } } @Override public void onPrepareOptionsMenu(Menu menu) { for (int index = 0; index < menu.size(); index++) { menu.getItem(index).setVisible(false); } getActivity().getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); getActivity().getActionBar().setDisplayShowTitleEnabled(true); super.onPrepareOptionsMenu(menu); } @Override public boolean onKey(View view, int keyCode, KeyEvent event) { switch (keyCode) { case KeyEvent.KEYCODE_BACK: onUserDismiss(); return true; } return false; } public void decreaseIndexOfCurrentlyEditedElement() { indexOfCurrentlyEditedElement--; } }