/* * 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.formulaeditor; import android.content.Context; import org.catrobat.catroid.ProjectManager; import org.catrobat.catroid.R; import org.catrobat.catroid.content.Project; import org.catrobat.catroid.content.Scene; import org.catrobat.catroid.content.Sprite; import org.catrobat.catroid.content.bricks.UserBrick; import org.catrobat.catroid.content.bricks.UserScriptDefinitionBrickElement; import org.catrobat.catroid.ui.UserBrickScriptActivity; import org.catrobat.catroid.ui.adapter.DataAdapter; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; public class DataContainer extends BaseDataContainer { public static final transient int USER_VARIABLE_SPRITE = 0; public static final transient int USER_VARIABLE_PROJECT = 1; public static final transient int USER_VARIABLE_USERBRICK = 2; public static final transient int USER_LIST_SPRITE = 4; public static final transient int USER_LIST_PROJECT = 5; public static final transient int USER_DATA_EMPTY = 6; private transient Project project; public DataContainer(Project project) { spriteVariables = new HashMap<>(); spriteListOfLists = new HashMap<>(); this.project = project; } private DataContainer() { } public void cloneSpriteVariablesForScene(Scene scene, DataContainer original) { Map<Sprite, List<UserVariable>> clonedList = new HashMap<>(); for (Map.Entry<Sprite, List<UserVariable>> entry : original.spriteVariables.entrySet()) { List<UserVariable> newList = new ArrayList<>(); for (UserVariable userVariable : entry.getValue()) { newList.add(new UserVariable(userVariable.getName())); } if (entry.getKey() == null) { continue; } Sprite clonedSpriteInstance = scene.getSpriteBySpriteName(entry.getKey().getName()); clonedList.put(clonedSpriteInstance, newList); } spriteVariables = clonedList; } public void cloneSpriteListsForScene(Scene scene, DataContainer original) { Map<Sprite, List<UserList>> clonedList = new HashMap<>(); for (Map.Entry<Sprite, List<UserList>> entry : original.spriteListOfLists.entrySet()) { List<UserList> newList = new ArrayList<>(); for (UserList userList : entry.getValue()) { newList.add(new UserList(userList.getName())); } Sprite newSpriteInstance = scene.getSpriteBySpriteName(entry.getKey().getName()); clonedList.put(newSpriteInstance, newList); } spriteListOfLists = clonedList; } public void setSpriteVariablesForSupportContainer(SupportDataContainer container) { if (container.spriteVariables != null) { spriteVariables = container.spriteVariables; } if (container.userBrickVariables != null) { userBrickVariables = container.userBrickVariables; } if (container.spriteListOfLists != null) { spriteListOfLists = container.spriteListOfLists; } } public void setProject(Project project) { this.project = project; } public List<UserVariable> getProjectVariables() { if (project == null) { project = ProjectManager.getInstance().getCurrentProject(); } return project.getProjectVariables(); } public Map<Sprite, List<UserVariable>> getSpriteVariableMap() { return spriteVariables; } public List<UserList> getProjectLists() { if (project == null) { project = ProjectManager.getInstance().getCurrentProject(); } return project.getProjectLists(); } public void removeVariablesOfClones() { for (Sprite s : new HashSet<>(spriteVariables.keySet())) { if (s.isClone) { spriteVariables.remove(s); } } for (Sprite s : new HashSet<>(spriteListOfLists.keySet())) { if (s.isClone) { spriteListOfLists.remove(s); } } } public DataAdapter createDataAdapter(Context context, Sprite sprite) { List<UserVariable> userBrickVariables = new LinkedList<>(); List<UserVariable> spriteVariables = getOrCreateVariableListForSprite(sprite); List<UserList> spriteUserList = getOrCreateUserListListForSprite(sprite); return new DataAdapter(context, spriteUserList, getProjectLists(), spriteVariables, getProjectVariables(), userBrickVariables); } public DataAdapter createDataAdapter(Context context, UserBrick userBrick, Sprite sprite) { List<UserVariable> userBrickVariables; if (userBrick == null || !(context instanceof UserBrickScriptActivity)) { userBrickVariables = new LinkedList<>(); } else { userBrickVariables = getOrCreateVariableListForUserBrick(userBrick); } List<UserVariable> spriteVariables = getOrCreateVariableListForSprite(sprite); List<UserList> spriteUserList = getOrCreateUserListListForSprite(sprite); return new DataAdapter(context, spriteUserList, getProjectLists(), spriteVariables, getProjectVariables(), userBrickVariables); } public UserVariable getUserVariable(String userVariableName, Sprite sprite) { UserVariable userVariable; userVariable = findUserVariable(userVariableName, getOrCreateVariableListForSprite(sprite)); if (userVariable == null) { userVariable = findUserVariable(userVariableName, getProjectVariables()); } UserBrick userBrick = getCurrentUserBrick(); if (userVariable == null && userBrick != null) { userVariable = findUserVariable(userVariableName, getOrCreateVariableListForUserBrick(userBrick)); } return userVariable; } public UserVariable addSpriteVariableIfDoesNotExist(String userVariableName, Sprite sprite) { UserVariable addedUserVariable = null; List<UserVariable> list = spriteVariables.get(sprite); if (list == null) { list = new ArrayList<>(); } for (UserVariable variable : list) { if (variable.getName().equals(userVariableName)) { addedUserVariable = variable; } } if (addedUserVariable == null) { addedUserVariable = new UserVariable(userVariableName); list.add(addedUserVariable); spriteVariables.put(sprite, list); } return addedUserVariable; } public UserList addSpriteListIfDoesNotExist(String userListName, Sprite sprite) { UserList addedUserList = null; List<UserList> lists = spriteListOfLists.get(sprite); if (lists == null) { lists = new ArrayList<>(); } for (UserList list : lists) { if (list.getName().equals(userListName)) { addedUserList = list; } } if (addedUserList == null) { addedUserList = new UserList(userListName); lists.add(addedUserList); spriteListOfLists.put(sprite, lists); } return addedUserList; } public UserVariable addUserBrickVariableToUserBrickIfNotExists(UserBrick userBrick, String userVariableName, Object userVariableValue) { List<UserVariable> varList = getOrCreateVariableListForUserBrick(userBrick); UserVariable userVariableToAdd = null; for (UserVariable existingVariable : varList) { if (existingVariable.getName().equals(userVariableName)) { userVariableToAdd = existingVariable; break; } } if (userVariableToAdd == null) { userVariableToAdd = new UserVariable(userVariableName, userVariableValue); varList.add(userVariableToAdd); } return userVariableToAdd; } public UserVariable addUserBrickVariableToUserBrick(UserBrick userBrick, String userVariableName, Object userVariableValue) { List<UserVariable> varList = getOrCreateVariableListForUserBrick(userBrick); UserVariable userVariableToAdd = new UserVariable(userVariableName, userVariableValue); varList.add(userVariableToAdd); return userVariableToAdd; } public UserVariable addSpriteUserVariable(String userVariableName) { Sprite currentSprite = ProjectManager.getInstance().getCurrentSprite(); return addSpriteUserVariableToSprite(currentSprite, userVariableName); } public UserList renameSpriteUserList(String newName, String oldName) { Sprite currentSprite = ProjectManager.getInstance().getCurrentSprite(); List<UserList> varList = getOrCreateUserListListForSprite(currentSprite); UserList userListToRename = findUserList(oldName, varList); userListToRename.setName(newName); return userListToRename; } public UserVariable renameSpriteUserVariable(String newName, String oldName) { Sprite currentSprite = ProjectManager.getInstance().getCurrentSprite(); List<UserVariable> varList = getOrCreateVariableListForSprite(currentSprite); UserVariable userVariableToRename = findUserVariable(oldName, varList); userVariableToRename.setName(newName); return userVariableToRename; } public UserVariable addSpriteUserVariableToSprite(Sprite sprite, String userVariableName) { List<UserVariable> varList = getOrCreateVariableListForSprite(sprite); UserVariable userVariableToAdd = new UserVariable(userVariableName); varList.add(userVariableToAdd); return userVariableToAdd; } public UserVariable addProjectUserVariable(String userVariableName) { UserVariable userVariableToAdd = new UserVariable(userVariableName); getProjectVariables().add(userVariableToAdd); return userVariableToAdd; } public UserVariable renameProjectUserVariable(String newName, String oldName) { UserVariable userVariableToRename = findUserVariable(oldName, getProjectVariables()); userVariableToRename.setName(newName); return userVariableToRename; } /** * This function deletes the user variable with userVariableName in the current context. * * The current context consists of all global variables, the sprite variables for the current sprite, * and the user brick variables for the current user brick. */ public void deleteUserVariableByName(String userVariableName) { Sprite currentSprite = ProjectManager.getInstance().getCurrentSprite(); UserBrick userBrick = getCurrentUserBrick(); List<UserVariable> context = getUserVariableContext(userVariableName, userBrick, currentSprite); if (context != null) { UserVariable variableToDelete = findUserVariable(userVariableName, context); if (variableToDelete != null) { context.remove(variableToDelete); if (userBrick != null) { List<UserScriptDefinitionBrickElement> currentElements = userBrick.getUserScriptDefinitionBrickElements(); for (int id = 0; id < currentElements.size(); id++) { if (currentElements.get(id).getText().equals(userVariableName) && currentElements.get(id).isVariable()) { Context brickContext = userBrick.getDefinitionBrick().view.getContext(); userBrick.getDefinitionBrick().removeVariablesInFormulas(currentElements.get(id).getText(), brickContext); currentElements.remove(id); } } } } } } public List<UserVariable> getOrCreateVariableListForSprite(Sprite sprite) { List<UserVariable> variables = spriteVariables.get(sprite); if (variables == null) { variables = new ArrayList<>(); spriteVariables.put(sprite, variables); removeSpriteVariableWithSameSpriteName(sprite); } return variables; } private void removeSpriteVariableWithSameSpriteName(Sprite spriteToKeep) { if (spriteVariables == null || spriteToKeep == null) { return; } Iterator iterator = spriteVariables.keySet().iterator(); while (iterator.hasNext()) { Sprite sprite = (Sprite) iterator.next(); if (sprite == null || !(sprite == spriteToKeep) && spriteVariables.get(sprite).size() == 0 && sprite.getName().equals(spriteToKeep.getName())) { iterator.remove(); } } } public void removeVariableListForSprite(Sprite sprite) { spriteVariables.remove(sprite); spriteListOfLists.remove(sprite); for (UserBrick userBrick : sprite.getUserBrickList()) { userBrickVariables.remove(userBrick); } } public List<UserVariable> getVariableListForSprite(Sprite sprite) { List<UserVariable> variables = spriteVariables.get(sprite); if (variables == null) { variables = new ArrayList<>(); } return variables; } public void cleanVariableListForSprite(Sprite sprite) { List<UserVariable> variables = spriteVariables.get(sprite); if (variables != null) { variables.clear(); } spriteVariables.remove(sprite); } public UserVariable getUserVariable(String name, UserBrick userBrick, Sprite currentSprite) { List<UserVariable> contextList = getUserVariableContext(name, userBrick, currentSprite); return findUserVariable(name, contextList); } /** * This function finds the user variable with userVariableName in the current context. * * The current context consists of all global variables, the sprite variables for the current sprite, * and the user brick variables for the current user brick. */ public List<UserVariable> getUserVariableContext(String name, UserBrick userBrick, Sprite currentSprite) { UserVariable variableToReturn; List<UserVariable> spriteVariables = getOrCreateVariableListForSprite(currentSprite); variableToReturn = findUserVariable(name, spriteVariables); if (variableToReturn != null) { return spriteVariables; } if (userBrick != null) { List<UserVariable> userBrickVariables = getOrCreateVariableListForUserBrick(userBrick); variableToReturn = findUserVariable(name, userBrickVariables); if (variableToReturn != null) { return userBrickVariables; } } variableToReturn = findUserVariable(name, getProjectVariables()); if (variableToReturn != null) { return getProjectVariables(); } return null; } public UserVariable findUserVariable(String name, List<UserVariable> variables) { if (variables == null) { return null; } for (UserVariable variable : variables) { if (variable.getName().equals(name)) { return variable; } } return null; } public void resetAllDataObjects() { resetAllUserLists(); resetAllUserVariables(); } private void resetAllUserVariables() { resetUserVariables(getProjectVariables()); for (Sprite currentSprite : spriteVariables.keySet()) { resetUserVariables(spriteVariables.get(currentSprite)); } } private void resetUserVariables(List<UserVariable> userVariableList) { for (UserVariable userVariable : userVariableList) { userVariable.setValue(0.0); } } public UserList getUserList(String userListName, Sprite sprite) { UserList userList; userList = findUserList(userListName, getOrCreateUserListListForSprite(sprite)); if (userList == null) { userList = findUserList(userListName, getProjectLists()); } return userList; } public UserList addSpriteUserList(String userListName) { Sprite currentSprite = ProjectManager.getInstance().getCurrentSprite(); return addSpriteUserListToSprite(currentSprite, userListName); } public UserList addSpriteUserListToSprite(Sprite sprite, String userListName) { UserList userListToAdd = new UserList(userListName); List<UserList> listOfUserLists = getOrCreateUserListListForSprite(sprite); listOfUserLists.add(userListToAdd); return userListToAdd; } public UserList addProjectUserList(String userListName) { UserList userListToAdd = new UserList(userListName); getProjectLists().add(userListToAdd); return userListToAdd; } public UserList renameProjectUserList(String newName, String oldName) { UserList userListToRename = findUserList(oldName, getProjectLists()); userListToRename.setName(newName); return userListToRename; } public void deleteUserListByName(String userListName) { Sprite currentSprite = ProjectManager.getInstance().getCurrentSprite(); UserList listToDelete; List<UserList> spriteVariables = getOrCreateUserListListForSprite(currentSprite); listToDelete = findUserList(userListName, spriteVariables); if (listToDelete != null) { spriteVariables.remove(listToDelete); } listToDelete = findUserList(userListName, getProjectLists()); if (listToDelete != null) { getProjectLists().remove(listToDelete); } } public List<UserList> getOrCreateUserListListForSprite(Sprite sprite) { List<UserList> userLists = spriteListOfLists.get(sprite); if (userLists == null) { userLists = new ArrayList<>(); spriteListOfLists.put(sprite, userLists); } return userLists; } public List<UserList> getUserListListForSprite(Sprite sprite) { List<UserList> userLists = spriteListOfLists.get(sprite); if (userLists == null) { userLists = new ArrayList<>(); } return userLists; } public void cleanUserListForSprite(Sprite sprite) { List<UserList> listOfUserLists = spriteListOfLists.get(sprite); if (listOfUserLists != null) { listOfUserLists.clear(); } spriteListOfLists.remove(sprite); } public UserList findUserList(String name, List<UserList> userLists) { if (userLists == null) { return null; } for (UserList userList : userLists) { if (userList.getName().equals(name)) { return userList; } } return null; } private void resetAllUserLists() { resetUserLists(getProjectLists()); for (Sprite currentSprite : spriteListOfLists.keySet()) { resetUserLists(spriteListOfLists.get(currentSprite)); } } private void resetUserLists(List<UserList> userVariableList) { for (UserList userList : userVariableList) { userList.getList().clear(); } } public UserList getUserList() { if (getProjectLists().size() > 0) { return getProjectLists().get(0); } for (Sprite currentSprite : spriteListOfLists.keySet()) { if (spriteListOfLists.get(currentSprite).size() > 0) { return spriteListOfLists.get(currentSprite).get(0); } } return null; } public boolean existSpriteVariable(UserVariable variable, Sprite sprite) { List<UserVariable> list = spriteVariables.get(sprite); if (list == null) { return false; } return list.contains(variable); } public boolean existSpriteVariableByName(String variableName, Sprite sprite) { if (sprite == null) { return false; } List<UserVariable> list = spriteVariables.get(sprite); if (list == null) { return false; } for (UserVariable variable : list) { if (variable.getName().equals(variableName)) { return true; } } return false; } public boolean existSpriteListByName(String listName, Sprite sprite) { if (sprite == null) { return false; } List<UserList> lists = spriteListOfLists.get(sprite); if (lists == null) { return false; } for (UserList list : lists) { if (list.getName().equals(listName)) { return true; } } return false; } public boolean existListInAnySprite(String listName, List<Sprite> sprites) { for (Sprite sprite : sprites) { if (existSpriteListByName(listName, sprite)) { return true; } } return false; } public boolean existVariableInAnySprite(String variableName, List<Sprite> sprites) { for (Sprite sprite : sprites) { if (existSpriteVariableByName(variableName, sprite)) { return true; } } return false; } public boolean existProjectVariable(UserVariable variable) { return getProjectVariables().contains(variable); } public boolean existSpriteList(UserList userList, Sprite sprite) { List<UserList> list = spriteListOfLists.get(sprite); if (list == null) { return false; } return list.contains(userList); } public boolean existProjectList(UserList list) { return getProjectLists().contains(list); } public boolean existProjectVariableWithName(String name) { for (UserVariable variable : getProjectVariables()) { if (name.equals(variable.getName())) { return true; } } return false; } public boolean existProjectListWithName(String name) { for (UserList list : getProjectLists()) { if (name.equals(list.getName())) { return true; } } return false; } public boolean existUserVariableWithName(String name) { for (List<UserVariable> variables : userBrickVariables.values()) { for (UserVariable variable : variables) { if (variable.getName().equals(name)) { return true; } } } return false; } public Integer getTypeOfUserVariable(String userVariableName, Sprite sprite) { UserVariable userVariable; userVariable = findUserVariable(userVariableName, getOrCreateVariableListForSprite(sprite)); if (userVariable != null) { return USER_VARIABLE_SPRITE; } userVariable = findUserVariable(userVariableName, getProjectVariables()); if (userVariable != null) { return USER_VARIABLE_PROJECT; } UserBrick userBrick = getCurrentUserBrick(); if (userBrick != null) { userVariable = findUserVariable(userVariableName, getOrCreateVariableListForUserBrick(userBrick)); if (userVariable != null) { return USER_VARIABLE_USERBRICK; } } return USER_VARIABLE_PROJECT; } public Integer getTypeOfUserList(String userListName, Sprite sprite) { UserList userList; userList = findUserList(userListName, getOrCreateUserListListForSprite(sprite)); if (userList != null) { return USER_LIST_SPRITE; } userList = findUserList(userListName, getProjectLists()); if (userList != null) { return USER_LIST_PROJECT; } return -1; } public List<UserList> getSpriteListOfLists(Sprite sprite) { return spriteListOfLists.get(sprite); } public UserBrick getCurrentUserBrick() { return ProjectManager.getInstance().getCurrentUserBrick(); } public void deleteUserVariableFromUserBrick(UserBrick userBrick, String userVariableName) { List<UserVariable> context = userBrickVariables.get(userBrick); UserVariable variableToDelete = findUserVariable(userVariableName, context); if (variableToDelete != null) { context.remove(variableToDelete); } } public List<UserVariable> getOrCreateVariableListForUserBrick(UserBrick userBrick) { if (userBrick == null) { return new ArrayList<>(); } List<UserVariable> variables = userBrickVariables.get(userBrick); if (variables == null) { variables = new ArrayList<>(); userBrickVariables.put(userBrick, variables); } return variables; } public String getUniqueVariableName(Context context) { Sprite currentSprite = ProjectManager.getInstance().getCurrentSprite(); String name = context.getResources().getString(R.string.new_user_brick_variable).trim(); int variableCounter = 0; String originalName = name; name += " " + variableCounter; while (getUserVariable(name, currentSprite) != null) { variableCounter++; name = originalName + " " + variableCounter; } name = originalName + " " + variableCounter; return name; } public void setUserBrickVariables(UserBrick key, List<UserVariable> userVariables) { userBrickVariables.put(key, userVariables); } }