diff --git a/.idea/misc.xml b/.idea/misc.xml
index 4e024a8..26dc4f5 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -25,5 +25,5 @@
-
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
index bee9e70..62306f1 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -2,7 +2,7 @@
-
+
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 8306744..94a25f7 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -1,7 +1,6 @@
-
\ No newline at end of file
diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAdapter.java
index 24a5009..01b252a 100644
--- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAdapter.java
+++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAdapter.java
@@ -38,6 +38,8 @@ class ModDetailAdapter extends FragmentStatePagerAdapter {
return ModDetailEventFragment.newInstance(mItemPos);
case ModulePart.GRADEBOOK:
return ModDetailGradebookFragment.newInstance(mItemPos);
+ case ModulePart.RESOURCES:
+ return ModDetailResourceFragment.newInstance(mItemPos);
default:
return null;
}
@@ -57,6 +59,8 @@ class ModDetailAdapter extends FragmentStatePagerAdapter {
return this.mContext.getResources().getString(R.string.events);
case ModulePart.GRADEBOOK:
return this.mContext.getResources().getString(R.string.gradebook);
+ case ModulePart.RESOURCES:
+ return this.mContext.getResources().getString(R.string.resourcen);
default:
return "";
}
diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceAdapter.java
new file mode 100644
index 0000000..8b5e570
--- /dev/null
+++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceAdapter.java
@@ -0,0 +1,34 @@
+package de.sebse.fuplanner.fragments.moddetails;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import de.sebse.fuplanner.services.KVV.types.Modules;
+import de.sebse.fuplanner.services.KVV.types.Resource;
+import de.sebse.fuplanner.tools.ui.treeview.TreeNode;
+import de.sebse.fuplanner.tools.ui.treeview.TreeViewAdapter;
+import de.sebse.fuplanner.tools.ui.treeview.TreeViewBinder;
+
+class ModDetailResourceAdapter extends TreeViewAdapter {
+ private Modules.Module mValue;
+ public ModDetailResourceAdapter(List extends TreeViewBinder> viewBinders) {
+ super(viewBinders);
+ mValue = null;
+ }
+
+ public void setModule(Modules.Module module) {
+ mValue = module;
+ this.setModule();
+ }
+
+ public void setModule() {
+ if (mValue == null || mValue.resources == null) {
+ return;
+ }
+ List nodes = new ArrayList<>();
+ for (Resource res: mValue.resources) {
+ nodes.add(res.getTreeNode());
+ }
+ refresh(nodes);
+ }
+}
diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceFragment.java
new file mode 100644
index 0000000..efdebb5
--- /dev/null
+++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceFragment.java
@@ -0,0 +1,132 @@
+package de.sebse.fuplanner.fragments.moddetails;
+
+
+import android.content.Context;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v4.app.Fragment;
+import android.support.v4.widget.SwipeRefreshLayout;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+
+import java.util.Arrays;
+
+import de.sebse.fuplanner.MainActivity;
+import de.sebse.fuplanner.R;
+import de.sebse.fuplanner.services.KVV.KVV;
+import de.sebse.fuplanner.services.KVV.types.Modules;
+import de.sebse.fuplanner.tools.logging.Logger;
+import de.sebse.fuplanner.tools.ui.treeview.DirectoryNodeBinder;
+import de.sebse.fuplanner.tools.ui.treeview.FileNodeBinder;
+import de.sebse.fuplanner.tools.ui.treeview.TreeNode;
+import de.sebse.fuplanner.tools.ui.treeview.TreeViewAdapter;
+
+/**
+ * A simple {@link Fragment} subclass.
+ * Use the {@link ModDetailResourceFragment#newInstance} factory method to
+ * create an instance of this fragment.
+ */
+public class ModDetailResourceFragment extends Fragment {
+ private static final String ARG_POSITION = "itemPosition";
+
+ private String mItemPos;
+ private final Logger log = new Logger(this);
+ private ModDetailResourceAdapter adapter;
+ private SwipeRefreshLayout swipeLayout;
+
+
+ public ModDetailResourceFragment() {
+ // Required empty public constructor
+ }
+
+ /**
+ * Use this factory method to create a new instance of
+ * this fragment using the provided parameters.
+ *
+ * @param itemPosition Item position in module list.
+ * @return A new instance of fragment ModDetailAnnounceFragment.
+ */
+ public static ModDetailResourceFragment newInstance(String itemPosition) {
+ ModDetailResourceFragment fragment = new ModDetailResourceFragment();
+ Bundle args = new Bundle();
+ args.putString(ARG_POSITION, itemPosition);
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if (getArguments() != null) {
+ mItemPos = getArguments().getString(ARG_POSITION);
+ }
+ }
+
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ // Inflate the layout for this fragment
+ View view = inflater.inflate(R.layout.fragment_recycler_view, container, false);
+ // Set the adapter
+ Context context = view.getContext();
+ RecyclerView recyclerView = view.findViewById(R.id.list);
+ recyclerView.setLayoutManager(new LinearLayoutManager(context));
+
+ adapter = new ModDetailResourceAdapter(Arrays.asList(new FileNodeBinder(), new DirectoryNodeBinder()));
+ adapter.setOnTreeNodeListener(new TreeViewAdapter.OnTreeNodeListener() {
+ @Override
+ public boolean onClick(TreeNode node, RecyclerView.ViewHolder holder) {
+ if (!node.isLeaf()) {
+ //Update and toggle the node.
+ onToggle(!node.isExpand(), holder);
+// if (!node.isExpand())
+// adapter.collapseBrotherNode(node);
+ }
+ return false;
+ }
+
+ @Override
+ public void onToggle(boolean isExpand, RecyclerView.ViewHolder holder) {
+ DirectoryNodeBinder.ViewHolder dirViewHolder = (DirectoryNodeBinder.ViewHolder) holder;
+ final ImageView ivArrow = dirViewHolder.getIvArrow();
+ int rotateDegree = isExpand ? 90 : -90;
+ ivArrow.animate().rotationBy(rotateDegree)
+ .start();
+ }
+ });
+
+ recyclerView.setAdapter(adapter);
+
+ // Getting SwipeContainerLayout
+ swipeLayout = view.findViewById(R.id.swipe_container);
+ // Adding Listener
+ swipeLayout.setOnRefreshListener(() -> refresh(true));
+ refresh(false);
+
+ return view;
+ }
+
+ private void refresh(boolean forceRefresh) {
+ if (getActivity() != null) {
+ KVV kvv = ((MainActivity) getActivity()).getKVV();
+ kvv.getModule(mItemPos, (Modules.Module module) -> {
+ adapter.setModule(module);
+ kvv.getModuleResources(module, success1 -> {
+ adapter.setModule();
+ swipeLayout.setRefreshing(false);
+ }, error -> {
+ swipeLayout.setRefreshing(false);
+ log.e(error);
+ }, forceRefresh);
+ }, error -> {
+ swipeLayout.setRefreshing(false);
+ log.e(error);
+ }, forceRefresh);
+ }
+ }
+
+}
diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModulePart.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModulePart.java
index 06c0fb4..17dff82 100644
--- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModulePart.java
+++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModulePart.java
@@ -7,7 +7,8 @@ class ModulePart {
static final int ASSIGNMENT = 3;
static final int EVENT = 4;
static final int GRADEBOOK = 5;
- private static final int[] pages = new int[]{OVERVIEW, ANNOUNCEMENT, ASSIGNMENT, EVENT, GRADEBOOK};
+ static final int RESOURCES = 6;
+ private static final int[] pages = new int[]{OVERVIEW, ANNOUNCEMENT, ASSIGNMENT, EVENT, GRADEBOOK, RESOURCES};
static int getPageCount() {
return pages.length;
diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Resource.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Resource.java
index 5365f96..fc5c93e 100644
--- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Resource.java
+++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Resource.java
@@ -3,6 +3,9 @@ package de.sebse.fuplanner.services.KVV.types;
import java.io.Serializable;
import java.util.ArrayList;
+import de.sebse.fuplanner.tools.ui.treeview.Dir;
+import de.sebse.fuplanner.tools.ui.treeview.TreeNode;
+
public abstract class Resource implements Serializable {
@@ -47,9 +50,9 @@ public abstract class Resource implements Serializable {
return visible;
}
+ public abstract TreeNode getTreeNode();
+
public static class File extends Resource {
-
-
private final String type;
public File(String author, String title, long modifiedDate, String url, boolean visible, String container, String type) {
@@ -67,6 +70,11 @@ public abstract class Resource implements Serializable {
", type='" + type + '\'' +
'}';
}
+
+ @Override
+ public TreeNode getTreeNode() {
+ return new TreeNode<>(new de.sebse.fuplanner.tools.ui.treeview.File(title));
+ }
}
public static class Folder extends Resource{
@@ -99,6 +107,15 @@ public abstract class Resource implements Serializable {
", childs='" + childs + '\'' +
'}';
}
+
+ @Override
+ public TreeNode getTreeNode() {
+ TreeNode dir = new TreeNode<>(new Dir(title));
+ for (Resource res: childs) {
+ dir.addChild(res.getTreeNode());
+ }
+ return dir;
+ }
}
}
diff --git a/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/Dir.java b/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/Dir.java
new file mode 100644
index 0000000..c36bd6e
--- /dev/null
+++ b/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/Dir.java
@@ -0,0 +1,21 @@
+package de.sebse.fuplanner.tools.ui.treeview;
+
+
+import de.sebse.fuplanner.R;
+
+/**
+ * Created by tlh on 2016/10/1 :)
+ */
+
+public class Dir implements LayoutItemType {
+ public String dirName;
+
+ public Dir(String dirName) {
+ this.dirName = dirName;
+ }
+
+ @Override
+ public int getLayoutId() {
+ return R.layout.item_dir;
+ }
+}
diff --git a/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/DirectoryNodeBinder.java b/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/DirectoryNodeBinder.java
new file mode 100644
index 0000000..40e2f23
--- /dev/null
+++ b/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/DirectoryNodeBinder.java
@@ -0,0 +1,55 @@
+package de.sebse.fuplanner.tools.ui.treeview;
+
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import de.sebse.fuplanner.R;
+
+/**
+ * Created by tlh on 2016/10/1 :)
+ */
+
+public class DirectoryNodeBinder extends TreeViewBinder {
+ @Override
+ public ViewHolder provideViewHolder(View itemView) {
+ return new ViewHolder(itemView);
+ }
+
+ @Override
+ public void bindView(ViewHolder holder, int position, TreeNode node) {
+ holder.ivArrow.setRotation(0);
+ holder.ivArrow.setImageResource(R.drawable.ic_keyboard_arrow_right_black_18dp);
+ int rotateDegree = node.isExpand() ? 90 : 0;
+ holder.ivArrow.setRotation(rotateDegree);
+ Dir dirNode = (Dir) node.getContent();
+ holder.tvName.setText(dirNode.dirName);
+ if (node.isLeaf())
+ holder.ivArrow.setVisibility(View.INVISIBLE);
+ else holder.ivArrow.setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ public int getLayoutId() {
+ return R.layout.item_dir;
+ }
+
+ public static class ViewHolder extends TreeViewBinder.ViewHolder {
+ private ImageView ivArrow;
+ private TextView tvName;
+
+ public ViewHolder(View rootView) {
+ super(rootView);
+ this.ivArrow = (ImageView) rootView.findViewById(R.id.iv_arrow);
+ this.tvName = (TextView) rootView.findViewById(R.id.tv_name);
+ }
+
+ public ImageView getIvArrow() {
+ return ivArrow;
+ }
+
+ public TextView getTvName() {
+ return tvName;
+ }
+ }
+}
diff --git a/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/File.java b/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/File.java
new file mode 100644
index 0000000..1f07396
--- /dev/null
+++ b/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/File.java
@@ -0,0 +1,21 @@
+package de.sebse.fuplanner.tools.ui.treeview;
+
+
+import de.sebse.fuplanner.R;
+
+/**
+ * Created by tlh on 2016/10/1 :)
+ */
+
+public class File implements LayoutItemType {
+ public String fileName;
+
+ public File(String fileName) {
+ this.fileName = fileName;
+ }
+
+ @Override
+ public int getLayoutId() {
+ return R.layout.item_file;
+ }
+}
diff --git a/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/FileNodeBinder.java b/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/FileNodeBinder.java
new file mode 100644
index 0000000..8ca2858
--- /dev/null
+++ b/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/FileNodeBinder.java
@@ -0,0 +1,38 @@
+package de.sebse.fuplanner.tools.ui.treeview;
+
+import android.view.View;
+import android.widget.TextView;
+
+import de.sebse.fuplanner.R;
+
+/**
+ * Created by tlh on 2016/10/1 :)
+ */
+
+public class FileNodeBinder extends TreeViewBinder {
+ @Override
+ public ViewHolder provideViewHolder(View itemView) {
+ return new ViewHolder(itemView);
+ }
+
+ @Override
+ public void bindView(ViewHolder holder, int position, TreeNode node) {
+ File fileNode = (File) node.getContent();
+ holder.tvName.setText(fileNode.fileName);
+ }
+
+ @Override
+ public int getLayoutId() {
+ return R.layout.item_file;
+ }
+
+ public class ViewHolder extends TreeViewBinder.ViewHolder {
+ public TextView tvName;
+
+ public ViewHolder(View rootView) {
+ super(rootView);
+ this.tvName = (TextView) rootView.findViewById(R.id.tv_name);
+ }
+
+ }
+}
diff --git a/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/LayoutItemType.java b/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/LayoutItemType.java
new file mode 100644
index 0000000..c4ea5ef
--- /dev/null
+++ b/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/LayoutItemType.java
@@ -0,0 +1,9 @@
+package de.sebse.fuplanner.tools.ui.treeview;
+
+/**
+ * Created by tlh on 2016/10/1 :)
+ */
+
+public interface LayoutItemType {
+ int getLayoutId();
+}
diff --git a/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/TreeNode.java b/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/TreeNode.java
new file mode 100644
index 0000000..38f6ed0
--- /dev/null
+++ b/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/TreeNode.java
@@ -0,0 +1,149 @@
+package de.sebse.fuplanner.tools.ui.treeview;
+
+import android.support.annotation.NonNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by tlh on 2016/10/1 :)
+ */
+
+public class TreeNode implements Cloneable {
+ private T content;
+ private TreeNode parent;
+ private List childList;
+ private boolean isExpand;
+ private boolean isLocked;
+ //the tree high
+ private int height = UNDEFINE;
+
+ private static final int UNDEFINE = -1;
+
+ public TreeNode(@NonNull T content) {
+ this.content = content;
+ this.childList = new ArrayList<>();
+ }
+
+ public int getHeight() {
+ if (isRoot())
+ height = 0;
+ else if (height == UNDEFINE)
+ height = parent.getHeight() + 1;
+ return height;
+ }
+
+ public boolean isRoot() {
+ return parent == null;
+ }
+
+ public boolean isLeaf() {
+ return childList == null || childList.isEmpty();
+ }
+
+ public void setContent(T content) {
+ this.content = content;
+ }
+
+ public T getContent() {
+ return content;
+ }
+
+ public List getChildList() {
+ return childList;
+ }
+
+ public void setChildList(List childList) {
+ this.childList.clear();
+ for (TreeNode treeNode : childList) {
+ addChild(treeNode);
+ }
+ }
+
+ public TreeNode addChild(TreeNode node) {
+ if (childList == null)
+ childList = new ArrayList<>();
+ childList.add(node);
+ node.parent = this;
+ return this;
+ }
+
+ public boolean toggle() {
+ isExpand = !isExpand;
+ return isExpand;
+ }
+
+ public void collapse() {
+ if (isExpand) {
+ isExpand = false;
+ }
+ }
+
+ public void collapseAll() {
+ if (childList == null || childList.isEmpty()) {
+ return;
+ }
+ for (TreeNode child : this.childList) {
+ child.collapseAll();
+ }
+ }
+
+ public void expand() {
+ if (!isExpand) {
+ isExpand = true;
+ }
+ }
+
+ public void expandAll() {
+ expand();
+ if (childList == null || childList.isEmpty()) {
+ return;
+ }
+ for (TreeNode child : this.childList) {
+ child.expandAll();
+ }
+ }
+
+ public boolean isExpand() {
+ return isExpand;
+ }
+
+ public void setParent(TreeNode parent) {
+ this.parent = parent;
+ }
+
+ public TreeNode getParent() {
+ return parent;
+ }
+
+ public TreeNode lock() {
+ isLocked = true;
+ return this;
+ }
+
+ public TreeNode unlock() {
+ isLocked = false;
+ return this;
+ }
+
+ public boolean isLocked() {
+ return isLocked;
+ }
+
+ @Override
+ public String toString() {
+ return "TreeNode{" +
+ "content=" + this.content +
+ ", parent=" + (parent == null ? "null" : parent.getContent().toString()) +
+ ", childList=" + (childList == null ? "null" : childList.toString()) +
+ ", isExpand=" + isExpand +
+ '}';
+ }
+
+ @Override
+ protected TreeNode clone() throws CloneNotSupportedException {
+ TreeNode clone = new TreeNode<>(this.content);
+ clone.isExpand = this.isExpand;
+ return clone;
+ }
+}
diff --git a/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/TreeViewAdapter.java b/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/TreeViewAdapter.java
new file mode 100644
index 0000000..0f3c130
--- /dev/null
+++ b/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/TreeViewAdapter.java
@@ -0,0 +1,320 @@
+package de.sebse.fuplanner.tools.ui.treeview;
+
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v7.util.DiffUtil;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Created by tlh on 2016/10/1 :)
+ */
+public class TreeViewAdapter extends RecyclerView.Adapter {
+ private static final String KEY_IS_EXPAND = "IS_EXPAND";
+ private final List extends TreeViewBinder> viewBinders;
+ private List displayNodes;
+ private int padding = 30;
+ private OnTreeNodeListener onTreeNodeListener;
+ private boolean toCollapseChild;
+
+ public TreeViewAdapter(List extends TreeViewBinder> viewBinders) {
+ this(null, viewBinders);
+ }
+
+ public TreeViewAdapter(List nodes, List extends TreeViewBinder> viewBinders) {
+ displayNodes = new ArrayList<>();
+ if (nodes != null)
+ findDisplayNodes(nodes);
+ this.viewBinders = viewBinders;
+ }
+
+ /**
+ * 从nodes的结点中寻找展开了的非叶结点,添加到displayNodes中。
+ *
+ * @param nodes 基准点
+ */
+ private void findDisplayNodes(List nodes) {
+ for (TreeNode node : nodes) {
+ displayNodes.add(node);
+ if (!node.isLeaf() && node.isExpand())
+ findDisplayNodes(node.getChildList());
+ }
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ return displayNodes.get(position).getContent().getLayoutId();
+ }
+
+ @Override
+ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ View v = LayoutInflater.from(parent.getContext())
+ .inflate(viewType, parent, false);
+ if (viewBinders.size() == 1)
+ return viewBinders.get(0).provideViewHolder(v);
+ for (TreeViewBinder viewBinder : viewBinders) {
+ if (viewBinder.getLayoutId() == viewType)
+ return viewBinder.provideViewHolder(v);
+ }
+ return viewBinders.get(0).provideViewHolder(v);
+ }
+
+ @Override
+ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position, List