source: trunk/gli/src/org/greenstone/gatherer/gui/GatherPane.java@ 12102

Last change on this file since 12102 was 11780, checked in by mdewsnip, 18 years ago

Added a "no collection loaded" message to the collection area when no collection is open.

  • Property svn:keywords set to Author Date Id Revision
File size: 16.8 KB
Line 
1/**
2 *#########################################################################
3 *
4 * A component of the Gatherer application, part of the Greenstone digital
5 * library suite from the New Zealand Digital Library Project at the
6 * University of Waikato, New Zealand.
7 *
8 * <BR><BR>
9 *
10 * Author: John Thompson, Greenstone Digital Library, University of Waikato
11 *
12 * <BR><BR>
13 *
14 * Copyright (C) 1999 New Zealand Digital Library Project
15 *
16 * <BR><BR>
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * <BR><BR>
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * <BR><BR>
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 *########################################################################
36 */
37package org.greenstone.gatherer.gui;
38
39import java.awt.*;
40import java.awt.event.*;
41import java.io.*;
42import java.util.*;
43import javax.swing.*;
44import javax.swing.event.*;
45import javax.swing.tree.*;
46import org.greenstone.gatherer.Configuration;
47import org.greenstone.gatherer.DebugStream;
48import org.greenstone.gatherer.Dictionary;
49import org.greenstone.gatherer.Gatherer;
50import org.greenstone.gatherer.collection.CollectionTree;
51import org.greenstone.gatherer.collection.CollectionTreeNode;
52import org.greenstone.gatherer.file.FileNode;
53import org.greenstone.gatherer.file.FileOpenActionListener;
54import org.greenstone.gatherer.file.FileQueue;
55import org.greenstone.gatherer.file.FileSystemModel;
56import org.greenstone.gatherer.file.RecycleBin;
57import org.greenstone.gatherer.file.WorkspaceTree;
58import org.greenstone.gatherer.file.WorkspaceTreeNode;
59import org.greenstone.gatherer.gui.tree.DragTree;
60import org.greenstone.gatherer.gui.ExplodeMetadataPrompt;
61import org.greenstone.gatherer.util.DragComponent;
62import org.greenstone.gatherer.util.DragGroup;
63import org.greenstone.gatherer.util.JarTools;
64import org.greenstone.gatherer.util.Utility;
65
66
67/** The collection pane is analogous with a file manager. It is there that the user chooses which files to include in their collection and what structure the file hierarchy should take. The later aspect is not important for the Greenstone Suite, but is usefull for grouping files for ease of metadata markup. The view essentially consists of two file trees, one denoting the entire source workspace and the other the files within your collection. The trees themselves have a title bar at the top, a filter control at the bottom, and are coloured to indicate activity (grey for disabled). The remainder of the screen is taken by a status area, to indicate current file job progress during copying etc, and three buttons for controlling features of the view.
68 * @author John Thompson, Greenstone Digital Library, University of Waikato
69 * @version 2.3
70 */
71public class GatherPane
72 extends JPanel
73 implements ActionListener
74{
75 private CardLayout card_layout = null;
76 private JPanel card_pane = null;
77 /** The name of the panel containing the "collection loaded" (collection tree) card. */
78 private String COLLECTION_LOADED_CARD = "";
79 /** The name of the panel containing the "no collection loaded" placeholder */
80 private String NO_COLLECTION_LOADED_CARD = "No collection loaded";
81 /** The group encompassing all of the components available as drop targets for drag and drop actions. Required so that only one component renders the ghost and higlights itself as a target, which the other members are restored to their original, pristine, condition. */
82 private DragGroup group = null;
83 /** The tree showing the files within the collection. */
84 private CollectionTree collection_tree = null;
85 /** The threaded queue that handles the actually movement of files, so that the gui remains responsive. */
86 private FileQueue file_queue = null;
87 /** The filter currently applied to the collection tree. */
88 private Filter collection_filter = null;
89 /** The filter currently applied to the workspace tree. */
90 private Filter workspace_filter = null;
91 /** The button used to cancel all pending file queue jobs. */
92 private JButton stop_action = null;
93 /** The button used to create a new folder in the collection tree. */
94 private JButton new_folder = null;
95 /** The label shown at the top of the collection tree. */
96 private JLabel collection_label = null;
97 /** The label shown in the status area explaining the file apon which action is taking place. */
98 private JLabel filename_label = null;
99 /** The label shown explaining the current state of the file queue thread. */
100 private JLabel status_label = null;
101 /** The label at the top of the workspace tree. */
102 private JLabel workspace_label = null;
103 /** The panel that contains the collection tree. */
104 private JPanel collection_pane = null;
105 /** The panel that contains the various controls including the status area. */
106 private JPanel control_pane = null;
107 /** The panel that contains the workspace tree. */
108 private JPanel workspace_pane = null;
109 /** The scrollable area into which the collection tree is placed. */
110 private JScrollPane collection_scroll = null;
111 /** The scrollable area into which the workspace tree is placed. */
112 private JScrollPane workspace_scroll = null;
113 /** A split pane seperating the two trees, allowing for the screen real-estate for each to be changed. */
114 private JSplitPane tree_pane = null;
115 /** The minimum size a gui component can become. */
116 static private Dimension MIN_SIZE = new Dimension( 90, 90);
117 /** The default size of the status area. */
118 static private Dimension STATUS_SIZE = new Dimension(450, 120);
119 /** The initial size of the trees. */
120 static private Dimension TREE_SIZE = new Dimension(400, 430);
121
122 /** The tree showing the available source workspace. */
123 public WorkspaceTree workspace_tree = null;
124
125
126 public GatherPane()
127 {
128 this.group = new DragGroup();
129 this.file_queue = Gatherer.f_man.getQueue();
130
131 // Create components.
132 stop_action = new GLIButton();
133 stop_action.addActionListener(this);
134 stop_action.setEnabled(false);
135 stop_action.setMnemonic(KeyEvent.VK_S);
136 file_queue.registerStopButton(stop_action);
137 Dictionary.registerBoth(stop_action, "Collection.Stop", "Collection.Stop_Tooltip");
138
139 new_folder = new GLIButton(JarTools.getImage("folder.gif"));
140 new_folder.addActionListener(this);
141 new_folder.setEnabled(false);
142 new_folder.setMinimumSize(MIN_SIZE);
143 new_folder.setMnemonic(KeyEvent.VK_N);
144 new_folder.setPreferredSize(MIN_SIZE);
145 Dictionary.registerTooltip(new_folder, "Collection.New_Folder_Tooltip");
146 }
147
148 /** Any implementation of ActionListener requires this method so that when an action is performed the appropriate effect can occur. In this case there are three valid possibilities. If the action occured on the recycle bin, then delete the current selection from the collection tree. If the action instead occured on the new folder button, then create a new folder under the current (single) selection in the collection tree. And finally if the cancel button was pressed, cancel the current, and remaining, jobs on the file queue. */
149 public void actionPerformed(ActionEvent event) {
150 // If a user has clicked on the bin button directly remove whatever
151 // files are selected in the active tree.
152 if (event.getSource() == Gatherer.recycle_bin) {
153 if (!Gatherer.recycle_bin.ignore()) {
154 // Find the active tree (you've made selections in).
155 DragTree tree = (DragTree) group.getActive();
156 // Fudge things a bit
157 group.setSource(tree);
158 // Determine the selection.
159 TreePath paths[] = tree.getSelectionPaths();
160 if(paths != null) {
161 FileNode[] source_nodes = new FileNode[paths.length];
162 for(int i = 0; i < paths.length; i++) {
163 source_nodes[i] = (FileNode)(paths[i].getLastPathComponent());
164 }
165 Gatherer.f_man.action(tree, source_nodes, Gatherer.recycle_bin, null);
166 }
167 }
168 }
169 // If a user has clicked on new_folder create a new folder under
170 // whatever node is selected.
171 else if(event.getSource() == new_folder && collection_tree != null) {
172 int count = collection_tree.getSelectionCount();
173 boolean error = false;
174 if(count == 1) {
175 TreePath path = collection_tree.getSelectionPath();
176 CollectionTreeNode node = (CollectionTreeNode) path.getLastPathComponent();
177 if (node.getAllowsChildren()) {
178 Gatherer.f_man.newFolder(collection_tree, node);
179 }
180 else {
181 // try the parent
182 CollectionTreeNode parent = (CollectionTreeNode) node.getParent();
183 if (parent!=null && parent.getAllowsChildren()) {
184 Gatherer.f_man.newFolder(collection_tree, parent);
185 } else {
186 error = true;
187 }
188 }
189 }
190 else {
191 error = true;
192 }
193 if(error) {
194 // instead of an error, we now create a new folder at the root
195 CollectionTreeNode node = (CollectionTreeNode) collection_tree.getModel().getRoot();
196 Gatherer.f_man.newFolder(collection_tree, node);
197 }
198 }
199 else if(event.getSource() == stop_action) {
200 file_queue.cancelAction();
201 }
202 }
203
204
205 /** Generates the pane on controls used to 'collect' files into the collection. Resposible for creating, connecting and laying out these controls. */
206 public void display()
207 {
208 // Workspace Tree
209 workspace_pane = new JPanel();
210 workspace_pane.setMinimumSize(MIN_SIZE);
211 workspace_pane.setPreferredSize(TREE_SIZE);
212 workspace_pane.setSize(TREE_SIZE);
213
214 workspace_label = new JLabel();
215 workspace_label.setOpaque(true);
216 workspace_label.setBackground(Configuration.getColor("coloring.workspace_heading_background", false));
217 workspace_label.setForeground(Configuration.getColor("coloring.workspace_heading_foreground", false));
218 Dictionary.registerText(workspace_label, "Collection.Workspace");
219
220 workspace_tree = new WorkspaceTree();
221 group.add(workspace_tree);
222 workspace_scroll = new JScrollPane(workspace_tree);
223 workspace_filter = workspace_tree.getFilter();
224
225 card_layout = new CardLayout();
226
227 // Collection Tree
228 collection_pane = new JPanel();
229 collection_pane.setMinimumSize(MIN_SIZE);
230 collection_pane.setPreferredSize(TREE_SIZE);
231 collection_pane.setSize(TREE_SIZE);
232
233 collection_label = new JLabel();
234 collection_label.setOpaque(true);
235 Dictionary.registerText(collection_label, "Collection.Collection");
236
237 collection_tree = Gatherer.c_man.getCollectionTree();
238 collection_tree.setEnabled(Gatherer.c_man.getCollectionTreeModel() != null);
239 group.add(collection_tree);
240 collection_filter = collection_tree.getFilter();
241
242 tree_pane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
243
244 // No collection loaded pane
245 JPanel no_collection_pane = new JPanel();
246 no_collection_pane.setBackground(Color.lightGray);
247
248 JLabel no_collection_label = new JLabel();
249 no_collection_label.setBackground(Color.lightGray);
250 no_collection_label.setForeground(Color.black);
251 no_collection_label.setOpaque(true);
252 Dictionary.registerText(no_collection_label, "Collection.Collection");
253
254 JPanel no_collection_loaded_panel = new JPanel();
255 no_collection_loaded_panel.setBorder(BorderFactory.createLineBorder(Color.black));
256 no_collection_loaded_panel.setBackground(Color.lightGray);
257
258 JLabel no_collection_loaded_label = new JLabel();
259 no_collection_loaded_label.setHorizontalAlignment(JLabel.CENTER);
260 no_collection_loaded_label.setVerticalAlignment(JLabel.CENTER);
261 Dictionary.registerText(no_collection_loaded_label, "Collection.No_Collection_Loaded");
262
263 // Status pane
264 control_pane = new JPanel();
265
266 JPanel inner_pane = new JPanel();
267 inner_pane.setSize(STATUS_SIZE);
268
269 card_pane = new JPanel();
270 JPanel file_pane = new JPanel();
271 JPanel progress_pane = new JPanel();
272 JLabel file_status = file_queue.getFileStatus();
273
274 JProgressBar progress_bar = file_queue.getProgressBar();
275
276 JPanel button_pane = new JPanel();
277
278 RecycleBin recycle_bin = Gatherer.recycle_bin;
279 recycle_bin.addActionListener(this);
280 recycle_bin.setMinimumSize(MIN_SIZE);
281 recycle_bin.setPreferredSize(MIN_SIZE);
282 Dictionary.registerTooltip(recycle_bin, "Collection.Delete_Tooltip");
283 group.add(recycle_bin);
284
285 // Layout Components.
286 workspace_pane.setLayout(new BorderLayout());
287 workspace_pane.add(workspace_label, BorderLayout.NORTH);
288 workspace_pane.add(workspace_scroll, BorderLayout.CENTER);
289 workspace_pane.add(workspace_filter, BorderLayout.SOUTH);
290
291 collection_pane.setLayout(new BorderLayout());
292 collection_pane.add(collection_label, BorderLayout.NORTH);
293
294 no_collection_loaded_panel.setLayout(new BorderLayout());
295 no_collection_loaded_panel.add(no_collection_loaded_label, BorderLayout.CENTER);
296
297 no_collection_pane.setLayout(new BorderLayout());
298 no_collection_pane.add(no_collection_label, BorderLayout.NORTH);
299 no_collection_pane.add(no_collection_loaded_panel, BorderLayout.CENTER);
300
301 card_pane.setLayout(card_layout);
302 card_pane.add(no_collection_pane, NO_COLLECTION_LOADED_CARD);
303 card_pane.add(collection_pane, COLLECTION_LOADED_CARD);
304
305 tree_pane.add(workspace_pane, JSplitPane.LEFT);
306 tree_pane.add(card_pane, JSplitPane.RIGHT);
307 tree_pane.setDividerLocation(TREE_SIZE.width - 10);
308
309 file_pane.setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
310 file_pane.setLayout(new BorderLayout());
311 file_pane.add(file_status, BorderLayout.CENTER);
312 file_pane.add(stop_action, BorderLayout.EAST);
313
314 progress_pane.setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
315 progress_pane.setLayout(new BorderLayout());
316 progress_pane.add(progress_bar, BorderLayout.CENTER);
317
318 inner_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(10,10,10,10), BorderFactory.createLoweredBevelBorder()));
319 inner_pane.setLayout(new GridLayout(2,1));
320 inner_pane.add(file_pane);
321 inner_pane.add(progress_pane);
322
323 button_pane.add(new_folder);
324 button_pane.add(recycle_bin);
325
326 control_pane.setLayout(new BorderLayout());
327 control_pane.add(inner_pane, BorderLayout.CENTER);
328 control_pane.add(button_pane, BorderLayout.EAST);
329
330 this.setLayout(new BorderLayout());
331 this.add(tree_pane, BorderLayout.CENTER);
332 this.add(control_pane, BorderLayout.SOUTH);
333 }
334
335
336 /** Called to inform this control panel that it has just gained focus as an effect of the user clicking on its tab.
337 */
338 public void gainFocus()
339 {
340 // Add the collection tree and filter back into this pane
341 collection_scroll = new JScrollPane(collection_tree);
342 collection_pane.add(collection_scroll, BorderLayout.CENTER);
343 collection_pane.add(collection_filter, BorderLayout.SOUTH);
344 }
345
346
347 /** Called to inform this pane that it has just lost focus as an effect of the user clicking on another tab
348 */
349 public void loseFocus()
350 {
351 // Remove the collection tree and filter from this pane so it can be added to the Enrich pane
352 collection_pane.remove(collection_scroll);
353 collection_pane.remove(collection_filter);
354 }
355
356
357 /** Retrieve a list of the currently selected file records in the collection tree. */
358 private CollectionTreeNode[] getCollectionTreeSelection()
359 {
360 TreePath paths[] = collection_tree.getSelectionPaths();
361 CollectionTreeNode records[] = null;
362 if (paths != null) {
363 records = new CollectionTreeNode[paths.length];
364 for (int i = 0; i < records.length; i++) {
365 records[i] = (CollectionTreeNode) paths[i].getLastPathComponent();
366 }
367 }
368 return records;
369 }
370
371
372 /** Called whenever the detail mode changes to ensure the filters are at an appropriate level (ie only editable by those that understand regular expression matching)
373 * @param mode the mode level as an int
374 */
375 public void modeChanged(int mode) {
376 collection_filter.setEditable(mode > Configuration.LIBRARIAN_MODE);
377 workspace_filter.setEditable(mode > Configuration.LIBRARIAN_MODE);
378 }
379
380
381 /** Refresh this pane, depending on what has just happened (refresh_reason). */
382 public void refresh(int refresh_reason, boolean collection_loaded)
383 {
384 if (collection_loaded) {
385 // Update collection tree
386 if (refresh_reason == Gatherer.COLLECTION_OPENED) {
387 collection_tree.setModel(Gatherer.c_man.getCollectionTreeModel());
388 }
389
390 card_layout.show(card_pane, COLLECTION_LOADED_CARD);
391 }
392 else {
393 // Update collection tree
394 collection_tree.setModel(new DefaultTreeModel(new DefaultMutableTreeNode("Error")));
395
396 card_layout.show(card_pane, NO_COLLECTION_LOADED_CARD);
397 }
398
399 // Enable or disable the controls
400 collection_tree.setEnabled(collection_loaded);
401 collection_filter.setEnabled(collection_loaded);
402 new_folder.setEnabled(collection_loaded);
403 }
404
405
406 public void refreshCollectionTree(int refresh_reason) {
407 collection_tree.refresh(null);
408 }
409
410
411 public void refreshWorkspaceTree(int refresh_reason) {
412 workspace_tree.refresh(refresh_reason);
413 }
414}
Note: See TracBrowser for help on using the repository browser.