1 | package org.greenstone.gatherer.gui;
|
---|
2 | /**
|
---|
3 | *#########################################################################
|
---|
4 | *
|
---|
5 | * A component of the Gatherer application, part of the Greenstone digital
|
---|
6 | * library suite from the New Zealand Digital Library Project at the
|
---|
7 | * University of Waikato, New Zealand.
|
---|
8 | *
|
---|
9 | * <BR><BR>
|
---|
10 | *
|
---|
11 | * Author: John Thompson, Greenstone Digital Library, University of Waikato
|
---|
12 | *
|
---|
13 | * <BR><BR>
|
---|
14 | *
|
---|
15 | * Copyright (C) 1999 New Zealand Digital Library Project
|
---|
16 | *
|
---|
17 | * <BR><BR>
|
---|
18 | *
|
---|
19 | * This program is free software; you can redistribute it and/or modify
|
---|
20 | * it under the terms of the GNU General Public License as published by
|
---|
21 | * the Free Software Foundation; either version 2 of the License, or
|
---|
22 | * (at your option) any later version.
|
---|
23 | *
|
---|
24 | * <BR><BR>
|
---|
25 | *
|
---|
26 | * This program is distributed in the hope that it will be useful,
|
---|
27 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
28 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
29 | * GNU General Public License for more details.
|
---|
30 | *
|
---|
31 | * <BR><BR>
|
---|
32 | *
|
---|
33 | * You should have received a copy of the GNU General Public License
|
---|
34 | * along with this program; if not, write to the Free Software
|
---|
35 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
---|
36 | *########################################################################
|
---|
37 | */
|
---|
38 | import java.awt.*;
|
---|
39 | import java.awt.event.*;
|
---|
40 | import java.io.*;
|
---|
41 | import java.util.*;
|
---|
42 | import javax.swing.*;
|
---|
43 | import javax.swing.border.*;
|
---|
44 | import javax.swing.event.*;
|
---|
45 | import javax.swing.table.*;
|
---|
46 | import javax.swing.tree.*;
|
---|
47 | import org.greenstone.gatherer.Gatherer;
|
---|
48 | import org.greenstone.gatherer.file.FileNode;
|
---|
49 | import org.greenstone.gatherer.file.FileOpenActionListener;
|
---|
50 | import org.greenstone.gatherer.gui.Filter;
|
---|
51 | import org.greenstone.gatherer.gui.GComboBox;
|
---|
52 | import org.greenstone.gatherer.gui.MetaEditPrompt;
|
---|
53 | import org.greenstone.gatherer.gui.WarningDialog;
|
---|
54 | import org.greenstone.gatherer.gui.table.GTableModel;
|
---|
55 | import org.greenstone.gatherer.gui.table.TableCellRenderer;
|
---|
56 | import org.greenstone.gatherer.gui.tree.DragTree;
|
---|
57 | import org.greenstone.gatherer.msm.ElementWrapper;
|
---|
58 | import org.greenstone.gatherer.msm.Metadata;
|
---|
59 | import org.greenstone.gatherer.msm.MSMEvent;
|
---|
60 | import org.greenstone.gatherer.msm.MSMListener;
|
---|
61 | import org.greenstone.gatherer.util.ArrayTools;
|
---|
62 | import org.greenstone.gatherer.util.DragGroup;
|
---|
63 | import org.greenstone.gatherer.util.TreeSynchronizer;
|
---|
64 | import org.greenstone.gatherer.util.Utility;
|
---|
65 | import org.greenstone.gatherer.util.XORToggleButtonGroup;
|
---|
66 | import org.greenstone.gatherer.valuetree.GValueTree;
|
---|
67 | import org.greenstone.gatherer.valuetree.GValueModel;
|
---|
68 | import org.greenstone.gatherer.valuetree.GValueNode;
|
---|
69 | import org.w3c.dom.Element;
|
---|
70 | /** Provides a view of controls for the editing of metadata. It makes use of several other important components such as a GTree, GTable and GValueTree. While much of the gui content is left to these components, the MetaEditPane is resposible for actioning metadata edit requests, listing for mouse clicks within its scope and other data functionality (such as providing a list of the selected files).
|
---|
71 | * @author John Thompson, Greenstone Digital Libraries, University of Waikato
|
---|
72 | * @version 2.3b
|
---|
73 | */
|
---|
74 | public class MetaEditPane
|
---|
75 | extends JPanel
|
---|
76 | implements ActionListener, ListSelectionListener, TreeModelListener, TreeSelectionListener, MSMListener {
|
---|
77 | /** <i>true</i> if the selection has changed since the last time it was asked for, <i>false</i> otherwise. */
|
---|
78 | public boolean has_changed = false;
|
---|
79 | /** The GValueTree graphically shows the available metadata that has been previously assigned, and provides controls for adding, updating and removing metadata, depending on the users selections in the other important components. */
|
---|
80 | public GValueTree tree = null;
|
---|
81 | /** If only files are selected, then show folder is not available. */
|
---|
82 | private boolean show_folder_enabled = false;
|
---|
83 | /** The layout manager used to display either the GTable (when records are selected) or a placeholder panel with the immortal words 'No Record Selected'. */
|
---|
84 | private CardLayout card_layout = null;
|
---|
85 | /** The layout manager used to display either the GValueTree (when records are selected) or a placeholder panel with the immortal words 'No Record Selected'. */
|
---|
86 | private CardLayout card_layout2 = null;
|
---|
87 | /** Used to dynamically filter the collection tree at user request. Note that this is synchronized with the collection tree filter in the Gather view. */
|
---|
88 | private Filter filter = null;
|
---|
89 | /** The data model behind the GTable, to which we hold a reference for convenient access. */
|
---|
90 | private GTableModel model = null;
|
---|
91 | /** The currently reported selection. Note that this may actually be incorrect, but if so the changed flag will be set, and the selection will be updated the next time it is needed. */
|
---|
92 | private FileNode records[] = null;
|
---|
93 | /** Records which of the three GTable views is currently being shown, so we can determine what view to change to next (as they cycle). */
|
---|
94 | //private int current_table_view;
|
---|
95 | /** The mode is determined by the metadata edit action choosen. */
|
---|
96 | private int mode;
|
---|
97 | /** The button, which when clicked, adds metadata to the selected records. */
|
---|
98 | private JButton add;
|
---|
99 | /** The button, which when clicked, removes the selected metadata from the selected records. */
|
---|
100 | private JButton remove;
|
---|
101 | /** The button, which when clicked, changes the currently shown GTable view. */
|
---|
102 | //private JButton table_view;
|
---|
103 | /** The button, which when clicked, updates the selected metadata from the selected records. */
|
---|
104 | private JButton update;
|
---|
105 | /** This button creates an editor dialog to allow for an expanded area to type in text. */
|
---|
106 | private JButton expand;
|
---|
107 | /** The label at the top of the collection tree, which shows the collection name. */
|
---|
108 | private JLabel collection_label;
|
---|
109 | /** The panel in which the metadata value card layout resides. */
|
---|
110 | private JPanel control_pane;
|
---|
111 | /** The panel in which the metadata table card layout resides. */
|
---|
112 | private JPanel table_card_pane;
|
---|
113 | /** The panel the table is added to. */
|
---|
114 | private JPanel table_pane;
|
---|
115 | /** An icon showing the current state of the table build. */
|
---|
116 | //private JProgressBar activity_bar;
|
---|
117 | /** The splitpane dividing the collection tree and the metadata based controls. */
|
---|
118 | private JSplitPane external_split;
|
---|
119 | /** Divides the metadata table and the value tree controls. */
|
---|
120 | private JSplitPane main_split_pane;
|
---|
121 | /** A reference to the metadata table, via its superclass. */
|
---|
122 | private JTable table;
|
---|
123 | /** The label shown at the top of the metadata table detailing the current selection statistics. */
|
---|
124 | private JTextField table_label;
|
---|
125 | /** The button to control whether assigned metadata is shown. */
|
---|
126 | //private JToggleButton assigned_metadata_view;
|
---|
127 | /** The button to control whether unassigned metadata is shown. */
|
---|
128 | //private JToggleButton unassigned_metadata_view;
|
---|
129 | /** A reference to the collection tree. */
|
---|
130 | public DragTree collection_tree;
|
---|
131 | /** The currently selected metadata determined by listening to every second list selection event from the metadata table. */
|
---|
132 | private Metadata selected_metadata;
|
---|
133 | /** Listens for right clicks over the collection tree. */
|
---|
134 | private RightButtonListener right_button_listener = null;
|
---|
135 | /** A temporary storage array from Strings passed to the dictionary to be inserted in the phrase returned. */
|
---|
136 | private String args[];
|
---|
137 | /** Provide synchronization between the collection trees in this view and the collection pane view. */
|
---|
138 | private TreeSynchronizer tree_sync = null;
|
---|
139 | static public Dimension BUTTON_SIZE = new Dimension(190, 25);
|
---|
140 | static private Dimension CONTROL_SIZE = new Dimension(560, 240);
|
---|
141 | static private Dimension LABEL_SIZE = new Dimension(75, 25);
|
---|
142 | static private Dimension MINIMUM_SIZE = new Dimension(100, 100);
|
---|
143 | static private Dimension TABLE_SIZE = new Dimension(560, 25);
|
---|
144 | static private Dimension TREE_SIZE = new Dimension(250, 500);
|
---|
145 | /** An element of the Mode type enumeration, indicating we are adding metadata (ie no metadata rows are selected in the metadata table). */
|
---|
146 | static private int ADD = 0;
|
---|
147 | /** An element of the Mode type enumeration, indicating we are editing existing metadata (ie some row is selected in the metadata table). */
|
---|
148 | static private int EDIT = 1;
|
---|
149 | /** The name of the panel containing the metadata table. */
|
---|
150 | static final private String CARD_ONE = "Card One";
|
---|
151 | /** The name of the panel containing the 'no file' placeholder for the metadata table. */
|
---|
152 | static final private String CARD_TWO = "Card Two";
|
---|
153 | /** The name of the panel containing the 'no metadata' placeholder for the metadata table. */
|
---|
154 | static final private String CARD_ZERO = "Card Zero";
|
---|
155 | /** The name of the panel containing the placeholder for the value tree. */
|
---|
156 | static final private String TOOLS_OFF = "Tools Off";
|
---|
157 | /** The name of the panel containing the value tree. */
|
---|
158 | static final private String TOOLS_ON = "Tools On";
|
---|
159 | /** Constructor.
|
---|
160 | * @param tree_sync The <strong>TreeSynchronizer</strong> to be used on the collection tree.
|
---|
161 | * @see org.greenstone.gatherer.Configuration
|
---|
162 | * @see org.greenstone.gatherer.gui.table.GTable
|
---|
163 | * @see org.greenstone.gatherer.valuetree.GValueTree
|
---|
164 | */
|
---|
165 | public MetaEditPane(TreeSynchronizer tree_sync) {
|
---|
166 | //this.current_table_view = GTableModel.SHOW_FILE;
|
---|
167 | this.tree = null;
|
---|
168 | this.tree_sync = tree_sync;
|
---|
169 |
|
---|
170 | add = new JButton(get("MetaEditPrompt.Accumulate"));
|
---|
171 | add.addActionListener(this);
|
---|
172 | add.setEnabled(false);
|
---|
173 | add.setMnemonic(KeyEvent.VK_A);
|
---|
174 | add.setPreferredSize(BUTTON_SIZE);
|
---|
175 |
|
---|
176 | update = new JButton(get("MetaEditPrompt.Overwrite"));
|
---|
177 | update.addActionListener(this);
|
---|
178 | update.setEnabled(false);
|
---|
179 | update.setMnemonic(KeyEvent.VK_P);
|
---|
180 | update.setPreferredSize(BUTTON_SIZE);
|
---|
181 |
|
---|
182 | remove = new JButton(get("MetaEditPrompt.Remove"));
|
---|
183 | remove.addActionListener(this);
|
---|
184 | remove.setEnabled(false);
|
---|
185 | remove.setMnemonic(KeyEvent.VK_R);
|
---|
186 | remove.setPreferredSize(BUTTON_SIZE);
|
---|
187 |
|
---|
188 | expand = new JButton(get("General.Expand"));
|
---|
189 | expand.addActionListener(this);
|
---|
190 | expand.setEnabled(true);
|
---|
191 | expand.setMnemonic(KeyEvent.VK_E);
|
---|
192 | expand.setPreferredSize(new Dimension(25, 25));
|
---|
193 |
|
---|
194 | tree = new GValueTree(this, CONTROL_SIZE.width, CONTROL_SIZE.height, add, update, remove, expand);
|
---|
195 | }
|
---|
196 | /** Called whenever an action occurs on one of our registered buttons.
|
---|
197 | * @param event An <strong>ActionEvent</strong> containing information about the event.
|
---|
198 | * @see org.greenstone.gatherer.collection.CollectionManager
|
---|
199 | * @see org.greenstone.gatherer.gui.table.GTableModel
|
---|
200 | * @see org.greenstone.gatherer.msm.ElementWrapper
|
---|
201 | * @see org.greenstone.gatherer.msm.MetadataSetManager
|
---|
202 | * @see org.greenstone.gatherer.msm.MSMEvent
|
---|
203 | * @see org.greenstone.gatherer.valuetree.GValueTree
|
---|
204 | */
|
---|
205 | public void actionPerformed(ActionEvent event) {
|
---|
206 | Object esrc = event.getSource();
|
---|
207 | if(esrc == add) {
|
---|
208 | (new AppendMetadataTask()).start();
|
---|
209 | }
|
---|
210 | else if(esrc == update) {
|
---|
211 | (new UpdateMetadataTask()).start();
|
---|
212 | }
|
---|
213 | else if(esrc == remove) {
|
---|
214 | (new RemoveMetadataTask()).start();
|
---|
215 | }
|
---|
216 | else if(esrc == expand) {
|
---|
217 | EditorDialog ed = new EditorDialog();
|
---|
218 | String temp = ed.display(tree.getSelectedValue());
|
---|
219 | if(temp != null) {
|
---|
220 | tree.setSelectedValue(temp);
|
---|
221 | }
|
---|
222 | }
|
---|
223 | //else if(esrc == assigned_metadata_view || esrc == unassigned_metadata_view) {
|
---|
224 | // model.changeView();
|
---|
225 | //}
|
---|
226 | validateControls();
|
---|
227 | }
|
---|
228 |
|
---|
229 | private class AppendMetadataTask
|
---|
230 | extends Thread {
|
---|
231 |
|
---|
232 | public AppendMetadataTask() { }
|
---|
233 |
|
---|
234 | public void run() {
|
---|
235 | // Check the new metadata is valid
|
---|
236 | ElementWrapper element = tree.getSelectedMetadataElement();
|
---|
237 | String value = tree.getSelectedValue();
|
---|
238 | if(records != null && element != null && value != null) {
|
---|
239 | // Check the records, and if they are folders then display the warning.
|
---|
240 | if(!records[0].isLeaf()) {
|
---|
241 | WarningDialog dialog = new WarningDialog("warning.DirectoryLevelMetadata", true);
|
---|
242 | if(dialog.display() == JOptionPane.OK_OPTION) {
|
---|
243 | Gatherer.c_man.getCollection().msm.addMetadata(System.currentTimeMillis(), records, element, value);
|
---|
244 | }
|
---|
245 | dialog.dispose();
|
---|
246 | dialog = null;
|
---|
247 | }
|
---|
248 | else {
|
---|
249 | Gatherer.c_man.getCollection().msm.addMetadata(System.currentTimeMillis(), records, element, value);
|
---|
250 | }
|
---|
251 | GValueNode value_node = ((GValueModel) tree.getModel()).addValue(value);
|
---|
252 | model.setSelectedMetadata(new Metadata(element, value_node));
|
---|
253 | }
|
---|
254 | }
|
---|
255 | }
|
---|
256 |
|
---|
257 | private class UpdateMetadataTask
|
---|
258 | extends Thread {
|
---|
259 |
|
---|
260 | public UpdateMetadataTask() { }
|
---|
261 |
|
---|
262 | public void run() {
|
---|
263 | // You can only update if there is a selected_metadata and
|
---|
264 | // you have valid values in all fields.
|
---|
265 | ElementWrapper element = tree.getSelectedMetadataElement();
|
---|
266 | String value = tree.getSelectedValue();
|
---|
267 | if(selected_metadata != null && records != null && element != null && value != null) {
|
---|
268 | selected_metadata = Gatherer.c_man.getCollection().msm.updateMetadata(System.currentTimeMillis(), selected_metadata, records, value, MetaEditPrompt.OVERWRITE, selected_metadata.isFileLevel());
|
---|
269 | }
|
---|
270 | GValueNode value_node = ((GValueModel) tree.getModel()).addValue(value);
|
---|
271 | model.setSelectedMetadata(new Metadata(element, value_node));
|
---|
272 | }
|
---|
273 | }
|
---|
274 |
|
---|
275 | private class RemoveMetadataTask
|
---|
276 | extends Thread {
|
---|
277 |
|
---|
278 | public RemoveMetadataTask() { }
|
---|
279 |
|
---|
280 | public void run() {
|
---|
281 | if(selected_metadata != null && records != null) {
|
---|
282 | Gatherer.c_man.getCollection().msm.removeMetadata(System.currentTimeMillis(), selected_metadata, records);
|
---|
283 | }
|
---|
284 | }
|
---|
285 | }
|
---|
286 |
|
---|
287 | /** 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.
|
---|
288 | * @see org.greenstone.gatherer.gui.table.GTableModel
|
---|
289 | */
|
---|
290 | public void afterDisplay() {
|
---|
291 | external_split.setDividerLocation(0.3);
|
---|
292 | if(table != null) {
|
---|
293 | Dimension table_size = table.getPreferredSize();
|
---|
294 | TableColumnModel column_model = table.getColumnModel();
|
---|
295 |
|
---|
296 | TableColumn inherited_column = column_model.getColumn(0);
|
---|
297 | inherited_column.setPreferredWidth(20);
|
---|
298 | inherited_column.setCellRenderer(new TableCellRenderer(model));
|
---|
299 |
|
---|
300 | TableColumn element_column = column_model.getColumn(1);
|
---|
301 | element_column.setPreferredWidth(table_size.width / 4);
|
---|
302 | element_column.setCellRenderer(new TableCellRenderer(model));
|
---|
303 |
|
---|
304 | TableColumn value_column = column_model.getColumn(2);
|
---|
305 | value_column.setPreferredWidth(((3 * table_size.width) / 4) - 15);
|
---|
306 | value_column.setCellRenderer(new TableCellRenderer(model));
|
---|
307 | }
|
---|
308 | table.doLayout();
|
---|
309 | model.fireTableDataChanged();
|
---|
310 | }
|
---|
311 | /** Called whenever a significant change has occured in the state of the currently loaded collection.
|
---|
312 | * @param ready <i>true</i> if there is a collection currently ready to be editing, <i>false</i> otherwise.
|
---|
313 | * @see org.greenstone.gatherer.collection.CollectionManager
|
---|
314 | * @see org.greenstone.gatherer.collection.CollectionModel
|
---|
315 | * @see org.greenstone.gatherer.tree.GTree
|
---|
316 | * @see org.greenstone.gatherer.util.TreeSynchronizer
|
---|
317 | */
|
---|
318 | public void collectionChanged(boolean ready) {
|
---|
319 | if(ready) {
|
---|
320 | TreeModel collection_model = Gatherer.c_man.getRecordSet();
|
---|
321 | args = new String[1];
|
---|
322 | args[0] = Gatherer.c_man.getCollection().getName();
|
---|
323 | collection_label.setText(get("Collection.Collection", args));
|
---|
324 | // Update label coloring.
|
---|
325 | collection_label.setBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
|
---|
326 | collection_label.setForeground(Gatherer.config.getColor("coloring.collection_heading_foreground", false));
|
---|
327 | collection_tree.setModel(collection_model);
|
---|
328 | // Update tree coloring.
|
---|
329 | collection_tree.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
|
---|
330 | collection_tree.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
|
---|
331 | // Register our msm dependant components (or correctly their models) with msm.
|
---|
332 | if(model != null) {
|
---|
333 | // remove the listener first - in case its already present
|
---|
334 | Gatherer.c_man.getCollection().msm.removeMSMListener(model);
|
---|
335 | Gatherer.c_man.getCollection().msm.addMSMListener(model);
|
---|
336 | }
|
---|
337 | // register the pane itself as an MSMListener, so if we add a new metadata set, it will immediately show up. - remove itself first just in case
|
---|
338 | Gatherer.c_man.getCollection().msm.removeMSMListener(this);
|
---|
339 | Gatherer.c_man.getCollection().msm.addMSMListener(this);
|
---|
340 | }
|
---|
341 | else {
|
---|
342 | collection_label.setText(get("Collection.No_Collection"));
|
---|
343 | collection_label.setBackground(Color.lightGray);
|
---|
344 | collection_label.setForeground(Color.black);
|
---|
345 | collection_tree.setModel(new DefaultTreeModel(new DefaultMutableTreeNode(get("Collection.No_Collection"))));
|
---|
346 | }
|
---|
347 |
|
---|
348 | filter.setEnabled(ready);
|
---|
349 | // Ensure that this collection tree view is synchronized with any others.
|
---|
350 | tree_sync.add(collection_tree);
|
---|
351 | }
|
---|
352 | /** Used to create, connect and layout the components to be shown on this control panel.
|
---|
353 | * @see org.greenstone.gatherer.Gatherer
|
---|
354 | * @see org.greenstone.gatherer.collection.CollectionManager
|
---|
355 | * @see org.greenstone.gatherer.collection.CollectionModel
|
---|
356 | * @see org.greenstone.gatherer.file.FileOpenActionListener
|
---|
357 | * @see org.greenstone.gatherer.gui.Filter
|
---|
358 | * @see org.greenstone.gatherer.gui.GComboBox
|
---|
359 | * @see org.greenstone.gatherer.gui.table.GTableModel
|
---|
360 | * @see org.greenstone.gatherer.tree.GTree
|
---|
361 | * @see org.greenstone.gatherer.tree.GTreeModel
|
---|
362 | * @see org.greenstone.gatherer.valuetree.GValueTree
|
---|
363 | */
|
---|
364 | public void display() {
|
---|
365 | right_button_listener = new RightButtonListener();
|
---|
366 | // Creation
|
---|
367 | JPanel collection_pane = new JPanel(new BorderLayout());
|
---|
368 | collection_pane.setMinimumSize(MINIMUM_SIZE);
|
---|
369 | collection_pane.setPreferredSize(TREE_SIZE);
|
---|
370 |
|
---|
371 | external_split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
|
---|
372 |
|
---|
373 | ///atherer.println("\tCreating collection_label");
|
---|
374 | args = new String[1];
|
---|
375 | args[0] = get("Collection.No_Collection");
|
---|
376 | collection_label = new JLabel(get("Collection.Collection"));
|
---|
377 | collection_label.setOpaque(true);
|
---|
378 |
|
---|
379 |
|
---|
380 | DragGroup group = new DragGroup();
|
---|
381 | TreeModel collection_model = Gatherer.c_man.getRecordSet();
|
---|
382 | if(collection_model != null) {
|
---|
383 | collection_tree = new DragTree("MetaEdit", collection_model, null);
|
---|
384 | collection_model.addTreeModelListener(this);
|
---|
385 | }
|
---|
386 | else {
|
---|
387 | collection_tree = new DragTree("MetaEdit", null);
|
---|
388 | }
|
---|
389 | group.add(collection_tree);
|
---|
390 | collection_tree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
|
---|
391 | collection_tree.putClientProperty("JTree.lineStyle", "Angled");
|
---|
392 | collection_tree.addMouseListener(Gatherer.g_man.foa_listener);
|
---|
393 | collection_tree.addMouseListener(right_button_listener);
|
---|
394 | collection_tree.addTreeSelectionListener(this);
|
---|
395 | collection_tree.addTreeExpansionListener(Gatherer.g_man.foa_listener);
|
---|
396 | collection_tree.setLargeModel(true);
|
---|
397 | collection_tree.setRootVisible(false);
|
---|
398 |
|
---|
399 | JScrollPane collection_scroll = new JScrollPane(collection_tree);
|
---|
400 |
|
---|
401 | filter = Gatherer.g_man.getFilter(collection_tree);
|
---|
402 | filter.setBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
|
---|
403 | // Change the default colours of this filters combobox.
|
---|
404 | GComboBox fcb = filter.getComboBox();
|
---|
405 | fcb.setBackgroundNonSelectionColor(Gatherer.config.getColor("coloring.collection_tree_background", false));
|
---|
406 | fcb.setTextNonSelectionColor(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
|
---|
407 | fcb.setBackgroundSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
|
---|
408 | fcb.setTextSelectionColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
|
---|
409 | fcb = null;
|
---|
410 |
|
---|
411 | // Connection
|
---|
412 |
|
---|
413 | // Layout
|
---|
414 | collection_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(3,3,3,3), BorderFactory.createLoweredBevelBorder()));
|
---|
415 | collection_pane.setMinimumSize(MINIMUM_SIZE);
|
---|
416 | collection_pane.setPreferredSize(new Dimension(Gatherer.g_man.getSize().width / 3, Gatherer.g_man.getSize().height));
|
---|
417 |
|
---|
418 | // Collection Pane
|
---|
419 |
|
---|
420 | collection_pane.add(collection_label, BorderLayout.NORTH);
|
---|
421 | collection_pane.add(collection_scroll, BorderLayout.CENTER);
|
---|
422 | collection_pane.add(filter, BorderLayout.SOUTH);
|
---|
423 |
|
---|
424 | // Main pane
|
---|
425 | //main_pane = new JPanel(new BorderLayout());
|
---|
426 | //main_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
|
---|
427 |
|
---|
428 | main_split_pane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
|
---|
429 | main_split_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
|
---|
430 | main_split_pane.setDividerSize(8);
|
---|
431 |
|
---|
432 | // Thumbnail - Currently disabled.
|
---|
433 | // At least until I figure out how to render thumbnails off screen,
|
---|
434 | // which possibly may happen with the discovery of CalpaHTML.
|
---|
435 | /*
|
---|
436 | thumbnail_pane = new JPanel(new BorderLayout());
|
---|
437 |
|
---|
438 | gatherer.debug("\tCreating thumbnail_label");
|
---|
439 | thumbnail_label = new JLabel(get("Thumbnail"));
|
---|
440 | thumbnail_label.setHorizontalAlignment(JLabel.CENTER);
|
---|
441 |
|
---|
442 | gatherer.debug("\tCreating thumbnail_view_pane");
|
---|
443 | thumbnail_view_pane = new JPanel(new FlowLayout(FlowLayout.CENTER));
|
---|
444 | thumbnail_scroll = new JScrollPane(thumbnail_view_pane);
|
---|
445 |
|
---|
446 | thumbnail_pane.add(thumbnail_label, BorderLayout.NORTH);
|
---|
447 | thumbnail_pane.add(thumbnail_scroll, BorderLayout.CENTER);
|
---|
448 | */
|
---|
449 |
|
---|
450 | // Metadata Table. In order to achieve what Ian envisions I'm going
|
---|
451 | // to have to do a tricky. The table itself will sit in a stacked
|
---|
452 | // CardLayout. Card zero will be a see-through JPanel with a message
|
---|
453 | // smack bang in the center, something like "No Metadata". If any
|
---|
454 | // page of the table would appear to have no metadata this card will
|
---|
455 | // be swapped to the front.
|
---|
456 |
|
---|
457 | table_pane = new JPanel();
|
---|
458 | table_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
|
---|
459 |
|
---|
460 | JPanel table_title_pane = new JPanel();
|
---|
461 |
|
---|
462 | ///atherer.println("\tCreating metadata_label");
|
---|
463 | table_label = new JTextField(get("No_File"));
|
---|
464 | table_label.setBackground(Color.white);
|
---|
465 | table_label.setEditable(false);
|
---|
466 |
|
---|
467 | //activity_bar = new JProgressBar();
|
---|
468 | //activity_bar.setPreferredSize(LABEL_SIZE);
|
---|
469 | //activity_bar.setString(get("Ready"));
|
---|
470 | //activity_bar.setStringPainted(true);
|
---|
471 | //activity_bar.setValue(activity_bar.getMaximum());
|
---|
472 |
|
---|
473 | card_layout = new CardLayout();
|
---|
474 |
|
---|
475 | table_card_pane = new JPanel();
|
---|
476 |
|
---|
477 | JPanel table_pane_zero = new JPanel();
|
---|
478 | table_pane_zero.setOpaque(false);
|
---|
479 |
|
---|
480 | JPanel table_pane_two = new JPanel();
|
---|
481 | table_pane_two.setOpaque(false);
|
---|
482 |
|
---|
483 | JLabel no_file_message = new JLabel(get("No_File"));
|
---|
484 | no_file_message.setHorizontalAlignment(JLabel.CENTER);
|
---|
485 | no_file_message.setOpaque(false);
|
---|
486 | no_file_message.setVerticalAlignment(JLabel.CENTER);
|
---|
487 |
|
---|
488 | JLabel no_metadata_message = new JLabel(get("No_Metadata"));
|
---|
489 | no_metadata_message.setHorizontalAlignment(JLabel.CENTER);
|
---|
490 | no_metadata_message.setOpaque(false);
|
---|
491 | no_metadata_message.setVerticalAlignment(JLabel.CENTER);
|
---|
492 |
|
---|
493 | JPanel table_pane_one = new JPanel();
|
---|
494 |
|
---|
495 | //JPanel view_pane = new JPanel();
|
---|
496 |
|
---|
497 | //JLabel view_label = new JLabel(get("View"));
|
---|
498 | //view_label.setPreferredSize(LABEL_SIZE);
|
---|
499 |
|
---|
500 | //JPanel view_button_pane = new JPanel();
|
---|
501 |
|
---|
502 | //assigned_metadata_view = new JToggleButton(get("View_Assigned"), Utility.OFF_ICON);
|
---|
503 | //assigned_metadata_view.setSelectedIcon(Utility.ON_ICON);
|
---|
504 | //assigned_metadata_view.setSelected(true);
|
---|
505 | //assigned_metadata_view.addActionListener(this);
|
---|
506 | //unassigned_metadata_view = new JToggleButton(get("View_Unassigned"), Utility.OFF_ICON);
|
---|
507 | //unassigned_metadata_view.setSelectedIcon(Utility.ON_ICON);
|
---|
508 | //unassigned_metadata_view.setSelected(true);
|
---|
509 | //unassigned_metadata_view.addActionListener(this);
|
---|
510 | //XORToggleButtonGroup view_group = new XORToggleButtonGroup();
|
---|
511 | //view_group.add(assigned_metadata_view);
|
---|
512 | //view_group.add(unassigned_metadata_view);
|
---|
513 |
|
---|
514 | ///atherer.println("\tCreating metadata_table");
|
---|
515 | table = new JTable();
|
---|
516 | //model = new GTableModel(table, assigned_metadata_view, unassigned_metadata_view, activity_bar);
|
---|
517 | model = new GTableModel(table);
|
---|
518 | table.setModel(model);
|
---|
519 | table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
---|
520 | table.getSelectionModel().addListSelectionListener(this);
|
---|
521 | table.setColumnSelectionAllowed(false);
|
---|
522 |
|
---|
523 | // The default JTable doesn't quite have the desired properties - when a
|
---|
524 | // table cell is clicked on, the table is scrolled so the cell is as
|
---|
525 | // visible as possible. This means that the left-most cells can become
|
---|
526 | // hidden. To fix this, the MouseInputHandler in BasicTableUI is removed
|
---|
527 | // as a MouseListener on the table, and a very slightly altered copy is
|
---|
528 | // added in its place (TableMouseInputHandler).
|
---|
529 | MouseListener[] mls = table.getMouseListeners();
|
---|
530 | for (int i = 0; i < mls.length; i++) {
|
---|
531 | // Remove the instances of MouseInputHandler
|
---|
532 | if (mls[i].toString().startsWith("javax.swing.plaf.basic.BasicTableUI$MouseInputHandler@")) {
|
---|
533 | table.removeMouseListener(mls[i]);
|
---|
534 | }
|
---|
535 | }
|
---|
536 | // Add the slightly-altered mouse listener
|
---|
537 | table.addMouseListener(new TableMouseInputHandler());
|
---|
538 |
|
---|
539 | JScrollPane table_scroll = new JScrollPane(table);
|
---|
540 | table_scroll.getViewport().setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
|
---|
541 | table_scroll.setOpaque(true);
|
---|
542 |
|
---|
543 | // Control pane
|
---|
544 | ///atherer.println("\tCreating Metadata Controls");
|
---|
545 |
|
---|
546 | control_pane = new JPanel();
|
---|
547 | control_pane.setBorder(BorderFactory.createLoweredBevelBorder());
|
---|
548 | control_pane.setMinimumSize(MINIMUM_SIZE);
|
---|
549 | control_pane.setSize(CONTROL_SIZE);
|
---|
550 | control_pane.setPreferredSize(CONTROL_SIZE);
|
---|
551 |
|
---|
552 | card_layout2 = new CardLayout();
|
---|
553 |
|
---|
554 | JPanel tools_off_pane = new JPanel();
|
---|
555 |
|
---|
556 | JLabel tools_off_label = new JLabel(get("No_Metadata_Element"));
|
---|
557 | tools_off_label.setHorizontalAlignment(JLabel.CENTER);
|
---|
558 | tools_off_label.setOpaque(false);
|
---|
559 | tools_off_label.setVerticalAlignment(JLabel.CENTER);
|
---|
560 |
|
---|
561 | JPanel tools_on_pane = new JPanel();
|
---|
562 | tools_on_pane.setMinimumSize(MINIMUM_SIZE);
|
---|
563 | tools_on_pane.setSize(TABLE_SIZE);
|
---|
564 | tools_on_pane.setPreferredSize(TABLE_SIZE);
|
---|
565 |
|
---|
566 | // Layout.
|
---|
567 |
|
---|
568 | // Metaedit controls
|
---|
569 | tools_off_pane.setLayout(new BorderLayout());
|
---|
570 | tools_off_pane.add(tools_off_label, BorderLayout.CENTER);
|
---|
571 |
|
---|
572 | tools_on_pane.setLayout(new BorderLayout());
|
---|
573 | tools_on_pane.add(tree, BorderLayout.CENTER);
|
---|
574 |
|
---|
575 | control_pane.setLayout(card_layout2);
|
---|
576 | control_pane.add(tools_off_pane, TOOLS_OFF);
|
---|
577 | control_pane.add(tools_on_pane, TOOLS_ON);
|
---|
578 |
|
---|
579 | // Table components
|
---|
580 | table_title_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
|
---|
581 | table_title_pane.setLayout(new BorderLayout());
|
---|
582 | //table_title_pane.setLayout(new GridLayout(1,2,5,0));
|
---|
583 | table_title_pane.add(table_label, BorderLayout.CENTER);
|
---|
584 | //table_title_pane.add(activity_bar);
|
---|
585 |
|
---|
586 | table_pane_zero.setLayout(new BorderLayout());
|
---|
587 | table_pane_zero.add(no_file_message, BorderLayout.CENTER);
|
---|
588 |
|
---|
589 | table_pane_one.setLayout(new BorderLayout());
|
---|
590 | table_pane_one.add(table_scroll, BorderLayout.CENTER);
|
---|
591 |
|
---|
592 | table_pane_two.setLayout(new BorderLayout());
|
---|
593 | table_pane_two.add(no_metadata_message, BorderLayout.CENTER);
|
---|
594 |
|
---|
595 | table_card_pane.setLayout(card_layout);
|
---|
596 | table_card_pane.add(table_pane_zero, CARD_ZERO);
|
---|
597 | table_card_pane.add(table_pane_one, CARD_ONE);
|
---|
598 | table_card_pane.add(table_pane_two, CARD_TWO);
|
---|
599 | //view_button_pane.setLayout(new GridLayout(1,2,5,0));
|
---|
600 | //view_button_pane.add(assigned_metadata_view);
|
---|
601 | //view_button_pane.add(unassigned_metadata_view);
|
---|
602 |
|
---|
603 | //view_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
|
---|
604 | //view_pane.setLayout(new BorderLayout());
|
---|
605 | //view_pane.add(view_label, BorderLayout.WEST);
|
---|
606 | //view_pane.add(view_button_pane, BorderLayout.CENTER);
|
---|
607 |
|
---|
608 | table_pane.setLayout(new BorderLayout());
|
---|
609 | table_pane.add(table_title_pane, BorderLayout.NORTH);
|
---|
610 | table_pane.add(table_card_pane, BorderLayout.CENTER);
|
---|
611 | //table_pane.add(view_pane, BorderLayout.SOUTH);
|
---|
612 |
|
---|
613 | //main_split_pane.add(control_pane, JSplitPane.TOP);
|
---|
614 | //main_split_pane.add(table_pane, JSplitPane.BOTTOM);
|
---|
615 | main_split_pane.add(table_pane, JSplitPane.TOP);
|
---|
616 | main_split_pane.add(control_pane, JSplitPane.BOTTOM);
|
---|
617 | main_split_pane.setDividerLocation(250);
|
---|
618 |
|
---|
619 | external_split.add(collection_pane, JSplitPane.LEFT);//BorderLayout.WEST);
|
---|
620 | //this.add(main_pane, BorderLayout.CENTER);
|
---|
621 | external_split.add(main_split_pane, JSplitPane.RIGHT);//BorderLayout.CENTER);
|
---|
622 |
|
---|
623 | this.setLayout(new BorderLayout());
|
---|
624 | this.add(external_split, BorderLayout.CENTER);
|
---|
625 | }
|
---|
626 |
|
---|
627 | /** Method that is called whenever an element within a set is changed or modified. - needed for MSMListener
|
---|
628 | * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
|
---|
629 | */
|
---|
630 | public void elementChanged(MSMEvent event) {}
|
---|
631 |
|
---|
632 | /** Ensures a certain tree path is expanded, visible and selected within the collection tree.
|
---|
633 | * @param path The <strong>TreePath</strong> to make visible.
|
---|
634 | * @see org.greenstone.gatherer.tree.GTree
|
---|
635 | */
|
---|
636 | public void expandPath(TreePath path) {
|
---|
637 | collection_tree.expandPath(path);
|
---|
638 | collection_tree.setSelectionPath(path);
|
---|
639 | }
|
---|
640 | /** Called to inform this control panel that it has just gained focus as an effect of the user clicking on its tab.
|
---|
641 | * @see org.greenstone.gatherer.tree.GTree
|
---|
642 | */
|
---|
643 | public void gainFocus() {
|
---|
644 | // Use this opportunity to update the table model etc.
|
---|
645 | valueChanged(new TreeSelectionEvent(this, null, false, null, null));
|
---|
646 | // tree.setElementModel(Gatherer.c_man.getCollection().msm.getElementModel());
|
---|
647 | // Update the menubars idea of whats been selected
|
---|
648 | if(collection_tree != null) {
|
---|
649 | if(collection_tree.isSelectionEmpty()) {
|
---|
650 | Gatherer.g_man.menu_bar.setMetaAuditSuffix(null);
|
---|
651 | }
|
---|
652 | else {
|
---|
653 | Gatherer.g_man.menu_bar.setMetaAuditSuffix(collection_tree.getSelectionDetails());
|
---|
654 | }
|
---|
655 | }
|
---|
656 | // Update the meta-audit view to show the current selection, if any.
|
---|
657 | Gatherer.g_man.meta_audit.setRecords(records);
|
---|
658 | }
|
---|
659 | /** Used to determine if this class contains a reference to an existing file record that matches the presumtively new record, and if one is found, returns it. Note that there is no need to search the metadata table model, as any file record that exists there must also exist in the records selection.
|
---|
660 | * @param new_record The <strong>FileNode</strong> which may or may not be the first occurance of a certain record.
|
---|
661 | * @return The matching <strong>FileNode</strong> if there is one, or <i>null</i>.
|
---|
662 | */
|
---|
663 | public FileNode getAnyExistingRecord(FileNode new_record) {
|
---|
664 | FileNode match = null;
|
---|
665 | for(int i = 0; records != null && i < records.length && match == null; i++) {
|
---|
666 | if(records[i].equals(new_record)) {
|
---|
667 | match = records[i];
|
---|
668 | }
|
---|
669 | }
|
---|
670 | return match;
|
---|
671 | }
|
---|
672 |
|
---|
673 | /** Retrieve the currently selected records.
|
---|
674 | * @return A <strong>FileNode[]</strong> containing the current, and up to date, selection.
|
---|
675 | */
|
---|
676 | public FileNode[] getSelectedNode() {
|
---|
677 | return records;
|
---|
678 | }
|
---|
679 |
|
---|
680 | /** Retrieve the currently selected metadata.
|
---|
681 | * @return The <strong>Metadata</strong> in question.
|
---|
682 | */
|
---|
683 | public Metadata getSelectedMetadata() {
|
---|
684 | return selected_metadata;
|
---|
685 | }
|
---|
686 |
|
---|
687 | /** Called whenever the metadata value changes in some way, such as the addition of a new value. - needed for MSMListener
|
---|
688 | * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
|
---|
689 | */
|
---|
690 | public void metadataChanged(MSMEvent event) {}
|
---|
691 |
|
---|
692 | /** Method that is called whenever the metadata set collection changes in some way, such as the addition of a new set or the merging of two sets. - needed for MSMListener
|
---|
693 | * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
|
---|
694 | */
|
---|
695 | public void setChanged(MSMEvent event){
|
---|
696 | // call the collection tree value changed - we need to do the same stuff here
|
---|
697 | valueChanged((TreeSelectionEvent) null);
|
---|
698 |
|
---|
699 | }
|
---|
700 |
|
---|
701 | public void setSelection(File file) {
|
---|
702 | collection_tree.setSelection(file);
|
---|
703 | }
|
---|
704 |
|
---|
705 | /** Determine the bounds of the selected metadata within the table, used during search and replace actions.
|
---|
706 | * @param metadata The <strong>Metadata</strong> to search for.
|
---|
707 | */
|
---|
708 | public Rectangle setSelectedMetadata(Metadata metadata) {
|
---|
709 | return model.setSelectedMetadata(metadata);
|
---|
710 | }
|
---|
711 |
|
---|
712 | public void refreshTrees() {
|
---|
713 | collection_tree.refresh(null); // Refresh entire tree.
|
---|
714 | }
|
---|
715 |
|
---|
716 | /* Called when nodes have been modified, but the model hasn't changed.
|
---|
717 | * @param event Everything you ever wanted to know about model changes in one tidy <strong>TreeModelEvent</strong> package.
|
---|
718 | */
|
---|
719 | public void treeNodesChanged(TreeModelEvent event) {
|
---|
720 | has_changed = true;
|
---|
721 | }
|
---|
722 |
|
---|
723 | /* Called when nodes have been added to the model.
|
---|
724 | * @param event Everything you ever wanted to know about model changes in one tidy <strong>TreeModelEvent</strong> package.
|
---|
725 | */
|
---|
726 | public void treeNodesInserted(TreeModelEvent event) {
|
---|
727 | has_changed = true;
|
---|
728 | }
|
---|
729 |
|
---|
730 | /* Called when nodes have been removed from the model.
|
---|
731 | * @param event Everything you ever wanted to know about model changes in one tidy <strong>TreeModelEvent</strong> package.
|
---|
732 | */
|
---|
733 | public void treeNodesRemoved(TreeModelEvent event) {
|
---|
734 | has_changed = true;
|
---|
735 | }
|
---|
736 |
|
---|
737 | /** Called when nodes have been rearranged within the model.
|
---|
738 | * @param event Everything you ever wanted to know about model changes in one tidy <strong>TreeModelEvent</strong> package.
|
---|
739 | */
|
---|
740 | public void treeStructureChanged(TreeModelEvent event) {
|
---|
741 | has_changed = true;
|
---|
742 | }
|
---|
743 | /** Called to ensure that if the tree model has changed in some way, the view has been updated.
|
---|
744 | * @see org.greenstone.gatherer.tree.GTree
|
---|
745 | */
|
---|
746 | public void updateTree() {
|
---|
747 | if(has_changed) {
|
---|
748 | tree.updateUI();
|
---|
749 | has_changed = false;
|
---|
750 | }
|
---|
751 | }
|
---|
752 |
|
---|
753 | /** This method enables or diables the various controls based upon the state of the system. This method should be called after every change which could affect the GUI.
|
---|
754 | */
|
---|
755 | public void validateControls() {
|
---|
756 | validateControls(true);
|
---|
757 | }
|
---|
758 | public void validateControls(boolean and_tree) {
|
---|
759 | validateMetadataTable();
|
---|
760 | // Validate card_layout_2
|
---|
761 | if (selected_metadata != null) {
|
---|
762 | card_layout2.show(control_pane, TOOLS_ON);
|
---|
763 | }
|
---|
764 | else {
|
---|
765 | card_layout2.show(control_pane, TOOLS_OFF);
|
---|
766 | }
|
---|
767 | if(and_tree) {
|
---|
768 | // Validate the buttons in the lower pane
|
---|
769 | if (selected_metadata == null) {
|
---|
770 | // Nothing selected
|
---|
771 | return;
|
---|
772 | }
|
---|
773 |
|
---|
774 | // Does the metadata element have no current value?
|
---|
775 | GValueNode value_node = selected_metadata.getValueNode();
|
---|
776 | if (value_node == null) {
|
---|
777 | // Can only append if something has been entered
|
---|
778 | add.setEnabled((tree.getSelectedValue().length() > 0));
|
---|
779 | // Nothing to replace or remove
|
---|
780 | update.setEnabled(false);
|
---|
781 | remove.setEnabled(false);
|
---|
782 | }
|
---|
783 |
|
---|
784 | else {
|
---|
785 | // Check if the text in the value field is the same as the metadata value
|
---|
786 | if (tree.getSelectedValue().equals(value_node.getFullPath())) {
|
---|
787 | // Can't append or replace
|
---|
788 | add.setEnabled(false);
|
---|
789 | update.setEnabled(false);
|
---|
790 | }
|
---|
791 | else {
|
---|
792 | // Can append or replace
|
---|
793 | add.setEnabled(true);
|
---|
794 | update.setEnabled(true);
|
---|
795 | }
|
---|
796 |
|
---|
797 | // Can only remove if the metadata is file level
|
---|
798 | remove.setEnabled(selected_metadata.isFileLevel());
|
---|
799 | }
|
---|
800 | }
|
---|
801 | }
|
---|
802 |
|
---|
803 | /** Validate the metadata table area, and if no metadata is available display the no metadata panel. */
|
---|
804 | public void validateMetadataTable() {
|
---|
805 | // Validate card_layout
|
---|
806 | if (records == null) {
|
---|
807 | card_layout.show(table_card_pane, CARD_ZERO);
|
---|
808 | } else if (model.getRowCount() == 0) {
|
---|
809 | card_layout.show(table_card_pane, CARD_TWO);
|
---|
810 | } else {
|
---|
811 | card_layout.show(table_card_pane, CARD_ONE);
|
---|
812 | }
|
---|
813 | /*
|
---|
814 | if(records != null && model.getRowCount() > 0) {
|
---|
815 | card_layout.show(table_card_pane, CARD_ONE);
|
---|
816 | }
|
---|
817 | else {
|
---|
818 | card_layout.show(table_card_pane, CARD_ZERO);
|
---|
819 | }*/
|
---|
820 | }
|
---|
821 |
|
---|
822 | /** Another in a long list of listeners, this one is called whenever the
|
---|
823 | * selection within the JTable changes. When it does we load the new data
|
---|
824 | * and set the selected_metadata if applicable (ie the metadata is non-
|
---|
825 | * empty).
|
---|
826 | * @param event The <strong>ListSelectionEvent</strong> which contains all the information about the event that has been fired.
|
---|
827 | * @see org.greenstone.gatherer.gui.table.GTableModel
|
---|
828 | * @see org.greenstone.gatherer.valuetree.GValueTree
|
---|
829 | */
|
---|
830 | public void valueChanged(ListSelectionEvent event) {
|
---|
831 | // We only want to handle one event per selection, so wait for the value to stabilise
|
---|
832 | ListSelectionModel lsm = table.getSelectionModel();
|
---|
833 | if (lsm.getValueIsAdjusting() == false) {
|
---|
834 | // We have a SINGLE_SELECTION model set so there is at most one
|
---|
835 | // selection. Get the offending row.
|
---|
836 | int selected = table.getSelectedRow();
|
---|
837 | selected_metadata = model.getMetadataAtRow(selected);
|
---|
838 | if(selected_metadata != null) { // Check something is selected.
|
---|
839 | tree.setSelectedMetadataElement(selected_metadata.getElement());
|
---|
840 | GValueNode value_node = selected_metadata.getValueNode();
|
---|
841 | if(value_node != null) {
|
---|
842 | tree.setSelectedValue(value_node.getFullPath());
|
---|
843 | }
|
---|
844 | else {
|
---|
845 | tree.setSelectedValue("");
|
---|
846 | }
|
---|
847 | }
|
---|
848 | validateControls(true);
|
---|
849 | }
|
---|
850 | }
|
---|
851 |
|
---|
852 | /** Called whenever the value tree of an metadata element changes in some way, such as the addition of a new value. - needed for MSMListener
|
---|
853 | * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
|
---|
854 | */
|
---|
855 | public void valueChanged(MSMEvent event) {}
|
---|
856 |
|
---|
857 | /** This method is called whenever the selection within the collection
|
---|
858 | * tree changes. This causes the table to be rebuilt with a new model
|
---|
859 | * @param event A <strong>TreeSelectionEvent</strong> containing information about the event.
|
---|
860 | * @see org.greenstone.gatherer.Gatherer
|
---|
861 | * @see org.greenstone.gatherer.collection.FileNode
|
---|
862 | * @see org.greenstone.gatherer.gui.GUIManager
|
---|
863 | * @see org.greenstone.gatherer.gui.MenuBar
|
---|
864 | * @see org.greenstone.gatherer.gui.table.GTableModel
|
---|
865 | * @see org.greenstone.gatherer.msm.MetadataSetManager
|
---|
866 | * @see org.greenstone.gatherer.tree.GTree
|
---|
867 | * @see org.greenstone.gatherer.util.ArrayTools
|
---|
868 | */
|
---|
869 | public void valueChanged(TreeSelectionEvent event) {
|
---|
870 | // System.err.println("\n(MEP) valueChanged(TreeSelectionEvent)...");
|
---|
871 |
|
---|
872 | // Don't bother if this isn't the selected view
|
---|
873 | if (Gatherer.g_man.getSelectedView() != this) {
|
---|
874 | return;
|
---|
875 | }
|
---|
876 |
|
---|
877 | if(collection_tree.getSelectionCount() > 0) {
|
---|
878 | records = null;
|
---|
879 | TreePath paths[] = collection_tree.getSelectionPaths();
|
---|
880 | for(int i = 0; i < paths.length; i++) {
|
---|
881 | FileNode record = (FileNode) paths[i].getLastPathComponent();
|
---|
882 | records = ArrayTools.add(records, record);
|
---|
883 | }
|
---|
884 |
|
---|
885 | table_label.setText(collection_tree.getSelectionDetails());
|
---|
886 |
|
---|
887 | // Remove old model from msm
|
---|
888 | Gatherer.c_man.getCollection().msm.removeMSMListener(model);
|
---|
889 | // Create new model
|
---|
890 | model = new GTableModel(table, records);
|
---|
891 | table.setModel(model);
|
---|
892 | }
|
---|
893 | else {
|
---|
894 | records = null;
|
---|
895 | table_label.setText(get("No_File"));
|
---|
896 | // Remove old model from msm
|
---|
897 | if(Gatherer.c_man.ready()) {
|
---|
898 | Gatherer.c_man.getCollection().msm.removeMSMListener(model);
|
---|
899 | }
|
---|
900 | // Create new model
|
---|
901 | model = new GTableModel(table);
|
---|
902 | table.setModel(model);
|
---|
903 | }
|
---|
904 |
|
---|
905 | table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
|
---|
906 | if(table != null) {
|
---|
907 | Dimension table_size = table.getPreferredSize();
|
---|
908 | TableColumnModel column_model = table.getColumnModel();
|
---|
909 |
|
---|
910 | TableColumn inherited_column = column_model.getColumn(0);
|
---|
911 | inherited_column.setPreferredWidth(20);
|
---|
912 | inherited_column.setCellRenderer(new TableCellRenderer(model));
|
---|
913 |
|
---|
914 | TableColumn element_column = column_model.getColumn(1);
|
---|
915 | element_column.setPreferredWidth(TABLE_SIZE.width / 4);
|
---|
916 | element_column.setCellRenderer(new TableCellRenderer(model));
|
---|
917 |
|
---|
918 | TableColumn value_column = column_model.getColumn(2);
|
---|
919 | value_column.setPreferredWidth(((3 * TABLE_SIZE.width) / 4) - 15);
|
---|
920 | value_column.setCellRenderer(new TableCellRenderer(model));
|
---|
921 | }
|
---|
922 | table.doLayout();
|
---|
923 | validateControls();
|
---|
924 | }
|
---|
925 |
|
---|
926 |
|
---|
927 | /** Retrieve a phrase from the Dictionary based on the given key.
|
---|
928 | * @param key The <strong>String</strong> which maps to the phrase to retrieve.
|
---|
929 | * @return The desired phrase as a <strong>String</strong>, or possibly an error message if no such phrase exists.
|
---|
930 | */
|
---|
931 | private String get(String key) {
|
---|
932 | return get(key, null);
|
---|
933 | }
|
---|
934 | /** Retrieve a phrase from the Dictionary based on the given key and filled in with the given arguments.
|
---|
935 | * @param key The <strong>String</strong> which maps to the phrase to retrieve.
|
---|
936 | * @param args A <strong>String[]</strong> of arguments to be inserted in the phrase.
|
---|
937 | * @return The desired phrase as a <strong>String</strong>, or possibly an error message if no such phrase exists.
|
---|
938 | * @see org.greenstone.gatherer.Dictionary
|
---|
939 | * @see org.greenstone.gatherer.Gatherer
|
---|
940 | */
|
---|
941 | private String get(String key, String args[]) {
|
---|
942 | if(key.indexOf('.') == -1) {
|
---|
943 | key = "MetaEdit." + key;
|
---|
944 | }
|
---|
945 | return Gatherer.dictionary.get(key,args);
|
---|
946 | }
|
---|
947 |
|
---|
948 |
|
---|
949 | /** A direct copy of javax.swing.plaf.basic.BasicTableUI$MouseInputHandler, except for one change in adjustFocusAndSelection(). The purpose of this change is to always keep the left-most cells of the table row selected visible. */
|
---|
950 | private class TableMouseInputHandler implements MouseInputListener
|
---|
951 | {
|
---|
952 | // Component receiving mouse events during editing.
|
---|
953 | // May not be editorComponent.
|
---|
954 | private Component dispatchComponent;
|
---|
955 | private boolean selectedOnPress;
|
---|
956 |
|
---|
957 | // The Table's mouse listener methods.
|
---|
958 |
|
---|
959 | public void mouseClicked(MouseEvent e) {}
|
---|
960 |
|
---|
961 | private void setDispatchComponent(MouseEvent e) {
|
---|
962 | Component editorComponent = table.getEditorComponent();
|
---|
963 | Point p = e.getPoint();
|
---|
964 | Point p2 = SwingUtilities.convertPoint(table, p, editorComponent);
|
---|
965 | dispatchComponent = SwingUtilities.getDeepestComponentAt(editorComponent,
|
---|
966 | p2.x, p2.y);
|
---|
967 | }
|
---|
968 |
|
---|
969 | private boolean repostEvent(MouseEvent e) {
|
---|
970 | // Check for isEditing() in case another event has
|
---|
971 | // caused the editor to be removed. See bug #4306499.
|
---|
972 | if (dispatchComponent == null || !table.isEditing()) {
|
---|
973 | return false;
|
---|
974 | }
|
---|
975 | MouseEvent e2 = SwingUtilities.convertMouseEvent(table, e, dispatchComponent);
|
---|
976 | dispatchComponent.dispatchEvent(e2);
|
---|
977 | return true;
|
---|
978 | }
|
---|
979 |
|
---|
980 | private void setValueIsAdjusting(boolean flag) {
|
---|
981 | table.getSelectionModel().setValueIsAdjusting(flag);
|
---|
982 | table.getColumnModel().getSelectionModel().setValueIsAdjusting(flag);
|
---|
983 | }
|
---|
984 |
|
---|
985 | private boolean shouldIgnore(MouseEvent e) {
|
---|
986 | return e.isConsumed() || (!(SwingUtilities.isLeftMouseButton(e) && table.isEnabled()));
|
---|
987 | }
|
---|
988 |
|
---|
989 | public void mousePressed(MouseEvent e) {
|
---|
990 | if (e.isConsumed()) {
|
---|
991 | selectedOnPress = false;
|
---|
992 | return;
|
---|
993 | }
|
---|
994 | selectedOnPress = true;
|
---|
995 | adjustFocusAndSelection(e);
|
---|
996 | }
|
---|
997 |
|
---|
998 | void adjustFocusAndSelection(MouseEvent e) {
|
---|
999 | if (shouldIgnore(e)) {
|
---|
1000 | return;
|
---|
1001 | }
|
---|
1002 |
|
---|
1003 | Point p = e.getPoint();
|
---|
1004 | int row = table.rowAtPoint(p);
|
---|
1005 | int column = table.columnAtPoint(p);
|
---|
1006 | // The autoscroller can generate drag events outside the Table's range.
|
---|
1007 | if ((column == -1) || (row == -1)) {
|
---|
1008 | return;
|
---|
1009 | }
|
---|
1010 |
|
---|
1011 | if (table.editCellAt(row, column, e)) {
|
---|
1012 | setDispatchComponent(e);
|
---|
1013 | repostEvent(e);
|
---|
1014 | }
|
---|
1015 | else if (table.isRequestFocusEnabled()) {
|
---|
1016 | table.requestFocus();
|
---|
1017 | }
|
---|
1018 |
|
---|
1019 | CellEditor editor = table.getCellEditor();
|
---|
1020 | if (editor == null || editor.shouldSelectCell(e)) {
|
---|
1021 | boolean adjusting = (e.getID() == MouseEvent.MOUSE_PRESSED) ? true : false;
|
---|
1022 | setValueIsAdjusting(adjusting);
|
---|
1023 | if (column == 0) {
|
---|
1024 | table.changeSelection(row, 0, e.isControlDown(), e.isShiftDown());
|
---|
1025 | }
|
---|
1026 | else {
|
---|
1027 | table.changeSelection(row, 1, e.isControlDown(), e.isShiftDown());
|
---|
1028 | }
|
---|
1029 | // table.changeSelection(row, column, e.isControlDown(), e.isShiftDown());
|
---|
1030 | }
|
---|
1031 | }
|
---|
1032 |
|
---|
1033 | public void mouseReleased(MouseEvent e) {
|
---|
1034 | if (selectedOnPress) {
|
---|
1035 | if (shouldIgnore(e)) {
|
---|
1036 | return;
|
---|
1037 | }
|
---|
1038 |
|
---|
1039 | repostEvent(e);
|
---|
1040 | dispatchComponent = null;
|
---|
1041 | setValueIsAdjusting(false);
|
---|
1042 | } else {
|
---|
1043 | adjustFocusAndSelection(e);
|
---|
1044 | }
|
---|
1045 | }
|
---|
1046 |
|
---|
1047 |
|
---|
1048 | public void mouseEntered(MouseEvent e) {}
|
---|
1049 |
|
---|
1050 | public void mouseExited(MouseEvent e) {}
|
---|
1051 |
|
---|
1052 | // The Table's mouse motion listener methods.
|
---|
1053 |
|
---|
1054 | public void mouseMoved(MouseEvent e) {}
|
---|
1055 |
|
---|
1056 | public void mouseDragged(MouseEvent e) {
|
---|
1057 | if (shouldIgnore(e)) {
|
---|
1058 | return;
|
---|
1059 | }
|
---|
1060 |
|
---|
1061 | repostEvent(e);
|
---|
1062 |
|
---|
1063 | CellEditor editor = table.getCellEditor();
|
---|
1064 | if (editor == null || editor.shouldSelectCell(e)) {
|
---|
1065 | Point p = e.getPoint();
|
---|
1066 | int row = table.rowAtPoint(p);
|
---|
1067 | int column = table.columnAtPoint(p);
|
---|
1068 | // The autoscroller can generate drag events outside the Table's range.
|
---|
1069 | if ((column == -1) || (row == -1)) {
|
---|
1070 | return;
|
---|
1071 | }
|
---|
1072 | table.changeSelection(row, column, false, true);
|
---|
1073 | }
|
---|
1074 | }
|
---|
1075 | }
|
---|
1076 |
|
---|
1077 |
|
---|
1078 | /** A listener for right mouse button clicks over the collection tree. */
|
---|
1079 | private class RightButtonListener
|
---|
1080 | extends MouseAdapter {
|
---|
1081 | /** Called whenever a mouse click occurs (right or left) over a target component.
|
---|
1082 | * @param event A <strong>MouseEvent</strong> containing further information about the mouse click action.
|
---|
1083 | * @see org.greenstone.gatherer.gui.MetaEditPane.RightButtonMenu
|
---|
1084 | */
|
---|
1085 | public void mouseClicked(MouseEvent event) {
|
---|
1086 | if(SwingUtilities.isRightMouseButton(event)) {
|
---|
1087 | new RightButtonMenu(event);
|
---|
1088 | }
|
---|
1089 | }
|
---|
1090 | }
|
---|
1091 | /** Provides a popup menu to display when a right mouse button click is detected over the collection tree. */
|
---|
1092 | private class RightButtonMenu
|
---|
1093 | extends JPopupMenu
|
---|
1094 | implements ActionListener {
|
---|
1095 | /** Constructor.
|
---|
1096 | * @param event The <strong>MouseEvent</strong> that triggered the creation of this menu. Used to determine where the menu will be located.
|
---|
1097 | */
|
---|
1098 | public RightButtonMenu(MouseEvent event) {
|
---|
1099 | super();
|
---|
1100 | // Creation
|
---|
1101 | JMenuItem show_metaaudit = new JMenuItem(get("Menu.Metadata_View") + " " + collection_tree.getSelectionDetails(), KeyEvent.VK_V);
|
---|
1102 | show_metaaudit.addActionListener(this);
|
---|
1103 | add(show_metaaudit);
|
---|
1104 | // Display
|
---|
1105 | show(collection_tree, event.getX(), event.getY());
|
---|
1106 | show_metaaudit = null;
|
---|
1107 | args = null;
|
---|
1108 |
|
---|
1109 | }
|
---|
1110 | /** Called whenever a user clicks on the single menu item, view all assigned metadata.
|
---|
1111 | * @param event An <strong>ActionEvent</strong> containing further information about the action.
|
---|
1112 | * @see org.greenstone.gatherer.Gatherer
|
---|
1113 | * @see org.greenstone.gatherer.gui.GUIManager
|
---|
1114 | */
|
---|
1115 | public void actionPerformed(ActionEvent event) {
|
---|
1116 | Gatherer.g_man.showMetaAuditBox();
|
---|
1117 | }
|
---|
1118 | }
|
---|
1119 |
|
---|
1120 | }
|
---|