Java tutorial
/** * Copyright (C) 2015 MKLab.org (Koga Laboratory) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.mklab.mikity.android; import java.util.List; import org.mklab.mikity.android.R; import org.mklab.mikity.android.editor.ModelEditor; import org.mklab.mikity.android.editor.ModelEditorFactory; import org.mklab.mikity.android.model.GraphTree; import org.mklab.mikity.android.model.TreeItem; import org.mklab.mikity.model.xml.simplexml.SceneModel; import org.mklab.mikity.model.xml.simplexml.model.BoxModel; import org.mklab.mikity.model.xml.simplexml.model.CapsuleModel; import org.mklab.mikity.model.xml.simplexml.model.ConeModel; import org.mklab.mikity.model.xml.simplexml.model.CylinderModel; import org.mklab.mikity.model.xml.simplexml.model.GroupModel; import org.mklab.mikity.model.xml.simplexml.model.NullModel; import org.mklab.mikity.model.xml.simplexml.model.ObjectModel; import org.mklab.mikity.model.xml.simplexml.model.QuadrangleModel; import org.mklab.mikity.model.xml.simplexml.model.SphereModel; import org.mklab.mikity.model.xml.simplexml.model.TriangleModel; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.Button; import android.widget.ListView; /** * ???? * * @author koga * @version $Revision$, 2016/01/08 */ public class SceneGraphTreeFragment extends Fragment { private ListView treeView; /** */ OpenglesModeler modeler; /** */ GraphTree tree; /** */ SceneModel model; /** */ GroupModel rootGroup; /** ? */ TreeItem rootItem = null; /** ????? */ TreeItem selectedTreeItem = null; /** ???? */ Object selectedObject = null; /** ???? */ GroupModel selectedGroup = null; /** ?? */ ObjectModel bufferedObject = null; /** ?? */ GroupModel bufferedGroup = null; ModelEditor modelEditorFragment = null; private static final int CONTEXT_MENU_CUT = 1; private static final int CONTEXT_MENU_COPY = 2; private static final int CONTEXT_MENU_PASTE = 3; private static final int CONTEXT_MENU_DELETE = 4; private static final int CONTEXT_MENU_EDIT = 5; //private static final int CONTEXT_MENU_TRANSFORM = 6; private int positionCount = 0; /** * {@inheritDoc} */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRetainInstance(true); setHasOptionsMenu(true); } /** * {@inheritDoc} */ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); final View view = inflater.inflate(R.layout.fragment_scene_graph_tree, container, false); this.treeView = (ListView) view.findViewById(R.id.scene_graph_tree_view); createTree(); createPopupMenu(); final Button backButton = (Button) view.findViewById(R.id.backButton); backButton.setOnClickListener(new OnClickListener() { /** * {@inheritDoc} */ public void onClick(View v) { SceneGraphTreeFragment.this.selectedTreeItem = SceneGraphTreeFragment.this.rootItem; updatetSelectedObject(); final FragmentManager manager = getActivity().getSupportFragmentManager(); manager.popBackStack(); } }); return view; } /** * {@inheritDoc} */ @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); menu.clear(); inflater.inflate(R.menu.menu_model, menu); } /** * {@inheritDoc} */ @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == R.id.menu_add_group) { addGroup(); return true; } else if (item.getItemId() == R.id.menu_add_box) { addBox(); return true; } else if (item.getItemId() == R.id.menu_add_cylinder) { addCylinder(); return true; } else if (item.getItemId() == R.id.menu_add_sphere) { addSphere(); return true; } else if (item.getItemId() == R.id.menu_add_cone) { addCone(); return true; } else if (item.getItemId() == R.id.menu_add_capsule) { addCapsule(); return true; } else if (item.getItemId() == R.id.menu_add_triangle) { addTriangle(); return true; } else if (item.getItemId() == R.id.menu_add_quadrangle) { addQuadrangle(); return true; } return super.onOptionsItemSelected(item); } /** * ????? */ private void createPopupMenu() { registerForContextMenu(this.treeView); } /** * {@inheritDoc} */ @Override public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, view, menuInfo); if (view.getId() == R.id.scene_graph_tree_view) { menu.add(0, CONTEXT_MENU_CUT, 0, R.string.cut); menu.add(0, CONTEXT_MENU_COPY, 0, R.string.copy); menu.add(0, CONTEXT_MENU_PASTE, 0, R.string.paste); menu.add(0, CONTEXT_MENU_DELETE, 0, R.string.delete); menu.add(0, CONTEXT_MENU_EDIT, 0, R.string.edit); //menu.add(0, CONTEXT_MENU_TRANSFORM, 0, R.string.transform); } } /** * {@inheritDoc} */ @Override public boolean onContextItemSelected(MenuItem item) { final AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo(); int position = info.position; int itemId = item.getItemId(); if (itemId == CONTEXT_MENU_CUT) { cutSelectedItem(); return true; } if (itemId == CONTEXT_MENU_COPY) { copySelectedItem(); return true; } if (itemId == CONTEXT_MENU_PASTE) { pasteBufferedObjectToSelectedItem(); return true; } if (itemId == CONTEXT_MENU_DELETE) { deleteSelectedItem(); return true; } if (itemId == CONTEXT_MENU_EDIT) { editSelectedItem(); return true; } // if (itemId == CONTEXT_MENU_TRANSFORM) { // return true; // } return super.onContextItemSelected(item); } /** * ??? * * @param model */ public void setModel(SceneModel model) { this.model = model; this.rootGroup = new GroupModel("scene"); //$NON-NLS-1$ this.rootGroup.setGroups(model.getGroups()); this.selectedGroup = this.rootGroup; this.selectedObject = this.rootGroup; } /** * ???? */ void createTree() { this.tree = new GraphTree(getActivity()); this.treeView.setAdapter(this.tree); bindModelToTree(); setSelectedItem(this.rootItem, 0); this.tree.notifyDataSetChanged(); this.treeView.setOnItemClickListener(new OnItemClickListener() { /** * {@inheritDoc} */ public void onItemClick(AdapterView<?> parent, View view, int position, long id) { SceneGraphTreeFragment.this.selectedTreeItem = (TreeItem) parent.getItemAtPosition(position); if (SceneGraphTreeFragment.this.selectedTreeItem.isExpanded()) { SceneGraphTreeFragment.this.selectedTreeItem.collapse(); } else { if (SceneGraphTreeFragment.this.selectedTreeItem.hasItems()) { SceneGraphTreeFragment.this.selectedTreeItem.expand(); } } SceneGraphTreeFragment.this.tree.notifyDataSetChanged(); updatetSelectedObject(); } }); } /** * ???(????)?? */ public void bindModelToTree() { clearTree(); this.positionCount = 0; this.rootItem = new TreeItem(this.tree, this.rootGroup); this.rootItem.setText("scene"); //$NON-NLS-1$ this.positionCount++; addItemToTree(this.rootItem, this.model.getGroups()); } /** * ???????? * * @param selectedItem ????? * @param position ??? */ private void setSelectedItem(TreeItem selectedItem, int position) { this.selectedTreeItem = selectedItem; this.treeView.setItemChecked(position, true); } /** * ???Item??? */ private void clearTree() { if (this.tree.getCount() == 0) { return; } for (final TreeItem item : this.tree.getItems()) { removeItemsFromTree(item); item.dispose(); } } /** * ?Item??? * * @param items Item */ private void removeItemsFromTree(TreeItem items) { for (final TreeItem item : items.getItems()) { if (item.getItemsCount() != 0) { removeItemsFromTree(item); } item.dispose(); } } /** * ???? * * @param parent * @param groups */ private void addItemToTree(TreeItem parent, List<GroupModel> groups) { for (final GroupModel group : groups) { final TreeItem groupItem = new TreeItem(parent, group); groupItem.setText(group.toShortString()); if (group == this.selectedObject) { setSelectedItem(groupItem, this.positionCount); } this.positionCount++; final List<ObjectModel> objects = group.getObjects(); final boolean groupHasAnyObject = objects.size() > 0 && (objects.get(0) instanceof NullModel) == false; if (groupHasAnyObject) { final TreeItem objectItems = new TreeItem(groupItem, group); objectItems.setText("object"); //$NON-NLS-1$ this.positionCount++; for (final ObjectModel object : objects) { if (object instanceof NullModel) { continue; } final TreeItem child = new TreeItem(objectItems, object); child.setText(object.toShortString()); if (object == this.selectedObject) { objectItems.expand(); setSelectedItem(child, this.positionCount); } this.positionCount++; } } addItemToTree(groupItem, group.getGroups()); } if (parent != null) { parent.expand(); } } /** * ??????? */ void updatetSelectedObject() { this.selectedObject = this.selectedTreeItem.getData(); if (this.selectedObject instanceof GroupModel) { this.selectedGroup = (GroupModel) this.selectedObject; } else { this.selectedGroup = (GroupModel) this.selectedTreeItem.getParentItem().getData(); } makeObjectNontransparent(this.selectedObject); } /** * ??????????? * * @param object */ private void makeObjectNontransparent(Object object) { if (object == this.rootGroup) { for (final GroupModel group : this.model.getGroups()) { setAllTransparent(group, false); } return; } for (final GroupModel group : this.model.getGroups()) { setAllTransparent(group, true); } if (object instanceof ObjectModel) { ((ObjectModel) object).setTransparent(false); } else if (object instanceof GroupModel) { final GroupModel group = (GroupModel) object; setTransparent(group, false); } } /** * ??????????? * * @param group * @param transparent ????true */ public void setAllTransparent(final GroupModel group, boolean transparent) { setTransparent(group, transparent); for (GroupModel childGroup : group.getGroups()) { setAllTransparent(childGroup, transparent); } } /** * ????????? * * @param group * @param transparent ????true */ public void setTransparent(final GroupModel group, boolean transparent) { for (ObjectModel primitive : group.getObjects()) { if (primitive instanceof NullModel) { continue; } primitive.setTransparent(transparent); } } /** * ??? */ void addGroup() { final GroupModel group = new GroupModel(getActivity().getString(R.string.group)); if (this.selectedGroup == this.rootGroup) { this.model.addGroup(group); } else { this.selectedGroup.add(group); } this.selectedGroup = group; this.selectedObject = group; this.modeler.setIsChanged(true); updateTree(); } /** * ??? */ void addBox() { final ObjectModel object = BoxModel.createDefault(); this.selectedGroup.add(object); this.selectedObject = object; this.modeler.setIsChanged(true); updateTree(); } /** * ??? */ void addCylinder() { final ObjectModel object = CylinderModel.createDefault(); this.selectedGroup.add(object); this.selectedObject = object; this.modeler.setIsChanged(true); updateTree(); } /** * ???? */ void addSphere() { final ObjectModel object = SphereModel.createDefault(); this.selectedGroup.add(object); this.selectedObject = object; this.modeler.setIsChanged(true); updateTree(); } /** * ???? */ void addCone() { final ObjectModel object = ConeModel.createDefault(); this.selectedGroup.add(object); this.selectedObject = object; this.modeler.setIsChanged(true); updateTree(); } /** * ??? */ void addCapsule() { final ObjectModel object = CapsuleModel.createDefault(); this.selectedGroup.add(object); this.selectedObject = object; this.modeler.setIsChanged(true); updateTree(); } /** * ??? */ void addTriangle() { final ObjectModel object = TriangleModel.createDefault(); this.selectedGroup.add(object); this.selectedObject = object; this.modeler.setIsChanged(true); updateTree(); } /** * ??? */ void addQuadrangle() { final ObjectModel object = QuadrangleModel.createDefault(); this.selectedGroup.add(object); this.selectedObject = object; this.modeler.setIsChanged(true); updateTree(); } /** * ???? */ void cutSelectedItem() { if (this.selectedObject instanceof GroupModel) { this.bufferedGroup = this.selectedGroup; this.bufferedObject = null; } else { this.bufferedGroup = null; this.bufferedObject = (ObjectModel) this.selectedObject; } deleteSelectedItem(); } /** * ???? */ void copySelectedItem() { if (this.selectedObject instanceof GroupModel) { this.bufferedGroup = this.selectedGroup; this.bufferedObject = null; } else { this.bufferedGroup = null; this.bufferedObject = (ObjectModel) this.selectedObject; } } /** * ???? */ void pasteBufferedObjectToSelectedItem() { if ((this.selectedObject instanceof GroupModel) == false) { return; } if (this.bufferedGroup != null) { final GroupModel group = this.bufferedGroup.clone(); if (this.selectedGroup == this.rootGroup) { this.model.addGroup(group); } else { this.selectedGroup.add(group); } this.selectedGroup = group; this.selectedObject = group; } if (this.bufferedObject != null) { final ObjectModel object = this.bufferedObject.createClone(); this.selectedGroup.add(object); this.selectedObject = object; } this.modeler.setIsChanged(true); updateTree(); } /** * ???item??? */ void deleteSelectedItem() { if (this.selectedTreeItem.getText().equals("scene")) { //$NON-NLS-1$ return; } final TreeItem parentItem = this.selectedTreeItem.getParentItem(); if (parentItem.getText().equals("scene")) { //$NON-NLS-1$ this.model.removeGroup((GroupModel) this.selectedObject); } else { final GroupModel group = (GroupModel) parentItem.getData(); removeObjectFromGroup(group, this.selectedObject); } this.selectedTreeItem.dispose(); parentItem.removeItem(this.selectedTreeItem); this.selectedGroup = (GroupModel) parentItem.getData(); this.selectedObject = parentItem.getData(); updateTree(); this.modeler.setIsChanged(true); this.modeler.updateRenderer(); //this.modeler.updatePropertyEditor(); } /** * ???item??? */ void editSelectedItem() { if (this.selectedTreeItem.getText().equals("scene")) { //$NON-NLS-1$ return; } final FragmentManager manager = getActivity().getSupportFragmentManager(); final FragmentTransaction transaction = manager.beginTransaction(); transaction.addToBackStack(null); if (this.modelEditorFragment != null) { transaction.remove((Fragment) this.modelEditorFragment); this.modelEditorFragment = null; } this.modelEditorFragment = ModelEditorFactory.create(this.selectedObject, this.selectedGroup, this, this.modeler); transaction.add(R.id.fragment_navigation_drawer, (Fragment) this.modelEditorFragment); transaction.commit(); updateTree(); this.modeler.updateRenderer(); //this.modeler.updatePropertyEditor(); } /** * ???? * * @param group * @param object */ void removeObjectFromGroup(GroupModel group, Object object) { if (object instanceof ObjectModel) { group.remove((ObjectModel) object); } if (object instanceof GroupModel) { group.remove((GroupModel) object); } } /** * ???? */ public void updateTree() { bindModelToTree(); this.tree.notifyDataSetChanged(); this.modeler.updateRenderer(); //this.modeler.updatePropertyEditor(); } /** * ??????? * * @param selectedGroup ???? */ public void setSelectedGroup(GroupModel selectedGroup) { this.selectedGroup = selectedGroup; } /** * ??????? * * @return ???? */ public GroupModel getSelectedGroup() { return this.selectedGroup; } /** * ??????? * * @param selectedObject ???? */ public void setSelectedObject(Object selectedObject) { this.selectedObject = selectedObject; } /** * ??????? * * @return ???? */ public Object getSelectedObject() { return this.selectedObject; } /** * ??? * * @return */ public SceneModel getModel() { return this.model; } /** * ??? * * @param modeler */ public void setModeler(OpenglesModeler modeler) { this.modeler = modeler; } }