]> git.argeo.org Git - gpl/argeo-suite.git/blob - library/org.argeo.documents.ui/src/org/argeo/documents/ui/DocumentsFolderComposite.java
Support for docbook image object.
[gpl/argeo-suite.git] / library / org.argeo.documents.ui / src / org / argeo / documents / ui / DocumentsFolderComposite.java
1 package org.argeo.documents.ui;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.nio.file.Files;
6 import java.nio.file.Path;
7 import java.nio.file.attribute.FileTime;
8 import java.text.DateFormat;
9 import java.text.SimpleDateFormat;
10 import java.util.ArrayList;
11 import java.util.Date;
12 import java.util.List;
13
14 import javax.jcr.Node;
15
16 import org.apache.commons.logging.Log;
17 import org.apache.commons.logging.LogFactory;
18 import org.argeo.cms.ui.fs.FileDrop;
19 import org.argeo.cms.ui.fs.FsStyles;
20 import org.argeo.cms.ui.util.CmsUiUtils;
21 import org.argeo.eclipse.ui.ColumnDefinition;
22 import org.argeo.eclipse.ui.EclipseUiUtils;
23 import org.argeo.eclipse.ui.fs.FileIconNameLabelProvider;
24 import org.argeo.eclipse.ui.fs.FsTableViewer;
25 import org.argeo.eclipse.ui.fs.FsUiConstants;
26 import org.argeo.eclipse.ui.fs.FsUiUtils;
27 import org.argeo.eclipse.ui.fs.NioFileLabelProvider;
28 import org.argeo.eclipse.ui.fs.ParentDir;
29 import org.eclipse.jface.viewers.DoubleClickEvent;
30 import org.eclipse.jface.viewers.IDoubleClickListener;
31 import org.eclipse.jface.viewers.ISelectionChangedListener;
32 import org.eclipse.jface.viewers.IStructuredSelection;
33 import org.eclipse.jface.viewers.SelectionChangedEvent;
34 import org.eclipse.jface.viewers.Viewer;
35 import org.eclipse.swt.SWT;
36 import org.eclipse.swt.custom.SashForm;
37 import org.eclipse.swt.events.KeyEvent;
38 import org.eclipse.swt.events.KeyListener;
39 import org.eclipse.swt.events.ModifyEvent;
40 import org.eclipse.swt.events.ModifyListener;
41 import org.eclipse.swt.events.MouseAdapter;
42 import org.eclipse.swt.events.MouseEvent;
43 import org.eclipse.swt.events.SelectionAdapter;
44 import org.eclipse.swt.events.SelectionEvent;
45 import org.eclipse.swt.graphics.Point;
46 import org.eclipse.swt.layout.GridData;
47 import org.eclipse.swt.layout.GridLayout;
48 import org.eclipse.swt.layout.RowData;
49 import org.eclipse.swt.layout.RowLayout;
50 import org.eclipse.swt.widgets.Button;
51 import org.eclipse.swt.widgets.Composite;
52 import org.eclipse.swt.widgets.Control;
53 import org.eclipse.swt.widgets.Label;
54 import org.eclipse.swt.widgets.Table;
55 import org.eclipse.swt.widgets.Text;
56
57 /**
58 * Default Documents folder composite: a sashForm layout with a simple table in
59 * the middle and an overview at right hand side.
60 */
61 public class DocumentsFolderComposite extends Composite {
62 private final static Log log = LogFactory.getLog(DocumentsFolderComposite.class);
63 private static final long serialVersionUID = -40347919096946585L;
64
65 private final Node currentBaseContext;
66
67 private final DocumentsUiService documentUiService = new DocumentsUiService();
68
69 // UI Parts for the browser
70 private Composite filterCmp;
71 private Composite breadCrumbCmp;
72 private Text filterTxt;
73 private FsTableViewer directoryDisplayViewer;
74 private Composite rightPanelCmp;
75
76 private DocumentsContextMenu contextMenu;
77 private DateFormat dateFormat = new SimpleDateFormat("YYYY-MM-dd HH:mm");
78
79 // Local context
80 private Path initialPath;
81 private Path currentFolder;
82
83 public DocumentsFolderComposite(Composite parent, int style, Node context) {
84 super(parent, style);
85 this.currentBaseContext = context;
86
87 this.setLayout(EclipseUiUtils.noSpaceGridLayout());
88
89 SashForm form = new SashForm(this, SWT.HORIZONTAL);
90
91 Composite centerCmp = new Composite(form, SWT.BORDER | SWT.NO_FOCUS);
92 createDisplay(centerCmp);
93
94 rightPanelCmp = new Composite(form, SWT.NO_FOCUS);
95
96 form.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
97 form.setWeights(new int[] { 55, 20 });
98 }
99
100 public void populate(Path path) {
101 initialPath = path;
102 directoryDisplayViewer.setInitialPath(initialPath);
103 setInput(path);
104 }
105
106 void refresh() {
107 modifyFilter(false);
108 }
109
110 private void createDisplay(final Composite parent) {
111 parent.setLayout(EclipseUiUtils.noSpaceGridLayout());
112
113 // top filter
114 filterCmp = new Composite(parent, SWT.NO_FOCUS);
115 filterCmp.setLayoutData(EclipseUiUtils.fillWidth());
116 RowLayout rl = new RowLayout(SWT.HORIZONTAL);
117 rl.wrap = true;
118 rl.center = true;
119 filterCmp.setLayout(rl);
120 // addFilterPanel(filterCmp);
121
122 // Main display
123 directoryDisplayViewer = new FsTableViewer(parent, SWT.MULTI);
124 List<ColumnDefinition> colDefs = new ArrayList<>();
125 colDefs.add(new ColumnDefinition(new FileIconNameLabelProvider(), " Name", 250));
126 colDefs.add(new ColumnDefinition(new NioFileLabelProvider(FsUiConstants.PROPERTY_SIZE), "Size", 100));
127 // colDefs.add(new ColumnDefinition(new NioFileLabelProvider(FsUiConstants.PROPERTY_TYPE), "Type", 150));
128 colDefs.add(new ColumnDefinition(new NioFileLabelProvider(FsUiConstants.PROPERTY_LAST_MODIFIED),
129 "Last modified", 400));
130 final Table table = directoryDisplayViewer.configureDefaultTable(colDefs);
131 table.setLayoutData(EclipseUiUtils.fillAll());
132
133 directoryDisplayViewer.addSelectionChangedListener(new ISelectionChangedListener() {
134
135 @Override
136 public void selectionChanged(SelectionChangedEvent event) {
137 IStructuredSelection selection = (IStructuredSelection) directoryDisplayViewer.getSelection();
138 Path selected = null;
139 if (selection.isEmpty())
140 setSelected(null);
141 else {
142 Object o = selection.getFirstElement();
143 if (o instanceof Path)
144 selected = (Path) o;
145 else if (o instanceof ParentDir)
146 selected = ((ParentDir) o).getPath();
147 }
148 if (selected != null) {
149 // TODO manage multiple selection
150 setSelected(selected);
151 }
152 }
153 });
154
155 directoryDisplayViewer.addDoubleClickListener(new IDoubleClickListener() {
156 @Override
157 public void doubleClick(DoubleClickEvent event) {
158 IStructuredSelection selection = (IStructuredSelection) directoryDisplayViewer.getSelection();
159 Path selected = null;
160 if (!selection.isEmpty()) {
161 Object o = selection.getFirstElement();
162 if (o instanceof Path)
163 selected = (Path) o;
164 else if (o instanceof ParentDir)
165 selected = ((ParentDir) o).getPath();
166 }
167 if (selected != null) {
168 if (Files.isDirectory(selected))
169 setInput(selected);
170 else
171 externalNavigateTo(selected);
172 }
173 }
174 });
175
176 // The context menu
177 contextMenu = new DocumentsContextMenu(this, documentUiService);
178
179 table.addMouseListener(new MouseAdapter() {
180 private static final long serialVersionUID = 6737579410648595940L;
181
182 @Override
183 public void mouseDown(MouseEvent e) {
184 if (e.button == 3) {
185 // contextMenu.setCurrFolderPath(currDisplayedFolder);
186 contextMenu.show(table, new Point(e.x, e.y),
187 (IStructuredSelection) directoryDisplayViewer.getSelection(), currentFolder);
188 }
189 }
190 });
191
192 FileDrop fileDrop = new FileDrop() {
193
194 @Override
195 protected void processFileUpload(InputStream in, String fileName, String contetnType) throws IOException {
196 Path file = currentFolder.resolve(fileName);
197 Files.copy(in, file);
198 refresh();
199 }
200 };
201 fileDrop.createDropTarget(directoryDisplayViewer.getTable());
202 }
203
204 /**
205 * Overwrite to enable single sourcing between workbench and CMS navigation
206 */
207 protected void externalNavigateTo(Path path) {
208
209 }
210
211 private void addPathElementBtn(Path path) {
212 Button elemBtn = new Button(breadCrumbCmp, SWT.PUSH);
213 String nameStr;
214 if (path.toString().equals("/"))
215 nameStr = "[jcr:root]";
216 else
217 nameStr = path.getFileName().toString();
218 // elemBtn.setText(nameStr + " >> ");
219 elemBtn.setText(nameStr);
220 CmsUiUtils.style(elemBtn, FsStyles.BREAD_CRUMB_BTN);
221 elemBtn.addSelectionListener(new SelectionAdapter() {
222 private static final long serialVersionUID = -4103695476023480651L;
223
224 @Override
225 public void widgetSelected(SelectionEvent e) {
226 setInput(path);
227 }
228 });
229 }
230
231 public void setInput(Path path) {
232 if (path.equals(currentFolder))
233 return;
234 // below initial path
235 if (!initialPath.equals(path) && initialPath.startsWith(path))
236 return;
237 currentFolder = path;
238
239 Path diff = initialPath.relativize(currentFolder);
240
241 for (Control child : filterCmp.getChildren())
242 if (!child.equals(filterTxt))
243 child.dispose();
244
245 // Bread crumbs
246 breadCrumbCmp = new Composite(filterCmp, SWT.NO_FOCUS);
247 CmsUiUtils.style(breadCrumbCmp, FsStyles.BREAD_CRUMB_BTN);
248 RowLayout breadCrumbLayout = new RowLayout();
249 breadCrumbLayout.spacing = 0;
250 breadCrumbLayout.marginTop = 0;
251 breadCrumbLayout.marginBottom = 0;
252 breadCrumbLayout.marginRight = 0;
253 breadCrumbLayout.marginLeft = 0;
254 breadCrumbCmp.setLayout(breadCrumbLayout);
255 addPathElementBtn(initialPath);
256 Path currTarget = initialPath;
257 if (!diff.toString().equals(""))
258 for (Path pathElem : diff) {
259 currTarget = currTarget.resolve(pathElem);
260 addPathElementBtn(currTarget);
261 }
262
263 if (filterTxt != null) {
264 filterTxt.setText("");
265 filterTxt.moveBelow(null);
266 } else {
267 modifyFilter(false);
268 }
269 setSelected(null);
270 filterCmp.getParent().layout(true, true);
271 }
272
273 private void setSelected(Path path) {
274 if (path == null)
275 setOverviewInput(currentFolder);
276 else
277 setOverviewInput(path);
278 }
279
280 public Viewer getViewer() {
281 return directoryDisplayViewer;
282 }
283
284 /**
285 * Recreates the content of the box that displays information about the current
286 * selected Path.
287 */
288 private void setOverviewInput(Path path) {
289 try {
290 EclipseUiUtils.clear(rightPanelCmp);
291 rightPanelCmp.setLayout(new GridLayout());
292 if (path != null) {
293 // if (isImg(context)) {
294 // EditableImage image = new Img(parent, RIGHT, context,
295 // imageWidth);
296 // image.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER,
297 // true, false,
298 // 2, 1));
299 // }
300
301 Label contextL = new Label(rightPanelCmp, SWT.NONE);
302 contextL.setText(path.getFileName().toString());
303 contextL.setFont(EclipseUiUtils.getBoldFont(rightPanelCmp));
304 FileTime lastModified = Files.getLastModifiedTime(path);
305 if (lastModified.toMillis() != 0)
306 try {
307 String lastModifiedStr = dateFormat.format(new Date(lastModified.toMillis()));
308 addProperty(rightPanelCmp, "Last modified", lastModifiedStr);
309 } catch (Exception e) {
310 log.error("Workarounded issue while getting last update date for " + path, e);
311 addProperty(rightPanelCmp, "Last modified", "-");
312 }
313 // addProperty(rightPannelCmp, "Owner",
314 // Files.getOwner(path).getName());
315 if (Files.isDirectory(path)) {
316 addProperty(rightPanelCmp, "Type", "Folder");
317 } else {
318 String mimeType = Files.probeContentType(path);
319 if (EclipseUiUtils.isEmpty(mimeType))
320 mimeType = "<i>Unknown</i>";
321 addProperty(rightPanelCmp, "Type", mimeType);
322 addProperty(rightPanelCmp, "Size", FsUiUtils.humanReadableByteCount(Files.size(path), false));
323 }
324
325 // read all attributes
326 // Map<String, Object> attrs = Files.readAttributes(path, "*");
327 // for (String attr : attrs.keySet()) {
328 // Object value = attrs.get(attr);
329 // String str;
330 // if (value instanceof Calendar) {
331 // str = dateFormat.format(((Calendar) value).getTime());
332 // } else {
333 // str = value.toString();
334 // }
335 // addProperty(rightPanelCmp, attr, str);
336 //
337 // }
338 }
339 rightPanelCmp.layout(true, true);
340 } catch (IOException e) {
341 throw new IllegalStateException("Cannot display details for " + path.toString(), e);
342 }
343 }
344
345 private void addFilterPanel(Composite parent) {
346 // parent.setLayout(EclipseUiUtils.noSpaceGridLayout(new GridLayout(2,
347 // false)));
348
349 filterTxt = new Text(parent, SWT.SEARCH | SWT.ICON_CANCEL);
350 filterTxt.setMessage("Search current folder");
351 filterTxt.setLayoutData(new RowData(250, SWT.DEFAULT));
352 filterTxt.addModifyListener(new ModifyListener() {
353 private static final long serialVersionUID = 1L;
354
355 public void modifyText(ModifyEvent event) {
356 modifyFilter(false);
357 }
358 });
359 filterTxt.addKeyListener(new KeyListener() {
360 private static final long serialVersionUID = 2533535233583035527L;
361
362 @Override
363 public void keyReleased(KeyEvent e) {
364 }
365
366 @Override
367 public void keyPressed(KeyEvent e) {
368 // boolean shiftPressed = (e.stateMask & SWT.SHIFT) != 0;
369 // // boolean altPressed = (e.stateMask & SWT.ALT) != 0;
370 // FilterEntitiesVirtualTable currTable = null;
371 // if (currEdited != null) {
372 // FilterEntitiesVirtualTable table =
373 // browserCols.get(currEdited);
374 // if (table != null && !table.isDisposed())
375 // currTable = table;
376 // }
377 //
378 // if (e.keyCode == SWT.ARROW_DOWN)
379 // currTable.setFocus();
380 // else if (e.keyCode == SWT.BS) {
381 // if (filterTxt.getText().equals("")
382 // && !(currEdited.getNameCount() == 1 ||
383 // currEdited.equals(initialPath))) {
384 // Path oldEdited = currEdited;
385 // Path parentPath = currEdited.getParent();
386 // setEdited(parentPath);
387 // if (browserCols.containsKey(parentPath))
388 // browserCols.get(parentPath).setSelected(oldEdited);
389 // filterTxt.setFocus();
390 // e.doit = false;
391 // }
392 // } else if (e.keyCode == SWT.TAB && !shiftPressed) {
393 // Path uniqueChild = getOnlyChild(currEdited,
394 // filterTxt.getText());
395 // if (uniqueChild != null) {
396 // // Highlight the unique chosen child
397 // currTable.setSelected(uniqueChild);
398 // setEdited(uniqueChild);
399 // }
400 // filterTxt.setFocus();
401 // e.doit = false;
402 // }
403 }
404 });
405 }
406
407 // private Path getOnlyChild(Path parent, String filter) {
408 // try (DirectoryStream<Path> stream =
409 // Files.newDirectoryStream(currDisplayedFolder, filter + "*")) {
410 // Path uniqueChild = null;
411 // boolean moreThanOne = false;
412 // loop: for (Path entry : stream) {
413 // if (uniqueChild == null) {
414 // uniqueChild = entry;
415 // } else {
416 // moreThanOne = true;
417 // break loop;
418 // }
419 // }
420 // if (!moreThanOne)
421 // return uniqueChild;
422 // return null;
423 // } catch (IOException ioe) {
424 // throw new DocumentsException(
425 // "Unable to determine unique child existence and get it under " + parent +
426 // " with filter " + filter,
427 // ioe);
428 // }
429 // }
430
431 private void modifyFilter(boolean fromOutside) {
432 if (!fromOutside)
433 if (currentFolder != null) {
434 String filter;
435 if (filterTxt != null)
436 filter = filterTxt.getText() + "*";
437 else
438 filter = "*";
439 directoryDisplayViewer.setInput(currentFolder, filter);
440 }
441 }
442
443 // Simplify UI implementation
444 private void addProperty(Composite parent, String propName, String value) {
445 Label propLbl = new Label(parent, SWT.NONE);
446 //propLbl.setText(ConnectUtils.replaceAmpersand(propName + ": " + value));
447 propLbl.setText(value);
448 //CmsUiUtils.markup(propLbl);
449 }
450
451 public Path getCurrentFolder() {
452 return currentFolder;
453 }
454
455 }