1 | package com.gs3.testGXT.client.tree;
|
---|
2 |
|
---|
3 | import java.util.LinkedList;
|
---|
4 | import java.util.List;
|
---|
5 |
|
---|
6 | import com.gs3.testGXT.client.Keys.FileSystemKey;
|
---|
7 | import com.sencha.gxt.data.shared.TreeStore;
|
---|
8 | import com.sencha.gxt.data.shared.TreeStore.TreeNode;
|
---|
9 | import com.sencha.gxt.dnd.core.client.TreeDropTarget;
|
---|
10 | import com.sencha.gxt.widget.core.client.box.AlertMessageBox;
|
---|
11 | import com.sencha.gxt.widget.core.client.button.TextButton;
|
---|
12 | import com.sencha.gxt.widget.core.client.event.SelectEvent;
|
---|
13 | import com.sencha.gxt.widget.core.client.event.SelectEvent.SelectHandler;
|
---|
14 | import com.sencha.gxt.widget.core.client.tree.Tree;
|
---|
15 |
|
---|
16 | //NOTE: the non-merge version of this is saved in the first git commit
|
---|
17 | public class MyTreeDropTarget extends TreeDropTarget<FileSystemKey> {
|
---|
18 | private TextButton btYes= new TextButton("Yes");;
|
---|
19 | private TextButton btYesToAll = new TextButton("Yes to All");
|
---|
20 | private TextButton btNo = new TextButton("No");
|
---|
21 | private TextButton btCancel = new TextButton("Cancel");
|
---|
22 | private TextButton btNoToAll = new TextButton("No to All");
|
---|
23 | private AlertMessageBox ctMsg= new AlertMessageBox("", "");;
|
---|
24 |
|
---|
25 | private boolean acceptable; //tag for if duplicate keys found
|
---|
26 | private boolean dropOnRoot;
|
---|
27 | //recovery items for when merge mode is enabled
|
---|
28 | private LinkedList<KeyIndex> itemsToAdd = new LinkedList<KeyIndex>();
|
---|
29 | private LinkedList<KeyIndex> conflicts = new LinkedList<KeyIndex>();
|
---|
30 |
|
---|
31 | private void createMergeWarn(String key1, String key2, int len) {
|
---|
32 | String heading = "Warning: " + len + " conflicting item";
|
---|
33 | if(len > 1)
|
---|
34 | heading += "s";
|
---|
35 |
|
---|
36 | ctMsg.setHeading(heading);
|
---|
37 |
|
---|
38 | String message = "The file '" + key2 + "' already exists in the destination folder '" + key1 + "'. Overwrite it?";
|
---|
39 | if(--len > 1) {
|
---|
40 | message += " (" + len + " more conflicts...)";
|
---|
41 | }
|
---|
42 | else if (len == 1) {
|
---|
43 | message += " (1 more conflict...)";
|
---|
44 | }
|
---|
45 |
|
---|
46 | ctMsg.setMessage(message);
|
---|
47 | ctMsg.setHeight(150);
|
---|
48 | ctMsg.show();
|
---|
49 | }
|
---|
50 |
|
---|
51 | public MyTreeDropTarget(Tree<FileSystemKey, ?> tree, boolean dropOnRoot) {
|
---|
52 | super(tree);
|
---|
53 |
|
---|
54 | this.dropOnRoot = dropOnRoot;
|
---|
55 | //choose to replace the current file
|
---|
56 | btYes.addSelectHandler(new SelectHandler() {
|
---|
57 | @Override
|
---|
58 | public void onSelect(SelectEvent event) {
|
---|
59 | itemsToAdd.add(conflicts.poll());
|
---|
60 | if(conflicts.size() == 0) {
|
---|
61 | ctMsg.hide();
|
---|
62 | InsertClonesFromList();
|
---|
63 | }
|
---|
64 | else {
|
---|
65 | createMergeWarn(conflicts.get(0).item.Key1(), conflicts.get(0).item.Key2(), conflicts.size());
|
---|
66 | }
|
---|
67 | }
|
---|
68 | });
|
---|
69 |
|
---|
70 | //chose to replace all the current files
|
---|
71 | btYesToAll.addSelectHandler(new SelectHandler() {
|
---|
72 | @Override
|
---|
73 | public void onSelect(SelectEvent event) {
|
---|
74 | ctMsg.hide();
|
---|
75 | itemsToAdd.addAll(conflicts);
|
---|
76 | conflicts = new LinkedList<KeyIndex>();
|
---|
77 | InsertClonesFromList();
|
---|
78 | }
|
---|
79 | });
|
---|
80 |
|
---|
81 | //chose not to replace the current file
|
---|
82 | btNo.addSelectHandler(new SelectHandler() {
|
---|
83 | public void onSelect(SelectEvent event) {
|
---|
84 | conflicts.poll();
|
---|
85 | if(conflicts.size() == 0) {
|
---|
86 | ctMsg.hide();
|
---|
87 | InsertClonesFromList();
|
---|
88 | }
|
---|
89 | else {
|
---|
90 | createMergeWarn(conflicts.get(0).item.Key1(), conflicts.get(0).item.Key2(), conflicts.size());
|
---|
91 | }
|
---|
92 | }
|
---|
93 | });
|
---|
94 |
|
---|
95 | //choose not to replace any files
|
---|
96 | btNoToAll.addSelectHandler(new SelectHandler() {
|
---|
97 | @Override
|
---|
98 | public void onSelect(SelectEvent event) {
|
---|
99 | ctMsg.hide();
|
---|
100 | conflicts = new LinkedList<KeyIndex>();
|
---|
101 | InsertClonesFromList();
|
---|
102 | }
|
---|
103 | });
|
---|
104 |
|
---|
105 |
|
---|
106 | //cancel to current operation, will have zero side-effects
|
---|
107 | btCancel.addSelectHandler(new SelectHandler() {
|
---|
108 | @Override
|
---|
109 | public void onSelect(SelectEvent event) {
|
---|
110 | ctMsg.hide();
|
---|
111 | conflicts = new LinkedList<KeyIndex>();
|
---|
112 | itemsToAdd = new LinkedList<KeyIndex>();
|
---|
113 | }
|
---|
114 | });
|
---|
115 |
|
---|
116 | //disable all of the predefined buttons on the item
|
---|
117 | ctMsg.setPredefinedButtons();
|
---|
118 | ctMsg.addButton(btYes);
|
---|
119 | ctMsg.addButton(btYesToAll);
|
---|
120 | ctMsg.addButton(btNo);
|
---|
121 | ctMsg.addButton(btNoToAll);
|
---|
122 | ctMsg.addButton(btCancel);
|
---|
123 | }
|
---|
124 |
|
---|
125 | //TODO: actual file operations
|
---|
126 | private void InsertClonesFromList() {
|
---|
127 | //itemsToAdd is the only list we need
|
---|
128 | TreeStore<FileSystemKey> ts = getWidget().getStore();
|
---|
129 | for(KeyIndex ki : itemsToAdd) {
|
---|
130 | if(ki.replace) {
|
---|
131 | ts.remove(ki.item);
|
---|
132 | }
|
---|
133 |
|
---|
134 | //always insert at index 0: the tree will be sorted later
|
---|
135 | if(ki.parent == null) {
|
---|
136 | ts.insert(0, ki.item);
|
---|
137 | }
|
---|
138 | else {
|
---|
139 | ts.insert(ki.parent, 0, ki.item);
|
---|
140 | }
|
---|
141 |
|
---|
142 | ts.update(ki.item); //forces item visibility
|
---|
143 | }
|
---|
144 |
|
---|
145 | itemsToAdd = new LinkedList<KeyIndex>();
|
---|
146 | conflicts = new LinkedList<KeyIndex>();
|
---|
147 | }
|
---|
148 |
|
---|
149 |
|
---|
150 | @Override
|
---|
151 | protected void appendModel(FileSystemKey p, List<?> items, int index) {
|
---|
152 | if (items.size() == 0)
|
---|
153 | return;
|
---|
154 | if (items.get(0) instanceof TreeStore.TreeNode) {
|
---|
155 | @SuppressWarnings("unchecked")
|
---|
156 | List<TreeStore.TreeNode<FileSystemKey>> nodes = (List<TreeStore.TreeNode<FileSystemKey>>) items;
|
---|
157 |
|
---|
158 | if(p == null != dropOnRoot)
|
---|
159 | return;
|
---|
160 | acceptable = true;
|
---|
161 |
|
---|
162 | checkMergeModel(p, nodes, false);
|
---|
163 |
|
---|
164 | if(acceptable) { //zero duplicates contained in the items to insert
|
---|
165 | InsertClonesFromList();
|
---|
166 | } else { //we have a bit of confirmation/denial to do
|
---|
167 | createMergeWarn(conflicts.get(0).item.Key1(), conflicts.get(0).item.Key2(), conflicts.size());
|
---|
168 | }
|
---|
169 | } else { // we should NEVER end up getting this unless we have items
|
---|
170 | // coming from another type of chart
|
---|
171 | @SuppressWarnings("unchecked")
|
---|
172 | List<FileSystemKey> models = (List<FileSystemKey>) items;
|
---|
173 | if (p == null) {
|
---|
174 | getWidget().getStore().insert(index, models);
|
---|
175 | } else {
|
---|
176 | getWidget().getStore().insert(p, index, models);
|
---|
177 | }
|
---|
178 | }
|
---|
179 | }
|
---|
180 |
|
---|
181 | //I think I'm making a mistake here...
|
---|
182 | @SuppressWarnings("unchecked")
|
---|
183 | private void checkMergeModel(FileSystemKey parent,
|
---|
184 | List<TreeStore.TreeNode<FileSystemKey>> items, boolean succ) {
|
---|
185 | for (TreeStore.TreeNode<FileSystemKey> node : items) {
|
---|
186 |
|
---|
187 | //don't allow shortcuts, or entire filesystem, to be dropped into right hand side
|
---|
188 | if(!node.getData().Droppable()) {
|
---|
189 | continue;
|
---|
190 | }
|
---|
191 | FileSystemKey clone;
|
---|
192 | // slightly different handling for if this item is at a root or a
|
---|
193 | // branch of the tree
|
---|
194 | if (parent == null) {
|
---|
195 | clone = new FileSystemKey(node.getData());
|
---|
196 | clone.SetKey("/", null, null);
|
---|
197 | } else {
|
---|
198 | clone = new FileSystemKey(node.getData());
|
---|
199 | clone.SetKey(parent.toKey(), null, null);
|
---|
200 | }
|
---|
201 |
|
---|
202 | if (!succ && getWidget().getStore().findModel(clone) != null) {
|
---|
203 | // key is a duplicate -> need to do some merging
|
---|
204 | if(!getWidget().isLeaf(clone)) {
|
---|
205 | //the item itself is already in the tree, and must itself be a folder,
|
---|
206 | //so we don't actually add it to the list of items
|
---|
207 | //we still need to add all of it's children though
|
---|
208 | checkMergeModel(clone, (List<TreeNode<FileSystemKey>>) node.getChildren(), succ);
|
---|
209 | }
|
---|
210 | else { //item is leaf
|
---|
211 | //the item is being merged-replaced, but only if the user wants this - we should have a confirmation dialog for all of these
|
---|
212 | //this also means no more recursion beyond this point
|
---|
213 | conflicts.add(new KeyIndex(clone, parent, true));
|
---|
214 | acceptable = false;
|
---|
215 | }
|
---|
216 | } else {
|
---|
217 | itemsToAdd.add(new KeyIndex(clone, parent, false));
|
---|
218 | List<TreeStore.TreeNode<FileSystemKey>> children = (List<TreeStore.TreeNode<FileSystemKey>>) node
|
---|
219 | .getChildren();
|
---|
220 | checkMergeModel(clone, children, true);
|
---|
221 | }
|
---|
222 | }
|
---|
223 | }
|
---|
224 |
|
---|
225 | private class KeyIndex {
|
---|
226 | public FileSystemKey item;
|
---|
227 | public FileSystemKey parent;
|
---|
228 | public boolean replace;
|
---|
229 | public KeyIndex(FileSystemKey item, FileSystemKey parent, boolean replace) {
|
---|
230 | this.item = item;
|
---|
231 | this.parent = parent;
|
---|
232 | this.replace = replace;
|
---|
233 | }
|
---|
234 | }
|
---|
235 |
|
---|
236 |
|
---|
237 | }
|
---|