1 /*
2  * Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE
3  */
4 package de.ilias.services.filemanager.content;
5 
6 import de.ilias.services.filemanager.FileManager;
7 import de.ilias.services.filemanager.events.ListItemContextMenuEventHandler;
8 import de.ilias.services.filemanager.utils.FileManagerUtils;
9 import java.util.ArrayList;
10 import java.util.Iterator;
11 import java.util.logging.Logger;
12 import javafx.collections.ObservableList;
13 import javafx.scene.Node;
14 import javafx.scene.control.ContextMenu;
15 import javafx.scene.control.ListView;
16 import javafx.scene.control.MenuItemBuilder;
17 import javafx.scene.control.SeparatorMenuItemBuilder;
18 import javafx.scene.image.ImageViewBuilder;
19 import javafx.scene.input.*;
20 
21 /**
22  * Class ListItemActionContextMenu
23  *
24  * @author Stefan Meyer <smeyer.ilias@gmx.de>
25  */
26 public class ListItemActionContextMenu extends ContextMenu {
27 
28 	private static final Logger logger = Logger.getLogger(ListItemActionContextMenu.class.getName());
29 
30 	private ObservableList<Node> selected = null;
31 	private Node source = null;
32 	private ArrayList<ListItem> listItems = new ArrayList<ListItem>();
33 
34 	private boolean allowOpen = false;
35 	private boolean allowCopy = false;
36 	private boolean allowPaste = false;
37 	private boolean allowDelete = false;
38 	private boolean allowRename = false;
39 	private boolean allowCopyToClipboard = false;
40 
41 	private boolean allowCreate = false;
42 	private boolean allowCourse = false;
43 	private boolean allowFolder = false;
44 	private boolean allowCategory = false;
45 	private boolean allowGroup = false;
46 
ListItemActionContextMenu(ObservableList<Node> sel, Node source)47 	public ListItemActionContextMenu(ObservableList<Node> sel, Node source) {
48 
49 		selected = sel;
50 		this.source = source;
51 		parseSelected();
52 		populate();
53 	}
54 
55 	/**
56 	 * get selected nodes
57 	 * @return
58 	 */
getSelectedNodes()59 	public ObservableList<Node> getSelectedNodes() {
60 		return selected;
61 	}
62 
63 	/**
64 	 * Get array list of list items
65 	 * @return
66 	 */
getSelectedItems()67 	public ArrayList<ListItem> getSelectedItems() {
68 		return listItems;
69 	}
70 
71 	/**
72 	 * Get source
73 	 * @return
74 	 */
getSource()75 	public Node getSource() {
76 		return source;
77 	}
78 
parseSelected()79 	protected void parseSelected() {
80 
81 		boolean multipleSelected;
82 
83 		if(getSelectedNodes().size() > 1) {
84 			multipleSelected = true;
85 			allowCreate = false;
86 			allowOpen = false;
87 			allowCopy = true;
88 			allowCopyToClipboard = true;
89 			allowPaste = false;
90 			allowRename = false;
91 			allowDelete = true;
92 		}
93 		else {
94 			multipleSelected = false;
95 			allowOpen = true;
96 			allowCopy = true;
97 			allowCopyToClipboard = true;
98 			allowRename = true;
99 			allowPaste = true;
100 			allowDelete = true;
101 		}
102 
103 		Iterator nodeIte = getSelectedNodes().iterator();
104 
105 		while(nodeIte.hasNext()) {
106 			Node node = (Node) nodeIte.next();
107 			ListItem listItem = (ListItem) node.getUserData();
108 
109 			getSelectedItems().add(listItem);
110 
111 			if(
112 					listItem instanceof RemoteListItem &&
113 					(getSelectedNodes().size() == 1) &&
114 					(listItem.getType().equals("crs") ||
115 					listItem.getType().equals("grp"))
116 			) {
117 				allowCopyToClipboard = false;
118 			}
119 
120 			// Currently no delete for local list
121 			if(listItem instanceof RemoteListItem && listItem.isContainer()) {
122 				//allowDelete = false;
123 			}
124 			if(!allowPaste(listItem)) {
125 				allowPaste = false;
126 			}
127 			/*
128 			if(listItem instanceof RemoteListItem && listItem.isContainer()) {
129 				allowOpen = false;
130 			}
131 			*/
132 			if(!listItem.isWritable()) {
133 				allowPaste = false;
134 				allowRename = false;
135 			}
136 			if(!listItem.isReadable()) {
137 				allowCopy = false;
138 				allowCopyToClipboard = false;
139 				allowOpen = false;
140 				allowPaste = false;
141 				allowRename = false;
142 			}
143 			if(!listItem.isDeletable()) {
144 				allowDelete = false;
145 			}
146 			if(listItem instanceof LocalListItem) {
147 				allowCopyToClipboard = false;
148 			}
149 			if(listItem.isCourseAllowed() && !multipleSelected) {
150 				allowCreate = true;
151 				allowCourse = true;
152 			}
153 			if(listItem.isCategoryAllowed() && !multipleSelected) {
154 				allowCreate = true;
155 				allowCategory = true;
156 			}
157 			if(listItem.isGroupAllowed() && !multipleSelected) {
158 				allowCreate = true;
159 				allowGroup = true;
160 			}
161 			if(listItem.isFolderAllowed() && !multipleSelected) {
162 				allowCreate = true;
163 				allowFolder = true;
164 			}
165 			// restrictive for upper link
166 			if(listItem.isUpperLink()) {
167 				allowCreate = false;
168 				allowOpen = false;
169 				allowCopy = false;
170 				allowCopyToClipboard = false;
171 				allowRename = false;
172 				allowPaste = false;
173 				allowDelete = false;
174 			}
175 		}
176 
177 		/**
178 		 * Default action of list view
179 		 */
180 		if(getSource() instanceof ListView) {
181 			allowOpen = false;
182 			allowCopy = false;
183 			allowCopyToClipboard = false;
184 			allowRename = false;
185 			allowDelete = false;
186 
187 			if(((ListItem)getSource().getUserData()).isCategoryAllowed()) {
188 				allowCreate = true;
189 				allowCategory = true;
190 			}
191 			if(((ListItem)getSource().getUserData()).isCourseAllowed()) {
192 				allowCreate = true;
193 				allowCourse = true;
194 			}
195 			if(((ListItem)getSource().getUserData()).isGroupAllowed()) {
196 				allowCreate = true;
197 				allowGroup = true;
198 			}
199 			if(((ListItem)getSource().getUserData()).isFolderAllowed()) {
200 				allowCreate = true;
201 				allowFolder = true;
202 			}
203 
204 			logger.info("List view default id = " + String.valueOf(((ListItem)getSource().getUserData()).getRefId()));
205 		}
206 
207 		// Hide paste if clipboard content id empty
208 		Clipboard clip = Clipboard.getSystemClipboard();
209 		if(!clip.hasFiles()) {
210 			allowPaste = false;
211 		}
212 	}
213 
214 
215 	/**
216 	 * Populate action menu
217 	 */
populate()218 	protected void populate() {
219 
220 		// Open
221 		this.getItems().addAll(
222 				MenuItemBuilder.create().
223 				text("Open").
224 				accelerator(new KeyCodeCombination(KeyCode.O,KeyCodeCombination.CONTROL_DOWN)).
225 				graphic(
226 					ImageViewBuilder.create().image(FileManagerUtils.getImageByName("edit.png")).build()).
227 				disable(!allowOpen).
228 				onAction(new ListItemContextMenuEventHandler((ListItem) getSource().getUserData(), ListItemContextMenuEventHandler.ACTION_OPEN)).
229 				build()
230 		);
231 
232 		// Separator
233 		this.getItems().addAll(
234 				SeparatorMenuItemBuilder.create().build());
235 
236 		// Copy disabled
237 		/*
238 		this.getItems().addAll(
239 				MenuItemBuilder.create().
240 				text("Copy").
241 				graphic(
242 					ImageViewBuilder.create().image(FileManagerUtils.getImageByName("edit-copy.png")).build()).
243 				disable(!allowCopy).
244 				onAction(new ListItemContextMenuEventHandler((ListItem) getSource().getUserData(), ListItemContextMenuEventHandler.ACTION_COPY)).
245 				build()
246 		);
247 
248 		*/
249 
250 		// Copy to clipboard
251 		this.getItems().addAll(
252 				MenuItemBuilder.create().
253 				text("Copy to Clipboard").
254 				accelerator(new KeyCodeCombination(KeyCode.C,KeyCodeCombination.CONTROL_DOWN)).
255 				graphic(
256 					ImageViewBuilder.create().image(FileManagerUtils.getImageByName("edit-copy.png")).build()).
257 				disable(!allowCopyToClipboard).
258 				onAction(new ListItemContextMenuEventHandler((ListItem) getSource().getUserData(), ListItemContextMenuEventHandler.ACTION_COPY_TO_CLIPBOARD)).
259 				build()
260 		);
261 
262 		// Paste
263 		this.getItems().addAll(
264 				MenuItemBuilder.create().
265 				text("Paste").
266 				accelerator(new KeyCodeCombination(KeyCode.V,KeyCodeCombination.CONTROL_DOWN)).
267 				graphic(
268 					ImageViewBuilder.create().image(FileManagerUtils.getImageByName("edit-paste.png")).build()).
269 				disable(!allowPaste).
270 				onAction(new ListItemContextMenuEventHandler((ListItem) getSource().getUserData(), ListItemContextMenuEventHandler.ACTION_PASTE)).
271 				build()
272 		);
273 
274 		// Seperator
275 		this.getItems().addAll(
276 				SeparatorMenuItemBuilder.create().build());
277 
278 		// Delete
279 		this.getItems().addAll(
280 				MenuItemBuilder.create().
281 				accelerator(new KeyCodeCombination(KeyCode.DELETE)).
282 				text("Delete").
283 				graphic(
284 					ImageViewBuilder.create().image(FileManagerUtils.getImageByName("edit-delete.png")).build()).
285 				disable(!allowDelete).
286 				onAction(new ListItemContextMenuEventHandler((ListItem) getSource().getUserData(), ListItemContextMenuEventHandler.ACTION_DELETE)).
287 				build()
288 		);
289 
290 		// Rename
291 		this.getItems().addAll(
292 				MenuItemBuilder.create().
293 				text("Rename").
294 				accelerator(new KeyCodeCombination(KeyCode.R,KeyCodeCombination.CONTROL_DOWN)).
295 				graphic(
296 					ImageViewBuilder.create().image(FileManagerUtils.getImageByName("edit-rename.png")).build()).
297 				disable(!allowRename).
298 				onAction(new ListItemContextMenuEventHandler((ListItem) getSource().getUserData(), ListItemContextMenuEventHandler.ACTION_RENAME)).
299 				build()
300 		);
301 
302 		// File lock for files
303 		if(checkAllowLock()) {
304 			this.getItems().addAll(
305 				MenuItemBuilder.create().
306 				text("Edit Revision State").
307 				accelerator(new KeyCodeCombination(KeyCode.L,KeyCodeCombination.CONTROL_DOWN)).
308 				graphic(
309 					ImageViewBuilder.create().image(FileManagerUtils.getImageByName("edit-revision.png")).build()).
310 				disable(false).
311 				onAction(new ListItemContextMenuEventHandler((ListItem) getSource().getUserData(), ListItemContextMenuEventHandler.ACTION_EDIT_REVISION_STATE)).
312 				build()
313 			);
314 		}
315 
316 
317 		if(allowCreate) {
318 			// Seperator
319 			this.getItems().addAll(
320 					SeparatorMenuItemBuilder.create().build());
321 
322 			// Category
323 			if(allowCategory) {
324 				this.getItems().addAll(
325 						MenuItemBuilder.create().
326 						text("Create Category").
327 						graphic(
328 							ImageViewBuilder.create().image(FileManagerUtils.getImageByName("icon_cat_s.gif")).build()).
329 						disable(false).
330 						onAction(new ListItemContextMenuEventHandler((ListItem) getSource().getUserData(), ListItemContextMenuEventHandler.ACTION_CREATE_CAT)).
331 						build()
332 				);
333 			}
334 			// Folder
335 			if(allowFolder) {
336 				this.getItems().addAll(
337 						MenuItemBuilder.create().
338 						text("Create Folder").
339 						graphic(
340 							ImageViewBuilder.create().image(FileManagerUtils.getImageByName("icon_fold_s.gif")).build()).
341 						disable(false).
342 						onAction(new ListItemContextMenuEventHandler((ListItem) getSource().getUserData(), ListItemContextMenuEventHandler.ACTION_CREATE_FOLD)).
343 						build()
344 				);
345 			}
346 			// Course
347 			if(allowCourse) {
348 				this.getItems().addAll(
349 						MenuItemBuilder.create().
350 						text("Create Course").
351 						graphic(
352 							ImageViewBuilder.create().image(FileManagerUtils.getImageByName("icon_crs_s.gif")).build()).
353 						disable(false).
354 						onAction(new ListItemContextMenuEventHandler((ListItem) getSource().getUserData(), ListItemContextMenuEventHandler.ACTION_CREATE_CRS)).
355 						build()
356 				);
357 			}
358 			// Group
359 			if(allowGroup) {
360 				this.getItems().addAll(
361 						MenuItemBuilder.create().
362 						text("Create Group").
363 						graphic(
364 							ImageViewBuilder.create().image(FileManagerUtils.getImageByName("icon_grp_s.gif")).build()).
365 						disable(false).
366 						onAction(new ListItemContextMenuEventHandler((ListItem) getSource().getUserData(), ListItemContextMenuEventHandler.ACTION_CREATE_GRP)).
367 						build()
368 				);
369 			}
370 
371 		}
372 	}
373 
374 	/**
375 	 * Check if lock action should be displayed.
376 	 * @return
377 	 */
checkAllowLock()378 	protected boolean checkAllowLock() {
379 
380 		if(this.getSelectedNodes().size() != 1) {
381 			return false;
382 		}
383 
384 		Iterator nodeIte = getSelectedNodes().iterator();
385 		while(nodeIte.hasNext()) {
386 			Node node = (Node) nodeIte.next();
387 			ListItem item = (ListItem) node.getUserData();
388 
389 			if(item.getType().equals("file") && item.isWritable()) {
390 				logger.info("Item allows file lock");
391 				return true;
392 			}
393 		}
394 		return false;
395 	}
396 
397 	/**
398 	 * Check if paste is allowed
399 	 * @param item
400 	 * @return
401 	 */
allowPaste(ListItem item)402 	public static boolean allowPaste(ListItem item) {
403 
404 		if(item.isContainer() && item.isWritable()) {
405 			return true;
406 		}
407 		if(item.getType().equalsIgnoreCase("file") && item.isWritable()) {
408 			return true;
409 		}
410 		return false;
411 	}
412 }
413