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

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

Removed another dead function.

  • 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.TreeSynchronizer;
65import org.greenstone.gatherer.util.Utility;
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 /** 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. */
76 private DragGroup group = null;
77 /** The tree showing the files within the collection. */
78 private CollectionTree collection_tree = null;
79 /** The threaded queue that handles the actually movement of files, so that the gui remains responsive. */
80 private FileQueue file_queue = null;
81 /** The filter currently applied to the collection tree. */
82 private Filter collection_filter = null;
83 /** The filter currently applied to the workspace tree. */
84 private Filter workspace_filter = null;
85 /** The button used to cancel all pending file queue jobs. */
86 private JButton stop_action = null;
87 /** The button used to create a new folder in the collection tree. */
88 private JButton new_folder = null;
89 /** The label shown at the top of the collection tree. */
90 private JLabel collection_label = null;
91 /** The label shown in the status area explaining the file apon which action is taking place. */
92 private JLabel filename_label = null;
93 /** The label shown explaining the current state of the file queue thread. */
94 private JLabel status_label = null;
95 /** The label at the top of the workspace tree. */
96 private JLabel workspace_label = null;
97 /** The panel that contains the collection tree. */
98 private JPanel collection_pane = null;
99 /** The panel that contains the various controls including the status area. */
100 private JPanel control_pane = null;
101 /** The panel that contains the workspace tree. */
102 private JPanel workspace_pane = null;
103 /** The scrollable area into which the collection tree is placed. */
104 private JScrollPane collection_scroll = null;
105 /** The scrollable area into which the workspace tree is placed. */
106 private JScrollPane workspace_scroll = null;
107 /** A split pane seperating the two trees, allowing for the screen real-estate for each to be changed. */
108 private JSplitPane tree_pane = null;
109 /** Ensures that expansion and selection events between collection trees based on the same model are synchronized. */
110 private TreeSynchronizer collection_tree_sync = null;
111 /** The minimum size a gui component can become. */
112 static private Dimension MIN_SIZE = new Dimension( 90, 90);
113 /** The default size of the status area. */
114 static private Dimension STATUS_SIZE = new Dimension(450, 120);
115 /** The initial size of the trees. */
116 static private Dimension TREE_SIZE = new Dimension(400, 430);
117
118 /** The tree showing the available source workspace. */
119 public WorkspaceTree workspace_tree = null;
120
121
122 /* Constructor.
123 * @param tree_sync Ensures that expansion events between like trees are synchronized.
124 * @see org.greenstone.gatherer.file.FileManager
125 * @see org.greenstone.gatherer.file.FileQueue
126 */
127 public GatherPane(TreeSynchronizer collection_tree_sync) {
128 this.group = new DragGroup();
129 this.file_queue = Gatherer.f_man.getQueue();
130 this.collection_tree_sync = collection_tree_sync;
131
132 // Create components.
133 stop_action = new GLIButton();
134 stop_action.addActionListener(this);
135 stop_action.setEnabled(false);
136 stop_action.setMnemonic(KeyEvent.VK_S);
137 file_queue.registerStopButton(stop_action);
138 Dictionary.registerBoth(stop_action, "Collection.Stop", "Collection.Stop_Tooltip");
139
140 new_folder = new GLIButton(JarTools.getImage("folder.gif"));
141 new_folder.addActionListener(this);
142 new_folder.setEnabled(false);
143 new_folder.setMinimumSize(MIN_SIZE);
144 new_folder.setMnemonic(KeyEvent.VK_N);
145 new_folder.setPreferredSize(MIN_SIZE);
146 Dictionary.registerTooltip(new_folder, "Collection.New_Folder_Tooltip");
147 }
148
149 /** 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. */
150 public void actionPerformed(ActionEvent event) {
151 // If a user has clicked on the bin button directly remove whatever
152 // files are selected in the active tree.
153 if (event.getSource() == Gatherer.recycle_bin) {
154 if (!Gatherer.recycle_bin.ignore()) {
155 // Find the active tree (you've made selections in).
156 DragTree tree = (DragTree) group.getActive();
157 // Fudge things a bit
158 group.setSource(tree);
159 // Determine the selection.
160 TreePath paths[] = tree.getSelectionPaths();
161 if(paths != null) {
162 FileNode[] source_nodes = new FileNode[paths.length];
163 for(int i = 0; i < paths.length; i++) {
164 source_nodes[i] = (FileNode)(paths[i].getLastPathComponent());
165 }
166 Gatherer.f_man.action(tree, source_nodes, Gatherer.recycle_bin, null);
167 }
168 }
169 }
170 // If a user has clicked on new_folder create a new folder under
171 // whatever node is selected.
172 else if(event.getSource() == new_folder && collection_tree != null) {
173 int count = collection_tree.getSelectionCount();
174 boolean error = false;
175 if(count == 1) {
176 TreePath path = collection_tree.getSelectionPath();
177 CollectionTreeNode node = (CollectionTreeNode) path.getLastPathComponent();
178 if (node.getAllowsChildren()) {
179 Gatherer.f_man.newFolder(collection_tree, node);
180 }
181 else {
182 // try the parent
183 CollectionTreeNode parent = (CollectionTreeNode) node.getParent();
184 if (parent!=null && parent.getAllowsChildren()) {
185 Gatherer.f_man.newFolder(collection_tree, parent);
186 } else {
187 error = true;
188 }
189 }
190 }
191 else {
192 error = true;
193 }
194 if(error) {
195 // instead of an error, we now create a new folder at the root
196 CollectionTreeNode node = (CollectionTreeNode) collection_tree.getModel().getRoot();
197 Gatherer.f_man.newFolder(collection_tree, node);
198 }
199 }
200 else if(event.getSource() == stop_action) {
201 file_queue.cancelAction();
202 }
203 }
204
205
206 /** Generates the pane on controls used to 'collect' files into the collection. Resposible for creating, connecting and laying out these controls. */
207 public void display()
208 {
209 // Workspace Tree
210 workspace_pane = new JPanel();
211 workspace_pane.setMinimumSize(MIN_SIZE);
212 workspace_pane.setPreferredSize(TREE_SIZE);
213 workspace_pane.setSize(TREE_SIZE);
214
215 workspace_label = new JLabel();
216 workspace_label.setOpaque(true);
217 workspace_label.setBackground(Configuration.getColor("coloring.workspace_heading_background", false));
218 workspace_label.setForeground(Configuration.getColor("coloring.workspace_heading_foreground", false));
219 Dictionary.registerText(workspace_label, "Collection.Workspace");
220
221 workspace_tree = new WorkspaceTree(Utility.WORKSPACE_TREE);
222 group.add(workspace_tree);
223
224 workspace_scroll = new JScrollPane(workspace_tree);
225
226 workspace_filter = Gatherer.g_man.getFilter(workspace_tree);
227 workspace_filter.setBackground(Configuration.getColor("coloring.workspace_heading_background", false));
228 workspace_filter.setEditable(Configuration.getMode() > Configuration.LIBRARIAN_MODE);
229 Dictionary.registerTooltip(workspace_filter.getComboBox(), "Collection.Filter_Tooltip");
230
231 // Collection Tree
232 collection_pane = new JPanel();
233 collection_pane.setMinimumSize(MIN_SIZE);
234 collection_pane.setPreferredSize(TREE_SIZE);
235 collection_pane.setSize(TREE_SIZE);
236
237 collection_label = new JLabel();
238 collection_label.setOpaque(true);
239 Dictionary.registerText(collection_label, "Collection.No_Collection");
240
241 collection_tree = new CollectionTree(Utility.COLLECTION_TREE, Gatherer.c_man.getCollectionTreeModel(), true);
242 collection_tree.setEnabled(Gatherer.c_man.getCollectionTreeModel() != null);
243 group.add(collection_tree);
244
245 collection_scroll = new JScrollPane(collection_tree);
246
247 collection_filter = Gatherer.g_man.getFilter(collection_tree);
248 collection_filter.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
249 collection_filter.setEditable(Configuration.getMode() > Configuration.LIBRARIAN_MODE);
250 Dictionary.registerTooltip(collection_filter.getComboBox(), "Collection.Filter_Tooltip");
251
252 tree_pane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
253
254 // Status pane
255 control_pane = new JPanel();
256
257 JPanel inner_pane = new JPanel();
258 inner_pane.setSize(STATUS_SIZE);
259
260 JPanel file_pane = new JPanel();
261 JPanel progress_pane = new JPanel();
262 JLabel file_status = file_queue.getFileStatus();
263
264 JProgressBar progress_bar = file_queue.getProgressBar();
265
266 JPanel button_pane = new JPanel();
267
268 RecycleBin recycle_bin = Gatherer.recycle_bin;
269 recycle_bin.addActionListener(this);
270 recycle_bin.setMinimumSize(MIN_SIZE);
271 recycle_bin.setPreferredSize(MIN_SIZE);
272 Dictionary.registerTooltip(recycle_bin, "Collection.Delete_Tooltip");
273 group.add(recycle_bin);
274
275 // Layout Components.
276 workspace_pane.setLayout(new BorderLayout());
277 workspace_pane.add(workspace_label, BorderLayout.NORTH);
278 workspace_pane.add(workspace_scroll, BorderLayout.CENTER);
279 workspace_pane.add(workspace_filter, BorderLayout.SOUTH);
280
281 collection_pane.setLayout(new BorderLayout());
282 collection_pane.add(collection_label, BorderLayout.NORTH);
283 collection_pane.add(collection_scroll, BorderLayout.CENTER);
284 collection_pane.add(collection_filter, BorderLayout.SOUTH);
285
286 tree_pane.add(workspace_pane, JSplitPane.LEFT);
287 tree_pane.add(collection_pane, JSplitPane.RIGHT);
288 tree_pane.setDividerLocation(TREE_SIZE.width - 10);
289
290 file_pane.setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
291 file_pane.setLayout(new BorderLayout());
292 file_pane.add(file_status, BorderLayout.CENTER);
293 file_pane.add(stop_action, BorderLayout.EAST);
294
295 progress_pane.setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
296 progress_pane.setLayout(new BorderLayout());
297 progress_pane.add(progress_bar, BorderLayout.CENTER);
298
299 inner_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(10,10,10,10), BorderFactory.createLoweredBevelBorder()));
300 inner_pane.setLayout(new GridLayout(2,1));
301 inner_pane.add(file_pane);
302 inner_pane.add(progress_pane);
303
304 button_pane.add(new_folder);
305 button_pane.add(recycle_bin);
306
307 control_pane.setLayout(new BorderLayout());
308 control_pane.add(inner_pane, BorderLayout.CENTER);
309 control_pane.add(button_pane, BorderLayout.EAST);
310
311 this.setLayout(new BorderLayout());
312 this.add(tree_pane, BorderLayout.CENTER);
313 this.add(control_pane, BorderLayout.SOUTH);
314 }
315
316
317 /** Called to inform this control panel that it has just gained focus as an effect of the user clicking on its tab.
318 */
319 public void gainFocus() {
320 // Update the meta-audit view to show the current selection, if any.
321 Gatherer.g_man.meta_audit.setRecords(getCollectionTreeSelection());
322 }
323
324
325 /** Retrieve a list of the currently selected file records in the collection tree. */
326 private CollectionTreeNode[] getCollectionTreeSelection()
327 {
328 TreePath paths[] = collection_tree.getSelectionPaths();
329 CollectionTreeNode records[] = null;
330 if (paths != null) {
331 records = new CollectionTreeNode[paths.length];
332 for (int i = 0; i < records.length; i++) {
333 records[i] = (CollectionTreeNode) paths[i].getLastPathComponent();
334 }
335 }
336 return records;
337 }
338
339
340 /** 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)
341 * @param mode the mode level as an int
342 */
343 public void modeChanged(int mode) {
344 collection_filter.setEditable(mode > Configuration.LIBRARIAN_MODE);
345 workspace_filter.setEditable(mode > Configuration.LIBRARIAN_MODE);
346 }
347
348
349 /** Refresh this pane, depending on what has just happened (refresh_reason). */
350 public void refresh(int refresh_reason, boolean collection_loaded)
351 {
352 if (collection_loaded) {
353 // Update collection label
354 Dictionary.registerText(collection_label, "Collection.Collection");
355 collection_label.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
356 collection_label.setForeground(Configuration.getColor("coloring.collection_heading_foreground", false));
357
358 // Update collection tree
359 if (refresh_reason == Gatherer.COLLECTION_OPENED) {
360 collection_tree.setModel(Gatherer.c_man.getCollectionTreeModel());
361 }
362
363 // Update collection filter
364 collection_filter.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
365 }
366 else {
367 // Update collection label
368 String[] args = new String[1];
369 args[0] = Dictionary.get("Collection.No_Collection");
370 Dictionary.registerText(collection_label, "Collection.Collection", args);
371 collection_label.setBackground(Color.lightGray);
372 collection_label.setForeground(Color.black);
373
374 // Update collection tree
375 collection_tree.setModel(new DefaultTreeModel(new DefaultMutableTreeNode("Error")));
376
377 // Update collection filter
378 collection_filter.setBackground(Color.lightGray);
379 }
380
381 // Enable or disable the controls
382 workspace_tree.setEnabled(true);
383 collection_tree.setEnabled(collection_loaded);
384 collection_filter.setEnabled(collection_loaded);
385 new_folder.setEnabled(collection_loaded);
386
387 // Ensure that this collection tree view is synchronized with all others
388 collection_tree_sync.add(collection_tree);
389 }
390
391
392 public void refreshCollectionTree(int refresh_reason) {
393 collection_tree.refresh(null);
394 }
395
396
397 public void refreshWorkspaceTree(int refresh_reason) {
398 workspace_tree.refresh(refresh_reason);
399 }
400}
Note: See TracBrowser for help on using the repository browser.