Changeset 5176


Ignore:
Timestamp:
2003-08-18T15:20:16+12:00 (21 years ago)
Author:
mdewsnip
Message:

Tidied up this class, and moved GValueTree into it.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/gli/src/org/greenstone/gatherer/gui/MetaEditPane.java

    r4686 r5176  
    4747import org.greenstone.gatherer.Gatherer;
    4848import org.greenstone.gatherer.file.FileNode;
    49 import org.greenstone.gatherer.file.FileOpenActionListener;
    5049import org.greenstone.gatherer.gui.Filter;
    5150import org.greenstone.gatherer.gui.GComboBox;
     
    6362import org.greenstone.gatherer.util.TreeSynchronizer;
    6463import org.greenstone.gatherer.util.Utility;
    65 import org.greenstone.gatherer.util.XORToggleButtonGroup;
    66 import org.greenstone.gatherer.valuetree.GValueTree;
    6764import org.greenstone.gatherer.valuetree.GValueModel;
    6865import org.greenstone.gatherer.valuetree.GValueNode;
    69 import org.w3c.dom.Element;
    7066/** 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).
    7167* @author John Thompson, Greenstone Digital Libraries, University of Waikato
     
    7470public class MetaEditPane
    7571    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;
     72    implements ActionListener, ListSelectionListener, TreeSelectionListener, MSMListener {
    7973    /** 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;
     74    private GValueTree tree = null;
    8375    /** The layout manager used to display either the GTable (when records are selected) or a placeholder panel with the immortal words 'No Record Selected'. */
    8476    private CardLayout card_layout = null;
     
    9183    /** 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. */
    9284    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;
    9785    /** The button, which when clicked, adds metadata to the selected records. */
    9886    private JButton add;
    9987    /** The button, which when clicked, removes the selected metadata from the selected records. */
    10088    private JButton remove;
    101     /** The button, which when clicked, changes the currently shown GTable view. */
    102     //private JButton table_view;
    10389    /** The button, which when clicked, updates the selected metadata from the selected records. */
    10490    private JButton update;
     
    11197    /** The panel in which the metadata table card layout resides. */
    11298    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;
    11799    /** The splitpane dividing the collection tree and the metadata based controls. */
    118100    private JSplitPane external_split;
    119     /** Divides the metadata table and the value tree controls. */
    120     private JSplitPane main_split_pane;
    121101    /** A reference to the metadata table, via its superclass. */
    122102    private JTable table;
    123103    /** The label shown at the top of the metadata table detailing the current selection statistics. */
    124104    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;
    129105    /** A reference to the collection tree. */
    130     public DragTree collection_tree;
     106    private DragTree collection_tree;
    131107    /** The currently selected metadata determined by listening to every second list selection event from the metadata table. */
    132108    private Metadata selected_metadata;
    133     /** Listens for right clicks over the collection tree. */
    134     private RightButtonListener right_button_listener = null;
    135109    /** A temporary storage array from Strings passed to the dictionary to be inserted in the phrase returned. */
    136110    private String args[];
    137111    /** Provide synchronization between the collection trees in this view and the collection pane view. */
    138112    private TreeSynchronizer tree_sync = null;
    139     static public Dimension BUTTON_SIZE = new Dimension(190, 25);
     113    static private Dimension BUTTON_SIZE = new Dimension(190, 25);
    140114    static private Dimension CONTROL_SIZE = new Dimension(560, 240);
    141     static private Dimension LABEL_SIZE = new Dimension(75, 25);
    142115    static private Dimension MINIMUM_SIZE = new Dimension(100, 100);
    143116    static private Dimension TABLE_SIZE = new Dimension(560, 25);
    144117    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;
    149118    /** The name of the panel containing the metadata table. */
    150119    static final private String CARD_ONE  = "Card One";
     
    157126    /** The name of the panel containing the value tree. */
    158127    static final private String TOOLS_ON  = "Tools On";
     128
    159129    /** Constructor.
    160130     * @param tree_sync The <strong>TreeSynchronizer</strong> to be used on the collection tree.
     
    164134     */
    165135    public MetaEditPane(TreeSynchronizer tree_sync) {
    166     //this.current_table_view = GTableModel.SHOW_FILE;
    167136    this.tree = null;
    168137    this.tree_sync = tree_sync;
     
    192161    expand.setPreferredSize(new Dimension(25, 25));
    193162
    194     tree = new GValueTree(this, CONTROL_SIZE.width, CONTROL_SIZE.height, add, update, remove, expand);
    195     }
     163    tree = new GValueTree(this, CONTROL_SIZE.width, CONTROL_SIZE.height);
     164    }
     165
    196166    /** 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     */
     167     * @param event An <strong>ActionEvent</strong> containing information about the event.
     168     * @see org.greenstone.gatherer.collection.CollectionManager
     169     * @see org.greenstone.gatherer.gui.table.GTableModel
     170     * @see org.greenstone.gatherer.msm.ElementWrapper
     171     * @see org.greenstone.gatherer.msm.MetadataSetManager
     172     * @see org.greenstone.gatherer.msm.MSMEvent
     173     * @see org.greenstone.gatherer.valuetree.GValueTree
     174     */
    205175    public void actionPerformed(ActionEvent event) {
    206176    Object esrc = event.getSource();
     
    221191        }
    222192    }
    223     //else if(esrc == assigned_metadata_view || esrc == unassigned_metadata_view) {
    224     //  model.changeView();
    225     //}
    226193    validateControls();
    227194    }
     
    230197    extends Thread {
    231198
    232     public AppendMetadataTask() { }
     199    private AppendMetadataTask() { }
    233200
    234201    public void run() {
     
    259226    extends Thread {
    260227
    261     public UpdateMetadataTask() { }
     228    private UpdateMetadataTask() { }
    262229
    263230    public void run() {
     
    276243    extends Thread {
    277244
    278     public RemoveMetadataTask() { }
     245    private RemoveMetadataTask() { }
    279246
    280247    public void run() {
     
    289256
    290257    /** 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.
    291     * @see org.greenstone.gatherer.gui.table.GTableModel
    292     */
     258     * @see org.greenstone.gatherer.gui.table.GTableModel
     259     */
    293260    public void afterDisplay() {
    294261    external_split.setDividerLocation(0.3);
     
    313280    }
    314281    /** Called whenever a significant change has occured in the state of the currently loaded collection.
    315     * @param ready <i>true</i> if there is a collection currently ready to be editing, <i>false</i> otherwise.
    316     * @see org.greenstone.gatherer.collection.CollectionManager
    317     * @see org.greenstone.gatherer.collection.CollectionModel
    318     * @see org.greenstone.gatherer.tree.GTree
    319     * @see org.greenstone.gatherer.util.TreeSynchronizer
    320     */
     282     * @param ready <i>true</i> if there is a collection currently ready to be editing, <i>false</i> otherwise.
     283     * @see org.greenstone.gatherer.collection.CollectionManager
     284     * @see org.greenstone.gatherer.collection.CollectionModel
     285     * @see org.greenstone.gatherer.tree.GTree
     286     * @see org.greenstone.gatherer.util.TreeSynchronizer
     287     */
    321288    public void collectionChanged(boolean ready) {
    322289    if(ready) {
     
    325292        args[0] = Gatherer.c_man.getCollection().getName();
    326293        collection_label.setText(get("Collection.Collection", args));
    327                 // Update label coloring.
     294        // Update label coloring.
    328295        collection_label.setBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
    329296        collection_label.setForeground(Gatherer.config.getColor("coloring.collection_heading_foreground", false));
    330297        collection_tree.setModel(collection_model);
    331                 // Update tree coloring.
     298        // Update tree coloring.
    332299        collection_tree.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
    333300        collection_tree.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
     
    354321    }
    355322    /** Used to create, connect and layout the components to be shown on this control panel.
    356     * @see org.greenstone.gatherer.Gatherer
    357     * @see org.greenstone.gatherer.collection.CollectionManager
    358     * @see org.greenstone.gatherer.collection.CollectionModel
    359     * @see org.greenstone.gatherer.file.FileOpenActionListener
    360     * @see org.greenstone.gatherer.gui.Filter
    361     * @see org.greenstone.gatherer.gui.GComboBox
    362     * @see org.greenstone.gatherer.gui.table.GTableModel
    363     * @see org.greenstone.gatherer.tree.GTree
    364     * @see org.greenstone.gatherer.tree.GTreeModel
    365     * @see org.greenstone.gatherer.valuetree.GValueTree
    366     */
     323     * @see org.greenstone.gatherer.Gatherer
     324     * @see org.greenstone.gatherer.collection.CollectionManager
     325     * @see org.greenstone.gatherer.collection.CollectionModel
     326     * @see org.greenstone.gatherer.file.FileOpenActionListener
     327     * @see org.greenstone.gatherer.gui.Filter
     328     * @see org.greenstone.gatherer.gui.GComboBox
     329     * @see org.greenstone.gatherer.gui.table.GTableModel
     330     * @see org.greenstone.gatherer.tree.GTree
     331     * @see org.greenstone.gatherer.tree.GTreeModel
     332     * @see org.greenstone.gatherer.valuetree.GValueTree
     333     */
    367334    public void display() {
    368     right_button_listener = new RightButtonListener();
     335    RightButtonListener right_button_listener = new RightButtonListener();
    369336    // Creation
    370337    JPanel collection_pane = new JPanel(new BorderLayout());
     
    385352    if(collection_model != null) {
    386353        collection_tree = new DragTree("MetaEdit", collection_model, null, false);
    387         collection_model.addTreeModelListener(this);
    388354    }
    389355    else {
     
    425391    collection_pane.add(filter, BorderLayout.SOUTH);
    426392
    427     // Main pane
    428     //main_pane = new JPanel(new BorderLayout());
    429     //main_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
    430 
    431     main_split_pane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
     393    JSplitPane main_split_pane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
    432394    main_split_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
    433395    main_split_pane.setDividerSize(8);
     
    458420    // be swapped to the front.
    459421
    460     table_pane = new JPanel();
     422    JPanel table_pane = new JPanel();
    461423    table_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
    462424
     
    467429    table_label.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
    468430    table_label.setEditable(false);
    469 
    470     //activity_bar = new JProgressBar();
    471     //activity_bar.setPreferredSize(LABEL_SIZE);
    472     //activity_bar.setString(get("Ready"));
    473     //activity_bar.setStringPainted(true);
    474     //activity_bar.setValue(activity_bar.getMaximum());
    475431
    476432    card_layout = new CardLayout();
     
    495451
    496452    JPanel table_pane_one = new JPanel();
    497 
    498     //JPanel view_pane = new JPanel();
    499 
    500     //JLabel view_label = new JLabel(get("View"));
    501     //view_label.setPreferredSize(LABEL_SIZE);
    502 
    503     //JPanel view_button_pane = new JPanel();
    504 
    505     //assigned_metadata_view = new JToggleButton(get("View_Assigned"), Utility.OFF_ICON);
    506     //assigned_metadata_view.setSelectedIcon(Utility.ON_ICON);
    507     //assigned_metadata_view.setSelected(true);
    508     //assigned_metadata_view.addActionListener(this);
    509     //unassigned_metadata_view = new JToggleButton(get("View_Unassigned"), Utility.OFF_ICON);
    510     //unassigned_metadata_view.setSelectedIcon(Utility.ON_ICON);
    511     //unassigned_metadata_view.setSelected(true);
    512     //unassigned_metadata_view.addActionListener(this);
    513     //XORToggleButtonGroup view_group = new XORToggleButtonGroup();
    514     //view_group.add(assigned_metadata_view);
    515     //view_group.add(unassigned_metadata_view);
    516453
    517454    ///atherer.println("\tCreating metadata_table");
     
    584521    //table_title_pane.setLayout(new GridLayout(1,2,5,0));
    585522    table_title_pane.add(table_label, BorderLayout.CENTER);
    586     //table_title_pane.add(activity_bar);
    587523
    588524    table_pane_zero.setLayout(new BorderLayout());
     
    599535    table_card_pane.add(table_pane_one, CARD_ONE);
    600536    table_card_pane.add(table_pane_two, CARD_TWO);
    601     //view_button_pane.setLayout(new GridLayout(1,2,5,0));
    602     //view_button_pane.add(assigned_metadata_view);
    603     //view_button_pane.add(unassigned_metadata_view);
    604 
    605     //view_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
    606     //view_pane.setLayout(new BorderLayout());
    607     //view_pane.add(view_label, BorderLayout.WEST);
    608     //view_pane.add(view_button_pane, BorderLayout.CENTER);
    609537
    610538    table_pane.setLayout(new BorderLayout());
    611539    table_pane.add(table_title_pane, BorderLayout.NORTH);
    612540    table_pane.add(table_card_pane, BorderLayout.CENTER);
    613     //table_pane.add(view_pane, BorderLayout.SOUTH);
    614 
    615     //main_split_pane.add(control_pane, JSplitPane.TOP);
    616     //main_split_pane.add(table_pane, JSplitPane.BOTTOM);
     541
    617542    main_split_pane.add(table_pane, JSplitPane.TOP);
    618543    main_split_pane.add(control_pane, JSplitPane.BOTTOM);
    619544    main_split_pane.setDividerLocation(250);
    620545
    621     external_split.add(collection_pane, JSplitPane.LEFT);//BorderLayout.WEST);
    622     //this.add(main_pane, BorderLayout.CENTER);
    623     external_split.add(main_split_pane, JSplitPane.RIGHT);//BorderLayout.CENTER);
     546    external_split.add(collection_pane, JSplitPane.LEFT);
     547    external_split.add(main_split_pane, JSplitPane.RIGHT);
    624548
    625549    this.setLayout(new BorderLayout());
     
    633557
    634558    /** Ensures a certain tree path is expanded, visible and selected within the collection tree.
    635     * @param path The <strong>TreePath</strong> to make visible.
    636     * @see org.greenstone.gatherer.tree.GTree
    637     */
    638     public void expandPath(TreePath path) {
     559     * @param path The <strong>TreePath</strong> to make visible.
     560     * @see org.greenstone.gatherer.tree.GTree
     561     */
     562    private void expandPath(TreePath path) {
    639563    collection_tree.expandPath(path);
    640564    collection_tree.setSelectionPath(path);
    641565    }
    642566    /** Called to inform this control panel that it has just gained focus as an effect of the user clicking on its tab.
    643     * @see org.greenstone.gatherer.tree.GTree
    644     */
     567     * @see org.greenstone.gatherer.tree.GTree
     568     */
    645569    public void gainFocus() {
    646570    // Use this opportunity to update the table model etc.
     
    659583    Gatherer.g_man.meta_audit.setRecords(records);
    660584    }
    661     /** 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.
    662      * @param new_record The <strong>FileNode</strong> which may or may not be the first occurance of a certain record.
    663      * @return The matching <strong>FileNode</strong> if there is one, or <i>null</i>.
    664      */
    665     public FileNode getAnyExistingRecord(FileNode new_record) {
    666     FileNode match = null;
    667     for(int i = 0; records != null && i < records.length && match == null; i++) {
    668         if(records[i].equals(new_record)) {
    669         match = records[i];
    670         }
    671     }
    672     return match;
    673     }
    674585
    675586    /** Retrieve the currently selected records.
    676     * @return A <strong>FileNode[]</strong> containing the current, and up to date, selection.
    677     */
     587     * @return A <strong>FileNode[]</strong> containing the current, and up to date, selection.
     588     */
    678589    public FileNode[] getSelectedNode() {
    679590    return records;
    680591    }
    681592
    682     /** Retrieve the currently selected metadata.
    683     * @return The <strong>Metadata</strong> in question.
    684     */
    685     public Metadata getSelectedMetadata() {
    686     return selected_metadata;
    687     }
    688 
    689593    /** Called whenever the metadata value changes in some way, such as the addition of a new value. - needed for MSMListener
    690594     * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
    691595     */
    692596    public void metadataChanged(MSMEvent event) {}
     597
     598    public void refreshTrees() {
     599    collection_tree.refresh(null); // Refresh entire tree.
     600    }
    693601
    694602    /** 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
     
    701609    }
    702610
    703     public void setSelection(File file) {
    704     collection_tree.setSelection(file);
    705     }
    706 
    707     /** Determine the bounds of the selected metadata within the table, used during search and replace actions.
    708     * @param metadata The <strong>Metadata</strong> to search for.
    709     */
    710     public Rectangle setSelectedMetadata(Metadata metadata) {
    711     // return model.setSelectedMetadata(metadata);
    712     return null;  // For now
    713     }
    714 
    715     public void refreshTrees() {
    716     collection_tree.refresh(null); // Refresh entire tree.
    717     }
    718 
    719     /* Called when nodes have been modified, but the model hasn't changed.
    720     * @param event Everything you ever wanted to know about model changes in one tidy <strong>TreeModelEvent</strong> package.
    721     */
    722     public void treeNodesChanged(TreeModelEvent event) {
    723     has_changed = true;
    724     }
    725 
    726     /* Called when nodes have been added to the model.
    727       * @param event Everything you ever wanted to know about model changes in one tidy <strong>TreeModelEvent</strong> package.
    728       */
    729     public void treeNodesInserted(TreeModelEvent event) {
    730     has_changed = true;
    731     }
    732 
    733     /* Called when nodes have been removed from the model.
    734       * @param event Everything you ever wanted to know about model changes in one tidy <strong>TreeModelEvent</strong> package.
    735       */
    736     public void treeNodesRemoved(TreeModelEvent event) {
    737     has_changed = true;
    738     }
    739 
    740     /** Called when nodes have been rearranged within the model.
    741       * @param event Everything you ever wanted to know about model changes in one tidy <strong>TreeModelEvent</strong> package.
    742       */
    743     public void treeStructureChanged(TreeModelEvent event) {
    744     has_changed = true;
    745     }
    746     /** Called to ensure that if the tree model has changed in some way, the view has been updated.
    747     * @see org.greenstone.gatherer.tree.GTree
    748     */
    749     public void updateTree() {
    750     if(has_changed) {
    751         tree.updateUI();
    752         has_changed = false;
    753     }
    754     }
    755 
    756611    /** 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.
    757       */
    758     public void validateControls() {
    759     validateControls(true);
    760     }
    761     public void validateControls(boolean and_tree) {
     612     */
     613    private void validateControls() {
    762614    validateMetadataTable();
    763615    // Validate card_layout_2
     
    768620        card_layout2.show(control_pane, TOOLS_OFF);
    769621    }
    770     if(and_tree) {
    771         // Validate the buttons in the lower pane
    772         if (selected_metadata == null) {
    773         // Nothing selected
    774         return;
    775         }
    776 
    777         // Does the metadata element have no current value?
    778         GValueNode value_node = selected_metadata.getValueNode();
    779         if (value_node == null) {
    780         // Can only append if something has been entered
    781         add.setEnabled((tree.getSelectedValue().length() > 0));
    782         // Nothing to replace or remove
     622
     623    // Validate the buttons in the lower pane
     624    if (selected_metadata == null) {
     625        // Nothing selected
     626        return;
     627    }
     628
     629    // Does the metadata element have no current value?
     630    GValueNode value_node = selected_metadata.getValueNode();
     631    if (value_node == null) {
     632        // Can only append if something has been entered
     633        add.setEnabled((tree.getSelectedValue().length() > 0));
     634        // Nothing to replace or remove
     635        update.setEnabled(false);
     636        remove.setEnabled(false);
     637    }
     638
     639    else {
     640        // Check if the text in the value field is the same as the metadata value
     641        if (tree.getSelectedValue().equals(value_node.getFullPath())) {
     642        // Can't append or replace
     643        add.setEnabled(false);
    783644        update.setEnabled(false);
    784         remove.setEnabled(false);
    785         }
    786 
     645        }
    787646        else {
    788         // Check if the text in the value field is the same as the metadata value
    789         if (tree.getSelectedValue().equals(value_node.getFullPath())) {
    790             // Can't append or replace
    791             add.setEnabled(false);
    792             update.setEnabled(false);
    793         }
    794         else {
    795             // Can append or replace
    796             add.setEnabled(true);
    797             update.setEnabled(true);
    798         }
    799 
    800         // Can only remove if the metadata is file level
    801         if (selected_metadata != null) {  // Shouldn't be necessary, but is
    802             remove.setEnabled(selected_metadata.isFileLevel());
    803         }
     647        // Can append or replace
     648        add.setEnabled(true);
     649        update.setEnabled(true);
     650        }
     651
     652        // Can only remove if the metadata is file level
     653        if (selected_metadata != null) {  // Shouldn't be necessary, but is
     654        remove.setEnabled(selected_metadata.isFileLevel());
    804655        }
    805656    }
     
    816667        card_layout.show(table_card_pane, CARD_ONE);
    817668    }
    818     /*
    819     if(records != null && model.getRowCount() > 0) {
    820         card_layout.show(table_card_pane, CARD_ONE);
    821     }
    822     else {
    823         card_layout.show(table_card_pane, CARD_ZERO);
    824         }*/
    825669    }
    826670
     
    851695        }
    852696        }
    853         validateControls(true);
     697        validateControls();
    854698    }
    855699    }
     
    937781
    938782    /** Retrieve a phrase from the Dictionary based on the given key.
    939     * @param key The <strong>String</strong> which maps to the phrase to retrieve.
    940     * @return The desired phrase as a <strong>String</strong>, or possibly an error message if no such phrase exists.
    941     */
     783     * @param key The <strong>String</strong> which maps to the phrase to retrieve.
     784     * @return The desired phrase as a <strong>String</strong>, or possibly an error message if no such phrase exists.
     785     */
    942786    private String get(String key) {
    943787    return get(key, null);
    944788    }
    945789    /** Retrieve a phrase from the Dictionary based on the given key and filled in with the given arguments.
    946     * @param key The <strong>String</strong> which maps to the phrase to retrieve.
    947     * @param args A <strong>String[]</strong> of arguments to be inserted in the phrase.
    948     * @return The desired phrase as a <strong>String</strong>, or possibly an error message if no such phrase exists.
    949     * @see org.greenstone.gatherer.Dictionary
    950     * @see org.greenstone.gatherer.Gatherer
    951     */
     790     * @param key The <strong>String</strong> which maps to the phrase to retrieve.
     791     * @param args A <strong>String[]</strong> of arguments to be inserted in the phrase.
     792     * @return The desired phrase as a <strong>String</strong>, or possibly an error message if no such phrase exists.
     793     * @see org.greenstone.gatherer.Dictionary
     794     * @see org.greenstone.gatherer.Gatherer
     795     */
    952796    private String get(String key, String args[]) {
    953797    if(key.indexOf('.') == -1) {
     
    1100944    }
    1101945    }
     946
     947
    1102948    /** Provides a popup menu to display when a right mouse button click is detected over the collection tree. */
    1103949    private class RightButtonMenu
     
    1106952    /** Constructor.
    1107953     * @param event The <strong>MouseEvent</strong> that triggered the creation of this menu. Used to determine where the menu will be located.
    1108         */
    1109     public RightButtonMenu(MouseEvent event) {
     954     */
     955    private RightButtonMenu(MouseEvent event) {
    1110956        super();
    1111                 // Creation
     957        // Creation
    1112958        JMenuItem show_metaaudit = new JMenuItem(get("Menu.Metadata_View") + " " + collection_tree.getSelectionDetails(), KeyEvent.VK_V);
    1113959        show_metaaudit.addActionListener(this);
    1114960        add(show_metaaudit);
    1115                 // Display
     961        // Display
    1116962        show(collection_tree, event.getX(), event.getY());
    1117963        show_metaaudit = null;
    1118         args = null;
    1119 
    1120     }
     964    }
     965
    1121966    /** Called whenever a user clicks on the single menu item, view all assigned metadata.
    1122         * @param event An <strong>ActionEvent</strong> containing further information about the action.
    1123         * @see org.greenstone.gatherer.Gatherer
    1124         * @see org.greenstone.gatherer.gui.GUIManager
    1125         */
     967     * @param event An <strong>ActionEvent</strong> containing further information about the action.
     968     * @see org.greenstone.gatherer.Gatherer
     969     * @see org.greenstone.gatherer.gui.GUIManager
     970     */
    1126971    public void actionPerformed(ActionEvent event) {
    1127972        Gatherer.g_man.showMetaAuditBox();
     
    1129974    }
    1130975
     976
     977    /**
     978     * @author John Thompson, Greenstone Digital Library, University of Waikato
     979     * @version 2.2
     980     */
     981    private class GValueTree
     982    extends JPanel
     983    implements TreeSelectionListener {
     984    private boolean ignore_tree_selection_event = false;
     985    private boolean manual_text_edit_event;
     986    private CardLayout card_layout;
     987    private String card_showing = null;
     988    /** The metadata element that is currently selected. */
     989    private ElementWrapper selected_metadata_element = null;
     990    private GValueModel vm;
     991    private JTextArea extracted_message;
     992    private JTextField value;
     993    private JTree tree;
     994    private MetaEditPane metaedit;
     995    private String args[] = new String[1];
     996    /** Stock standard size for labels. */
     997    final private Dimension VALUE_LABEL_SIZE = new Dimension(66, 26);
     998
     999    static final private String NONE = "None";
     1000    static final private String TREE = "Tree";
     1001
     1002
     1003    /**
     1004     * This class is a little bit complex, a little bit subtle, and a little bit odd.
     1005     * The strange interaction model is due to the fact that it is very tightly
     1006     * coupled to the MetaEditPane.
     1007     *
     1008     * The interaction is complex because there are three separate controls that the
     1009     * user may interact with, each of which can affect the other two. The three
     1010     * controls are:
     1011     *   - The "assigned metadata" table, at the top right of the meta edit pane.
     1012     *   - The "metadata value" text field, where users can type in new values.
     1013     *   - The "metadata value tree", which shows other values that have been
     1014     *     assigned to the selected metadata element.
     1015     *
     1016     * The interactions are:
     1017     *   - The "assigned metadata" table
     1018     *     Users may select one (and only one) row in this table. Selecting a row
     1019     *     chooses one metadata element. The text field will be set to the current
     1020     *     value of the metadata element. This value will also be selected in the
     1021     *     metadata value tree.
     1022     *
     1023     *   - The "metadata value" text field
     1024     *     If the value the user has typed in this is a prefix of an entry in the
     1025     *     value tree, this value will be selected in the value tree. In this case,
     1026     *     pressing "Enter" will complete the value (ie. make the value in the text
     1027     *     field the same as the value in the tree). This is to allow users to
     1028     *     quickly and easily assign existing metadata values to new documents.
     1029     *
     1030     *   - The "metadata value tree"
     1031     *     Selecting a value in the tree will set the text field to this value.
     1032     */
     1033    public GValueTree(MetaEditPane metaedit, int width, int height) {
     1034        super();
     1035
     1036        this.metaedit = metaedit;
     1037
     1038        setFont(Gatherer.config.getFont("general.font", false));
     1039        setPreferredSize(new Dimension(width, height));
     1040
     1041        JPanel metadata_pane = new JPanel();
     1042
     1043        JPanel value_pane = new JPanel();
     1044        JLabel value_label = new JLabel(get("Value"));
     1045        value_label.setPreferredSize(VALUE_LABEL_SIZE);
     1046
     1047        JPanel value_field_pane = new JPanel();
     1048        value = new JTextField();
     1049        value.setBackground(Gatherer.config.getColor("coloring.editable_background", false));
     1050        value.setForeground(Gatherer.config.getColor("coloring.editable_foreground", false));
     1051        value.setPreferredSize(new Dimension(413, 24));
     1052        value.getDocument().addDocumentListener(new DocumentListenerImpl());
     1053        value.addActionListener(new MetadataFieldListener());
     1054
     1055        JPanel button_pane = new JPanel();
     1056
     1057        JPanel tree_pane = new JPanel();
     1058        JLabel tree_label = new JLabel(get("Tree"));
     1059
     1060        tree = new JTree(new GValueModel());
     1061        tree.addTreeSelectionListener(this);
     1062        tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
     1063        tree.setRootVisible(false);
     1064        tree.putClientProperty("JTree.lineStyle", "Angled");
     1065
     1066        JPanel extracted_pane = new JPanel();
     1067        extracted_message = new JTextArea("");
     1068        extracted_message.setEditable(false);
     1069        extracted_message.setLineWrap(true);
     1070        extracted_message.setOpaque(false);
     1071        extracted_message.setWrapStyleWord(true);
     1072
     1073        card_layout = new CardLayout();
     1074
     1075        // Layout
     1076
     1077        value_field_pane.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
     1078        value_field_pane.setLayout(new BorderLayout(0, 0));
     1079        value_field_pane.add(value, BorderLayout.CENTER);
     1080
     1081        button_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
     1082        button_pane.setLayout(new GridLayout());
     1083        button_pane.add(add);
     1084        button_pane.add(update);
     1085        button_pane.add(remove);
     1086
     1087        value_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
     1088        value_pane.setLayout(new BorderLayout());
     1089        value_pane.add(value_label, BorderLayout.WEST);
     1090        value_pane.add(value_field_pane, BorderLayout.CENTER);
     1091        value_pane.add(expand, BorderLayout.EAST);
     1092        value_pane.add(button_pane, BorderLayout.SOUTH);
     1093
     1094        tree_pane.setLayout(new BorderLayout());
     1095        tree_pane.add(tree_label, BorderLayout.NORTH);
     1096        tree_pane.add(new JScrollPane(tree), BorderLayout.CENTER);
     1097
     1098        metadata_pane.setLayout(new BorderLayout());
     1099        metadata_pane.add(value_pane, BorderLayout.NORTH);
     1100        metadata_pane.add(tree_pane, BorderLayout.CENTER);
     1101
     1102        extracted_pane.setBorder(BorderFactory.createEmptyBorder(25,10,25,10));
     1103        extracted_pane.setLayout(new BorderLayout());
     1104        extracted_pane.add(extracted_message, BorderLayout.CENTER);
     1105
     1106        this.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
     1107        this.setLayout(card_layout);
     1108        this.add(metadata_pane, TREE);
     1109        this.add(extracted_pane, NONE);
     1110        card_showing = TREE;
     1111    }
     1112
     1113
     1114    public GValueModel getModel() {
     1115        return (GValueModel) tree.getModel();
     1116    }
     1117
     1118
     1119    public ElementWrapper getSelectedMetadataElement() {
     1120        return selected_metadata_element;
     1121    }
     1122
     1123
     1124    public String getSelectedValue() {
     1125        return value.getText();
     1126    }
     1127
     1128
     1129    public void setSelectedMetadataElement(ElementWrapper element)
     1130    {
     1131        ///ystem.err.println("Setting selected metadata element to: " + element);
     1132        if (element == null) {
     1133        selected_metadata_element = null;
     1134        return;
     1135        }
     1136
     1137        // Don't bother if the element selected is the same as the current one
     1138        if (selected_metadata_element != null && element.equals(selected_metadata_element)) {
     1139        return;
     1140        }
     1141
     1142        if (vm != null) {
     1143        // Close any expanded paths in the tree
     1144        GValueNode root_node = (GValueNode) vm.getRoot();
     1145        for (int i = 0; i < root_node.getChildCount(); i++) {
     1146            GValueNode child_node = (GValueNode) root_node.getChildAt(i);
     1147            TreePath child_path = new TreePath(child_node.getPath());
     1148            if (tree.isExpanded(child_path)) {
     1149            tree.collapsePath(child_path);
     1150            }
     1151        }
     1152        }
     1153
     1154        // Load the model for the newly selected metadata element
     1155        selected_metadata_element = element;
     1156        vm = Gatherer.c_man.getCollection().msm.getValueTree(element);
     1157        tree.setModel(vm);
     1158
     1159        // Special case the extracted metadata set
     1160        if (selected_metadata_element.getNamespace().equals("")) {
     1161        // Display the panel showing the "you cannot edit this metadata" message
     1162        args[0] = selected_metadata_element.toString();
     1163        extracted_message.setText(get("AutoMessage", args));
     1164        card_layout.show(this, NONE);
     1165        card_showing = NONE;
     1166        }
     1167        else {
     1168        // Display the panel for viewing and assigning metadata
     1169        card_layout.show(this, TREE);
     1170        card_showing = TREE;
     1171        }
     1172    }
     1173
     1174
     1175    /** Handles TreeSelectionEvents. */
     1176    public void valueChanged(TreeSelectionEvent event)
     1177    {
     1178        if (tree.getSelectionCount() != 0 && !ignore_tree_selection_event) {
     1179        TreePath path = tree.getSelectionPath();
     1180        GValueNode node = (GValueNode) path.getLastPathComponent();
     1181        setSelectedValue(node.getFullPath());
     1182        }
     1183    }
     1184
     1185
     1186    /** Sets the value in the text field. */
     1187    public void setSelectedValue(String val)
     1188    {
     1189        // Setting the text of the field causes the DocumentListener to be notified, and
     1190        //   updating the tree is handled there (DocumentListenerImpl::validate())
     1191        ///ystem.err.println("Setting selected value to: " + val);
     1192        if (!card_showing.equals(NONE)) {
     1193        manual_text_edit_event = val.equals("");  // Set to false unless val == ""
     1194        value.setText(Utility.stripNL(val));
     1195        value.setCaretPosition(0);
     1196        manual_text_edit_event = true;
     1197        }
     1198    }
     1199
     1200
     1201    private String get(String key) {
     1202        return get(key, null);
     1203    }
     1204
     1205    private String get(String key, String args[]) {
     1206        if (key.indexOf('.') == -1) {
     1207        key = "MetaEdit." + key;
     1208        }
     1209        return Gatherer.dictionary.get(key,args);
     1210    }
     1211
     1212
     1213    /** Returns a TreePath for the node most closely matching the metadata value. */
     1214    private TreePath getClosestPath(String val)
     1215    {
     1216        // Start at the root of the tree
     1217        GValueNode tree_node = (GValueNode) tree.getModel().getRoot();
     1218
     1219        // Hierarchical values are separated using '\'
     1220        StringTokenizer tokenizer = new StringTokenizer(val, "\\");
     1221        while (tokenizer.hasMoreTokens()) {
     1222        String token = tokenizer.nextToken();
     1223
     1224        // All components except the last must match exactly
     1225        if (tokenizer.hasMoreTokens()) {
     1226            for (int i = 0; i < tree_node.getChildCount(); i++) {
     1227            GValueNode child_node = (GValueNode) tree_node.getChildAt(i);
     1228            if (child_node.toString().equals(token)) {
     1229                // The matching node has been found, so move onto the next token
     1230                tree_node = child_node;
     1231                break;
     1232            }
     1233            }
     1234        }
     1235
     1236        // The last component may match partially
     1237        else {
     1238            for (int i = 0; i < tree_node.getChildCount(); i++) {
     1239            GValueNode child_node = (GValueNode) tree_node.getChildAt(i);
     1240            if (child_node.toString().startsWith(token)) {
     1241                // The closest node has been found, so return its path
     1242                return new TreePath(child_node.getPath());
     1243            }
     1244            }
     1245
     1246            // Not even a partial match
     1247            return null;
     1248        }
     1249        }
     1250
     1251        // If nothing else, return the path of the root node
     1252        return new TreePath(tree_node.getPath());
     1253    }
     1254
     1255
     1256    /** This function is copied from JTree::setPathToVisible(), and modified so tree rows
     1257        are always shown flushed left. Note: doesn't do accessibleContext stuff. */
     1258    private void scrollTreePathToVisible(TreePath path)
     1259    {
     1260        if (path != null) {
     1261        tree.makeVisible(path);
     1262
     1263        Rectangle bounds = tree.getPathBounds(path);
     1264        if (bounds != null) {
     1265            bounds.width += bounds.x;
     1266            bounds.x = 0;
     1267            tree.scrollRectToVisible(bounds);
     1268        }
     1269        }
     1270    }
     1271
     1272
     1273    private class MetadataFieldListener
     1274        implements ActionListener {
     1275        /** Gives notification of the Enter key being pressed on the text field */
     1276        public void actionPerformed(ActionEvent e) {
     1277        if (tree.getSelectionCount() != 0 && !value.getText().equals("")) {
     1278            TreePath path = tree.getSelectionPath();
     1279            GValueNode node = (GValueNode) path.getLastPathComponent();
     1280            value.setText(Utility.stripNL(node.getFullPath()));
     1281        }
     1282        }
     1283    }
     1284
     1285
     1286    private class DocumentListenerImpl
     1287        implements DocumentListener {
     1288        /** Gives notification that an attribute or set of attributes changed. */
     1289        public void changedUpdate(DocumentEvent e) {
     1290        validate();
     1291        }
     1292
     1293        /** Gives notification that there was an insert into the document. */
     1294        public void insertUpdate(DocumentEvent e) {
     1295        validate();
     1296        }
     1297
     1298        /** Gives notification that a portion of the document has been removed. */
     1299        public void removeUpdate(DocumentEvent e) {
     1300        validate();
     1301        }
     1302
     1303
     1304        /** Ensures that the value text field and value tree are synchronized. */
     1305        private void validate()
     1306        {
     1307        String value_text = value.getText();
     1308        ///ystem.err.println("\n(Validate) Value text: " + value_text);
     1309
     1310        // Ignore the validate() with empty text that occurs when value.setText() is used
     1311        if (!value_text.equals("") || manual_text_edit_event == true) {
     1312            TreePath closest_path = getClosestPath(value_text);
     1313
     1314            // Select the new path in the tree
     1315            // The tree selection event this causes must be ignored, since it alters value
     1316            ignore_tree_selection_event = true;
     1317            tree.setSelectionPath(closest_path);
     1318            ignore_tree_selection_event = false;
     1319
     1320            // If a folder has been specified, make sure it is expanded
     1321            if (value_text.endsWith("\\") && !tree.isExpanded(closest_path)) {
     1322            tree.expandPath(closest_path);
     1323            }
     1324
     1325            // Make sure the path is visible on the screen
     1326            scrollTreePathToVisible(closest_path);
     1327            // One call should be enough, but it isn't in some cases (for some reason)
     1328            scrollTreePathToVisible(closest_path);
     1329
     1330            // Update the status of the buttons
     1331            metaedit.validateControls();
     1332        }
     1333        }
     1334    }
     1335    }
    11311336}
Note: See TracChangeset for help on using the changeset viewer.