source: trunk/gli/src/org/greenstone/gatherer/gui/EnrichPane.java@ 11629

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

Kissed the horrible TreeSynchronizer goodbye.

  • Property svn:keywords set to Author Date Id Revision
File size: 14.4 KB
Line 
1/**
2 *############################################################################
3 * A component of the Greenstone Librarian Interface, part of the Greenstone
4 * digital library suite from the New Zealand Digital Library Project at the
5 * University of Waikato, New Zealand.
6 *
7 * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
8 * Based on code by John Thompson
9 *
10 * Copyright (C) 2005 New Zealand Digital Library Project
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *############################################################################
26 */
27
28package org.greenstone.gatherer.gui;
29
30
31import java.awt.*;
32import java.awt.event.*;
33import java.io.*;
34import java.util.*;
35import javax.swing.*;
36import javax.swing.event.*;
37import javax.swing.text.*;
38import javax.swing.tree.*;
39import org.greenstone.gatherer.Configuration;
40import org.greenstone.gatherer.DebugStream;
41import org.greenstone.gatherer.Dictionary;
42import org.greenstone.gatherer.Gatherer;
43import org.greenstone.gatherer.collection.CollectionTree;
44import org.greenstone.gatherer.collection.CollectionTreeNode;
45import org.greenstone.gatherer.gui.tree.DragTree;
46import org.greenstone.gatherer.metadata.MetadataElement;
47import org.greenstone.gatherer.metadata.MetadataValue;
48import org.greenstone.gatherer.metadata.MetadataValueTableEntry;
49import org.greenstone.gatherer.metadata.MetadataValueTreeNode;
50import org.greenstone.gatherer.metadata.MetadataXMLFileManager;
51import org.greenstone.gatherer.util.DragGroup;
52
53
54/** Provides a view of controls for the editing of metadata.
55 */
56public class EnrichPane
57 extends JPanel
58 implements TreeSelectionListener
59{
60 static private Dimension MINIMUM_SIZE = new Dimension(100, 100);
61 static private Dimension COLLECTION_TREE_SIZE = new Dimension(250, 500);
62
63 /** The collection tree. */
64 private CollectionTree collection_tree = null;
65 /** The currently reported selection. */
66 private CollectionTreeNode[] file_nodes = null;
67 /** Used to dynamically filter the collection tree. */
68 private Filter collection_filter = null;
69 /** The label at the top of the collection tree, which shows the collection name. */
70 private JLabel collection_label;
71 /** The panel that contains the collection tree. */
72 private JPanel collection_pane = null;
73 /** The scrollable area into which the collection tree is placed. */
74 private JScrollPane collection_scroll = null;
75 /** The splitpane dividing the collection tree and the metadata editing controls. */
76 private JSplitPane external_split;
77 /** The metadata value table shows the metadata values that are currently assigned to a file. */
78 private MetadataValueTablePane metadata_value_table_pane = null;
79 /** The metadata value tree shows the metadata values that are currently assigned to a metadata element. */
80 private MetadataValueTreePane metadata_value_tree_pane = null;
81
82
83 public EnrichPane()
84 {
85 // Create the metadata value tree pane
86 metadata_value_tree_pane = new MetadataValueTreePane();
87 metadata_value_tree_pane.addMetadataValueTreeSelectionListener(new MetadataValueTreeSelectionListener());
88
89 // Create metadata value table pane
90 metadata_value_table_pane = new MetadataValueTablePane();
91 metadata_value_table_pane.addMetadataValueTableListSelectionListener(new MetadataValueTableListSelectionListener());
92 metadata_value_table_pane.addMetadataValueTableMouseListener(new MetadataValueTableMouseListener());
93 metadata_value_table_pane.addMetadataValueTextFieldDocumentListener(new MetadataValueTextFieldDocumentListener());
94 metadata_value_table_pane.addMetadataValueTextFieldKeyListener(new MetadataValueTextFieldKeyListener());
95 }
96
97
98 /** Some actions can only occur after this panel has been displayed on-screen, so this method is provided to do exactly that. Such actions include the proportioning of the split panes and the setting of table column widths.
99 */
100 public void afterDisplay()
101 {
102 external_split.setDividerLocation(0.3);
103 }
104
105
106 /** Used to create, connect and layout the components to be shown on this control panel.
107 * @see org.greenstone.gatherer.Gatherer
108 * @see org.greenstone.gatherer.file.FileOpenActionListener
109 * @see org.greenstone.gatherer.gui.Filter
110 */
111 public void display()
112 {
113 // Creation
114 collection_pane = new JPanel(new BorderLayout());
115 collection_pane.setMinimumSize(MINIMUM_SIZE);
116 collection_pane.setPreferredSize(COLLECTION_TREE_SIZE);
117
118 external_split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
119
120 collection_label = new JLabel();
121 Dictionary.registerText(collection_label, "Collection.No_Collection");
122 collection_label.setOpaque(true);
123
124 DragGroup group = new DragGroup();
125 collection_tree = Gatherer.c_man.getCollectionTree();
126 group.add(collection_tree);
127 collection_tree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
128 collection_tree.addTreeSelectionListener(this);
129 collection_filter = collection_tree.getFilter();
130
131 // Layout
132 collection_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(3,3,3,3), BorderFactory.createLoweredBevelBorder()));
133 collection_pane.setMinimumSize(MINIMUM_SIZE);
134 collection_pane.setPreferredSize(new Dimension(Gatherer.g_man.getSize().width / 3, Gatherer.g_man.getSize().height));
135
136 // Collection Pane
137 collection_pane.add(collection_label, BorderLayout.NORTH);
138
139 JSplitPane metadata_editing_pane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
140 metadata_editing_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
141 metadata_editing_pane.setDividerSize(8);
142
143 metadata_editing_pane.add(metadata_value_table_pane, JSplitPane.TOP);
144 metadata_editing_pane.add(metadata_value_tree_pane, JSplitPane.BOTTOM);
145 metadata_editing_pane.setDividerLocation(250);
146
147 external_split.add(collection_pane, JSplitPane.LEFT);
148 external_split.add(metadata_editing_pane, JSplitPane.RIGHT);
149
150 this.setLayout(new BorderLayout());
151 this.add(external_split, BorderLayout.CENTER);
152 }
153
154
155 /** Called to inform this pane that it has just gained focus as an effect of the user clicking on its tab
156 */
157 public void gainFocus()
158 {
159 // If there is nothing in the collection tree there is nothing to do
160 if (collection_tree == null || collection_tree.getRowCount() == 0) {
161 return;
162 }
163
164 // Add the collection tree and filter back into this pane
165 collection_scroll = new JScrollPane(collection_tree);
166 collection_pane.add(collection_scroll, BorderLayout.CENTER);
167 collection_pane.add(collection_filter, BorderLayout.SOUTH);
168
169 // Select the first node in the tree if nothing is already selected
170 if (collection_tree.getSelectionPaths() == null) {
171 collection_tree.setImmediate(true);
172 collection_tree.setSelectionRow(0);
173 collection_tree.setImmediate(false);
174 return;
175 }
176
177 // Force all of the controls to be updated
178 valueChanged(null);
179 }
180
181
182 /** Called to inform this pane that it has just lost focus as an effect of the user clicking on another tab
183 */
184 public void loseFocus()
185 {
186 // Very important: make sure metadata value is saved before leaving the pane
187 metadata_value_table_pane.stopEditingAndRebuild(file_nodes);
188
189 // Upload the modified metadata.xml files to the server now, if we're using one
190 MetadataXMLFileManager.uploadModifiedMetadataXMLFiles();
191
192 // Remove the collection tree and filter from this pane so it can be added to the Gather pane
193 collection_pane.remove(collection_scroll);
194 collection_pane.remove(collection_filter);
195 }
196
197
198 /** 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)
199 * @param mode the mode level as an int
200 */
201 public void modeChanged(int mode)
202 {
203 collection_filter.setEditable(mode > Configuration.LIBRARIAN_MODE);
204 }
205
206
207 /** Refresh this pane, depending on what has just happened (refresh_reason). */
208 public void refresh(int refresh_reason, boolean collection_loaded)
209 {
210 if (collection_loaded) {
211 // Update collection label
212 Dictionary.registerText(collection_label, "Collection.Collection");
213 collection_label.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
214 collection_label.setForeground(Configuration.getColor("coloring.collection_heading_foreground", false));
215
216 // Update collection tree
217 if (refresh_reason == Gatherer.COLLECTION_OPENED) {
218 collection_tree.setModel(Gatherer.c_man.getCollectionTreeModel());
219 }
220
221 // Update collection filter
222 collection_filter.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
223 }
224 else {
225 // Update collection label
226 Dictionary.registerText(collection_label, "Collection.No_Collection");
227 collection_label.setBackground(Color.lightGray);
228 collection_label.setForeground(Color.black);
229
230 // Update collection tree
231 collection_tree.setModel(new DefaultTreeModel(new DefaultMutableTreeNode("Error")));
232
233 // Update collection filter
234 collection_filter.setBackground(Color.lightGray);
235 }
236
237 // Enable or disable the controls
238 collection_tree.setEnabled(collection_loaded);
239 collection_filter.setEnabled(collection_loaded);
240
241 // Force the metadata table to be rebuilt (for switching extracted metadata on or off)
242 if (refresh_reason == Gatherer.PREFERENCES_CHANGED) {
243 metadata_value_table_pane.stopEditingAndRebuild(file_nodes);
244 }
245 }
246
247
248 /** Called whenever the collection tree selection changes. This causes the metadata value table to be rebuilt. */
249 public void valueChanged(TreeSelectionEvent event)
250 {
251 // Nothing selected in the collection tree
252 if (collection_tree.getSelectionCount() == 0) {
253 file_nodes = null;
254 }
255
256 // Some files selected in the collection tree
257 else {
258 TreePath paths[] = collection_tree.getSelectionPaths();
259 file_nodes = new CollectionTreeNode[paths.length];
260 for (int i = 0; i < paths.length; i++) {
261 file_nodes[i] = (CollectionTreeNode) paths[i].getLastPathComponent();
262 }
263 }
264
265 // Update the metadata value table (and consequently, the metadata value tree)
266 metadata_value_table_pane.stopEditingAndRebuild(file_nodes);
267 }
268
269
270 private class MetadataValueTableListSelectionListener
271 implements ListSelectionListener
272 {
273 public void valueChanged(ListSelectionEvent list_selection_event)
274 {
275 // We only want to handle one event per selection, so wait for the value to stabilise
276 if (list_selection_event.getValueIsAdjusting()) {
277 return;
278 }
279
280 // Update the metadata value tree for the current table selection
281 metadata_value_tree_pane.rebuild(metadata_value_table_pane.getSelectedMetadataValueTableEntry());
282 }
283 }
284
285
286 private class MetadataValueTableMouseListener
287 extends MouseAdapter
288 {
289 public void mouseClicked(MouseEvent mouse_event)
290 {
291 // We're only interested in clicks on the inherited column
292 if (metadata_value_table_pane.isMouseEventForInheritedMetadataValueTableColumn(mouse_event) == false) {
293 return;
294 }
295
296 // If the selected metadata is inherited, switch to the folder it came from
297 MetadataValueTableEntry selected_metadata_value_table_entry = metadata_value_table_pane.getSelectedMetadataValueTableEntry();
298 if (selected_metadata_value_table_entry.isInheritedMetadata()) {
299 collection_tree.setSelection(selected_metadata_value_table_entry.getFolderMetadataInheritedFrom());
300 }
301 }
302 }
303
304
305 private class MetadataValueTextFieldDocumentListener
306 implements DocumentListener
307 {
308 /** Gives notification that an attribute or set of attributes changed */
309 public void changedUpdate(DocumentEvent document_event) {
310 validate(document_event);
311 }
312
313 /** Gives notification that there was an insert into the document */
314 public void insertUpdate(DocumentEvent document_event) {
315 validate(document_event);
316 }
317
318 /** Gives notification that a portion of the document has been removed */
319 public void removeUpdate(DocumentEvent document_event) {
320 validate(document_event);
321 }
322
323
324 /** Ensures that the value tree is updated in response to changes in the value text field */
325 private void validate(DocumentEvent document_event)
326 {
327 try {
328 Document document = document_event.getDocument();
329 String metadata_value_string = document.getText(0, document.getLength());
330 metadata_value_tree_pane.selectBestPathForMetadataValue(metadata_value_string);
331 }
332 catch (Exception exception) {
333 DebugStream.printStackTrace(exception);
334 }
335 }
336 }
337
338
339 private class MetadataValueTextFieldKeyListener
340 extends KeyAdapter
341 {
342 /** Gives notification of key events on the text field */
343 public void keyPressed(KeyEvent key_event)
344 {
345 // Tab: Auto-complete what is selected in the metadata value tree
346 if (key_event.getKeyCode() == KeyEvent.VK_TAB) {
347 MetadataValueTreeNode selected_metadata_value_tree_node = metadata_value_tree_pane.getSelectedMetadataValueTreeNode();
348 if (selected_metadata_value_tree_node != null) {
349 metadata_value_table_pane.setMetadataValueTextFieldValue(selected_metadata_value_tree_node.getFullValue());
350 }
351
352 // We do not want this event to be processed by the table also
353 key_event.consume();
354 }
355
356 // Enter: save the current value then add a blank row for the selected metadata element
357 if (key_event.getKeyCode() == KeyEvent.VK_ENTER) {
358 metadata_value_table_pane.stopEditingAndAddBlankRowForSelectedMetadataElement();
359 }
360 }
361 }
362
363
364 private class MetadataValueTreeSelectionListener
365 implements TreeSelectionListener
366 {
367 public void valueChanged(TreeSelectionEvent tree_selection_event)
368 {
369 // When a node is selected in the tree, fill the metadata value text field with the selected node's value
370 MetadataValueTreeNode selected_metadata_value_tree_node = metadata_value_tree_pane.getSelectedMetadataValueTreeNode();
371 if (selected_metadata_value_tree_node != null) {
372 metadata_value_table_pane.setMetadataValueTextFieldValue(selected_metadata_value_tree_node.getFullValue());
373 }
374 }
375 }
376}
Note: See TracBrowser for help on using the repository browser.