Changeset 4424
- Timestamp:
- 2003-05-30T13:49:03+12:00 (21 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/gli/src/org/greenstone/gatherer/valuetree/GValueTree.java
r4408 r4424 44 44 import javax.swing.tree.*; 45 45 import org.greenstone.gatherer.Gatherer; 46 import org.greenstone.gatherer.gui.EditorDialog;47 46 import org.greenstone.gatherer.gui.MetaEditPane; 48 47 import org.greenstone.gatherer.gui.SmarterTextArea; 49 import org.greenstone.gatherer.gui.combobox.GComboBox;50 import org.greenstone.gatherer.gui.combobox.GComboBoxModel;51 48 import org.greenstone.gatherer.msm.ElementWrapper; 52 49 import org.greenstone.gatherer.msm.Metadata; 53 import org.greenstone.gatherer.msm.MetadataComboBoxModel;54 import org.greenstone.gatherer.msm.MSMAction;55 import org.greenstone.gatherer.msm.MSMEvent;56 import org.greenstone.gatherer.msm.MSMListener;57 50 import org.greenstone.gatherer.util.Utility; 58 51 /** … … 62 55 public class GValueTree 63 56 extends JPanel 64 implements ActionListener, FocusListener, MSMListener, TreeSelectionListener { 65 /** Is the metadata currently shown in the edit controls common to all records selected. */ 66 private boolean common = false; 67 /** Certain actions are disabled if the metadata selected isn't at file level. */ 68 private boolean file_level = false; 69 private boolean ignore = false; 70 private boolean ignore_item_change = false; 57 implements TreeSelectionListener { 58 private boolean ignore_tree_selection_event = false; 59 private boolean manual_text_edit_event; 60 private JPanel center_pane; 71 61 private CardLayout card_layout; 72 private DefaultListModel list_model;73 62 /** The metadata element that is currently selected. */ 74 63 private ElementWrapper selected_metadata_element = null; 75 //private GComboBox elements;76 private MetadataComboBoxModel em;77 64 private GValueModel vm; 78 private Hashtable previous_values = new Hashtable();79 private JButton add;80 /** This button creates an editor dialog to allow for an expanded area to type in text. */81 private JButton expand = null;82 private JButton remove;83 private JButton restore;84 private JButton search;85 private JButton update;86 //private JLabel element_label;87 private JLabel value_label;88 private JList list;89 private JPanel auto_pane;90 private JPanel button_pane;91 private JPanel center_pane;92 //private JPanel list_pane;93 private JPanel north_pane;94 //private JPanel south_pane;95 private JPanel tree_pane;96 private JPanel value_pane;97 65 private JTextArea auto_message; 98 66 private JTextField value; … … 100 68 private MetaEditPane metaedit; 101 69 private String args[] = new String[1]; 102 private TreePath previous;103 private ValueListener value_listener;104 70 /** Stock standard size for labels. */ 105 71 static final private Dimension LABEL_SIZE = new Dimension(132, 26); 106 72 107 //static final private String LIST = "List";108 73 static final private String NONE = "None"; 109 74 static final private String TREE = "Tree"; 110 75 111 76 112 public GValueTree(MetaEditPane metaedit, int width, int height, JButton add, JButton update, JButton remove) { 113 this(metaedit, new Dimension(width, height), add, update, remove); 114 } 115 116 public GValueTree(MetaEditPane metaedit, Dimension size, JButton add, JButton update, JButton remove) { 77 public GValueTree(MetaEditPane metaedit, int width, int height, JButton add, JButton update, JButton remove, JButton expand) { 117 78 super(); 118 79 119 this.add = add;120 80 this.metaedit = metaedit; 121 this.remove = remove;122 this.update = update;123 124 ///ystem.err.println("Created new ValueListener!");125 value_listener = new ValueListener();126 127 int height = size.height;128 int width = size.width;129 81 130 82 setFont(Gatherer.config.getFont("general.font", false)); 131 //setSize(size); 83 84 Dimension size = new Dimension(width, height); 132 85 setPreferredSize(size); 133 86 134 //north_pane = new JPanel();135 136 //element_label = new JLabel(get("Element"));137 //element_label.setPreferredSize(LABEL_SIZE);138 139 //elements = new GComboBox();140 //elements.addItemListener(this);141 //elements.setEditable(false);142 //elements.setMaximumRowCount(5);143 //elements.setPreferredSize(new Dimension(413, 24));144 145 87 center_pane = new JPanel(); 146 88 147 89 card_layout = new CardLayout(); 148 90 149 auto_pane = new JPanel();91 JPanel auto_pane = new JPanel(); 150 92 args[0] = "Title"; 151 93 auto_message = new SmarterTextArea(get("AutoMessage", args), false); … … 154 96 auto_message.setWrapStyleWord(true); 155 97 156 tree_pane = new JPanel();98 JPanel tree_pane = new JPanel(); 157 99 158 100 JLabel tree_label = new JLabel(get("Tree")); … … 163 105 tree.setRootVisible(true); 164 106 tree.putClientProperty("JTree.lineStyle", "Angled"); 165 //setTreeEnabled(false);166 167 //list_pane = new JPanel();168 //JLabel list_label = new JLabel(get("List"));169 //list_model = new DefaultListModel();170 //list = new JList(list_model);171 //list.addListSelectionListener(new ListSelectionListenerImpl());172 107 173 108 JPanel controls_pane = new JPanel(); 174 109 175 value_pane = new JPanel();176 value_label = new JLabel(get("Value"));110 JPanel value_pane = new JPanel(); 111 JLabel value_label = new JLabel(get("Value")); 177 112 value_label.setPreferredSize(LABEL_SIZE); 178 113 JPanel edit_pane = new JPanel(); 179 expand = new JButton(get("General.Expand"));180 expand.setMnemonic(KeyEvent.VK_E);181 expand.setPreferredSize(MetaEditPane.BUTTON_SIZE);182 114 183 115 value = new JTextField(); 184 value.addActionListener(this);185 116 value.setBackground(Gatherer.config.getColor("coloring.editable", false)); 186 value.addFocusListener(this);187 //value.addKeyListener(this);188 117 value.setPreferredSize(new Dimension(413, 24)); 189 190 button_pane = new JPanel(); 118 value.getDocument().addDocumentListener(new DocumentListenerImpl()); 119 120 JPanel button_pane = new JPanel(); 191 121 192 122 JPanel inner_button_pane = new JPanel(); 193 123 194 //restore = new JButton(get("Restore"));195 //restore.setEnabled(false);196 //restore.setMnemonic(KeyEvent.VK_T);197 198 //search = new JButton(get("Search"));199 //search.setMnemonic(KeyEvent.VK_S);200 201 // Connection202 expand.addActionListener(this);203 //restore.addActionListener(this);204 //search.addActionListener(this);205 value.getDocument().addDocumentListener(new DocumentListenerImpl());206 207 124 // Layout 208 //element_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));209 //north_pane.setLayout(new BorderLayout());210 //north_pane.add(element_label, BorderLayout.CENTER);211 //north_pane.add(elements, BorderLayout.EAST);212 213 125 tree_pane.setLayout(new BorderLayout()); 214 126 tree_pane.add(tree_label, BorderLayout.NORTH); 215 127 tree_pane.add(new JScrollPane(tree), BorderLayout.CENTER); 216 128 217 //list_pane.setLayout(new BorderLayout());218 //list_pane.add(list_label, BorderLayout.NORTH);219 //list_pane.add(new JScrollPane(list), BorderLayout.CENTER);220 221 129 auto_pane.setBorder(BorderFactory.createEmptyBorder(25,10,25,10)); 222 130 auto_pane.setLayout(new BorderLayout()); … … 226 134 center_pane.setLayout(card_layout); 227 135 center_pane.add(tree_pane, TREE); 228 //center_pane.add(list_pane, LIST);229 136 center_pane.add(auto_pane, NONE); 230 137 … … 251 158 controls_pane.setLayout(new BorderLayout()); 252 159 controls_pane.add(value_pane, BorderLayout.CENTER); 253 //controls_pane.add(button_pane, BorderLayout.SOUTH);254 160 255 161 this.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); … … 257 163 this.add(controls_pane, BorderLayout.NORTH); 258 164 this.add(center_pane, BorderLayout.CENTER); 259 //this.add(south_pane, BorderLayout.SOUTH); 260 } 261 262 public void actionPerformed(ActionEvent event) { 263 ignore = true; 264 if(event.getSource() == value) { 265 StringTokenizer tokenizer = new StringTokenizer(value.getText(), "\\"); 266 TreePath closest = getClosestPath(tokenizer); 267 if(closest != null) { 268 TreePath path = tree.getSelectionPath(); 269 GValueNode node = (GValueNode)path.getLastPathComponent(); 270 ///ystem.err.println("1. Set value: " + node.toString()); 271 value.setText(Utility.stripNL(node.toString()));//formatPath(path, false))); 272 value.setCaretPosition(0); 273 // Now systematically add to selected record. 274 add.doClick(); 275 } 276 else { 277 int response = JOptionPane.showConfirmDialog(this, "Do you wish to create a new entry?", "Warning", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); 278 if(response == JOptionPane.YES_OPTION) { 279 TreePath new_path = addNode(value.getText()); 280 tree.setSelectionPath(new_path); 281 // tree.scrollPathToVisible(new_path); 282 scrollTreePathToVisible(new_path); 283 GValueNode node = (GValueNode)new_path.getLastPathComponent(); 284 ///ystem.err.println("2. Set value: " + node.toString()); 285 value.setText(Utility.stripNL(node.toString())); 286 value.setCaretPosition(0); 287 // Now systematically add to selected record. 288 add.doClick(); 289 } 290 } 291 } 292 //else if(event.getSource() == search) { 293 // searchValues(); 294 // restore.setEnabled(true); 295 // card_layout.show(center_pane, LIST); 296 //} 297 //else if(event.getSource() == restore) { 298 // restore.setEnabled(false); 299 // card_layout.show(center_pane, TREE); 300 //} 301 else if(event.getSource() == expand) { 302 EditorDialog ed = new EditorDialog(); 303 String temp = ed.display(value.getText()); 304 if(temp != null) { 305 ///ystem.err.println("3. Set value: " + temp); 306 value.setText(temp); 307 value.setCaretPosition(0); 308 } 309 //validateControls(); 310 } 311 ignore = false; 312 } 313 /** Called whenever an element within the metadata set module changes in some way. 314 * @param event A <strong>MSMEvent</strong> which contains information about the change. 315 */ 316 public void elementChanged(MSMEvent event) { 317 /* @TODO - Not sure. Figure out. */ 318 } 319 public void focusGained(FocusEvent event) { 320 321 } 322 323 public void focusLost(FocusEvent event) { 324 325 } 326 327 public boolean getCommon() { 328 return common; 329 } 165 } 166 167 168 public GValueModel getModel() { 169 return (GValueModel) tree.getModel(); 170 } 171 330 172 331 173 public ElementWrapper getSelectedMetadataElement() { … … 333 175 } 334 176 177 335 178 public String getSelectedValue() { 336 String value_text = value.getText(); 337 previous_values.put(selected_metadata_element, value_text); 338 return value_text; 339 } 340 341 public GValueModel getValueModel() { 342 return (GValueModel) tree.getModel(); 343 } 344 345 /** This method is required for any ItemListener so that it can be informed when the state of an item set changes (such as when a new selection is made in a combobox). Note that this update is subtly different from the validateControls() method as it also gathers new models for each combobox as required. The reason this isn't done as part of validateControls() is that this would continously reset whatever the user is attempting to type (ie value would be found to be enabled and a new model would be loaded erasing whatever the user just typed in value to fire the validateControls() in the first place!) 346 * @param event An ItemEvent encapsulating all the information about this event. 347 */ 348 /* 349 public void itemStateChanged(ItemEvent event) { 350 ///ystem.err.println("Item State Changed"); 351 if(!ignore_item_change) { 352 ignore_item_change = true; 353 selected_metadata_element = (ElementWrapper)em.getSelectedItem(); 354 if(selected_metadata_element != null) { 355 //elements.setToolTipText(selected_metadata_element.getToolTip()); 356 vm = null; 357 vm = Gatherer.c_man.getCollection().msm.getValueTree(selected_metadata_element); 358 if(vm != null) { 359 ///ystem.err.println("Assigning value model."); 360 vm.addTreeModelListener(value_listener); 361 tree.addTreeSelectionListener(this); 362 setTreeEnabled(true); 363 } 364 else { 365 ///ystem.err.println("Creating new model."); 366 vm = new GValueModel(get("Not_Applicable")); 367 setTreeEnabled(false); 368 } 369 tree.setModel(vm); 370 } 371 else { 372 setTreeEnabled(false); 373 } 374 value.setText(""); 375 metaedit.validateControls(false); 376 } 377 previous = null; 378 ignore_item_change = false; 379 validateControls(); 380 } 381 */ 382 383 /** Called whenever a metadata value is changed. 384 * @param event A <strong>MSMEvent</strong> which encapsulates relevant data about the change. 385 */ 386 public void metadataChanged(MSMEvent event) { 387 // Don't care. 388 } 389 390 public void newMetadataSetManager() { 391 if(Gatherer.c_man != null && Gatherer.c_man.getCollection() != null && Gatherer.c_man.getCollection().msm != null) { 392 Gatherer.c_man.getCollection().msm.addMSMListener(this); 393 } 394 setChanged(null); 395 } 396 397 public void refreshValueTree() { 398 if(em != null && em.getSize() > 0) { 399 setSelectedMetadataElement((ElementWrapper)em.getSelectedItem()); 400 } 401 } 402 403 public void registerModel(GValueModel model) { 404 vm = model; 405 vm.addTreeModelListener(value_listener); 406 tree.setModel(model); 407 tree.addTreeSelectionListener(this); 408 } 409 /** Called whenever a set within the metadata set module changes in some way. 410 * @param event A <strong>MSMEvent</strong> which contains information about the change. 411 */ 412 public void setChanged(MSMEvent event) { 413 // Update the element model. 414 MetadataComboBoxModel model = Gatherer.c_man.getCollection().msm.getElementModel(); 415 if(model.getSize() > 0) { 416 setElementModel(model); 417 model.setSelectedItem(model.getElementAt(0)); 418 vm = Gatherer.c_man.getCollection().msm.getValueTree((ElementWrapper)model.getSelectedItem()); 419 setTreeEnabled(true); 420 if(vm == null) { 421 vm = new GValueModel(get("Not_Applicable")); 422 setTreeEnabled(false); 423 } 424 } 425 else { 426 vm = new GValueModel(); 427 setTreeEnabled(true); 428 } 429 vm.addTreeModelListener(value_listener); 430 tree.setModel(vm); 431 tree.addTreeSelectionListener(this); 432 } 433 434 public void setCommon(boolean common) { 435 this.common = common; 436 } 437 438 public void setElementModel(MetadataComboBoxModel model) { 439 ///ystem.err.println("Reset ElementModel."); 440 setTreeEnabled(true); 441 Gatherer.c_man.getCollection().msm.addMSMListener(this); 442 if(model == null) { 443 Gatherer.println("model = null"); 444 System.exit(0); 445 } 446 ignore_item_change = true; 447 em = model; 448 //elements.setModel(em); 449 if(em.getSize() > 0) { 450 ///ystem.err.println("em.size() > 0"); 451 //elements.setEnabled(true); 452 //elements.setSelectedIndex(0); 453 selected_metadata_element = (ElementWrapper)em.getSelectedItem(); 454 //elements.setToolTipText(selected_metadata_element.getToolTip()); 455 // First we create and install a blank model, or else no updates ever work. 456 vm = new GValueModel(get("Not_Applicable")); 457 tree.setModel(vm); 458 // Now we create a new model if applicable, disabling otherwise. 459 if(selected_metadata_element.getNamespace().length() > 0) { 460 vm = Gatherer.c_man.getCollection().msm.getValueTree(selected_metadata_element); 461 vm.addTreeModelListener(value_listener); 462 ///ystem.err.println("Found existing model containing " + vm.size() + " entries"); 463 setTreeEnabled(true); 464 tree.setModel(vm); // This doesn't seem to work 465 } 466 else { 467 ///ystem.err.println("Creating new model."); 468 setTreeEnabled(false); 469 } 470 ///ystem.err.println("The value tree should have been updated by now."); 471 ///ystem.err.println("6. Set value: " + getLastValue()); 472 value.setText(Utility.stripNL(getLastValue())); 473 value.setCaretPosition(0); 474 } 475 else { 476 ///ystem.err.println("No elements loaded."); 477 //elements.setEnabled(false); 478 //elements.setToolTipText(get("No_Description")); 479 //setTreeEnabled(false); 480 value.setText(""); 481 } 482 previous = null; 483 ignore_item_change = false; 484 validateControls(); 485 } 486 487 public void setFileLevel(boolean file_level) { 488 this.file_level = file_level; 489 } 179 return value.getText(); 180 } 181 490 182 491 183 public void setRootVisible(boolean val) { … … 493 185 } 494 186 495 public void setSelectedMetadataElement(ElementWrapper element) { 496 if(!ignore_item_change) { 497 ignore_item_change = true; 498 if(element != null) { 499 selected_metadata_element = element; 500 //elements.setSelectedItem(element); 501 //elements.setToolTipText(element.getToolTip()); 502 vm = Gatherer.c_man.getCollection().msm.getValueTree(element); 503 if(vm != null) { 504 vm.addTreeModelListener(value_listener); 505 setTreeEnabled(true); 187 188 public void setSelectedMetadataElement(ElementWrapper element) 189 { 190 // System.err.println("Setting selected metadata element to: " + element); 191 if (element == null) { 192 selected_metadata_element = null; 193 setTreeEnabled(false); 194 return; 195 } 196 197 // Don't bother if the element selected is the same as the current one 198 if (selected_metadata_element != null && element.equals(selected_metadata_element)) { 199 return; 200 } 201 202 if (vm != null) { 203 // Close any expanded paths in the tree 204 GValueNode root_node = (GValueNode) vm.getRoot(); 205 for (int i = 0; i < root_node.getChildCount(); i++) { 206 GValueNode child_node = (GValueNode) root_node.getChildAt(i); 207 TreePath child_path = new TreePath(child_node.getPath()); 208 if (tree.isExpanded(child_path)) { 209 tree.collapsePath(child_path); 506 210 } 507 else { 508 vm = new GValueModel(get("Not_Applicable")); 509 setTreeEnabled(false); 510 } 511 tree.setModel(vm); 512 ///ystem.err.println("7. Set value: " + getLastValue()); 513 //value.setText(Utility.stripNL(getLastValue())); 514 //value.setCaretPosition(0); 515 } 516 else { 517 //elements.setToolTipText(get("No_Description")); 518 setTreeEnabled(false); 519 //value.setText(""); 520 } 521 metaedit.validateControls(false); 522 } 523 previous = null; 524 ignore_item_change = false; 525 //validateControls(); 526 } 527 528 public void setSelectedValue(String val) { 529 ignore = true; 211 } 212 } 213 214 // Load the model for the newly selected metadata element 215 selected_metadata_element = element; 216 vm = Gatherer.c_man.getCollection().msm.getValueTree(element); 217 setTreeEnabled(true); 218 tree.setModel(vm); 219 } 220 221 222 /** Handles TreeSelectionEvents. */ 223 public void valueChanged(TreeSelectionEvent event) 224 { 225 if(tree.getSelectionCount() != 0 && !ignore_tree_selection_event) { 226 TreePath path = tree.getSelectionPath(); 227 GValueNode node = (GValueNode) path.getLastPathComponent(); 228 setSelectedValue(node.getFullPath()); 229 } 230 } 231 232 233 /** Sets the value in the text field. */ 234 public void setSelectedValue(String val) 235 { 236 // Setting the text of the field causes the DocumentListener to be notified, and 237 // updating the tree is handled there (DocumentListenerImpl::validate()) 238 // System.err.println("Setting selected value to: " + val); 239 manual_text_edit_event = val.equals(""); // Set to false unless val == "" 530 240 value.setText(Utility.stripNL(val)); 531 241 value.setCaretPosition(0); 532 StringTokenizer tokenizer = new StringTokenizer(val, "\\"); 533 TreePath closest = getClosestPath(tokenizer); 534 if(previous != null) { 535 tree.collapsePath(getParent(previous)); 536 previous = null; 537 } 538 if(closest != null) { 539 tree.setSelectionPath(closest); 540 // tree.scrollPathToVisible(closest); 541 scrollTreePathToVisible(closest); 542 } 543 ignore = false; 544 //validateControls(); 545 } 546 547 /** This method enables or diables the various controls based upon the 548 * state of the system. This method should be called after every change 549 * which could affect the GUI. <br> 550 * Hack #1: For some reason this gets called 14 times for one selection. One day I'll figure out why, but for now I'll just ignore all but every fourteenth call. 551 */ 552 public void validateControls() { 553 Metadata selected_metadata = metaedit.getSelectedMetadata(); 554 if(metaedit.getSelectedNode() != null && selected_metadata != null) { 555 ElementWrapper element = selected_metadata.getElement(); 556 if(element.getNamespace() != "") { 557 GValueNode value_node = selected_metadata.getValueNode(); 558 ///ystem.err.println("Value node = " + value_node); 559 // We may be dealing with an element that has no current value 560 if(value_node == null) { 561 String new_value = value.getText(); 562 if(new_value.length() > 0) { 563 add.setEnabled(true); 564 } 565 else { 566 add.setEnabled(false); 567 } 568 // Nothing to update 569 update.setEnabled(false); 570 // Nothing to remove 571 remove.setEnabled(false); 572 } 573 // Or else we have some current value that may or may not match the one in our value field. 574 else { 575 String current_value = selected_metadata.getValueNode().getFullPath(); 576 String new_value = value.getText(); 577 ///ystem.err.println("Current value: '" + current_value + "'"); 578 ///ystem.err.println("New value: '" + new_value + "'"); 579 if(new_value.length() > 0 && !current_value.equals(new_value)) { 580 add.setEnabled(true); 581 if(common) { 582 update.setEnabled(true); 583 } 584 else { 585 update.setEnabled(false); 586 } 587 } 588 else { 589 add.setEnabled(false); 590 update.setEnabled(false); 591 } 592 // If you have something selected, and we're at the file level, you can remove it. 593 if(file_level) { 594 remove.setEnabled(true); 595 } 596 else { 597 remove.setEnabled(false); 598 } 599 } 600 } 601 else { 602 add.setEnabled(false); 603 update.setEnabled(false); 604 remove.setEnabled(false); 605 } 606 } 607 else { 608 add.setEnabled(false); 609 update.setEnabled(false); 610 remove.setEnabled(false); 611 } 612 } 613 614 /** Called when the value tree of a certain element has changed significantly. If we are displaying the tree for the element noted in the event, then reload the value model. 615 * @param event A <strong>MSMEvent</strong> containing information about the event. 616 */ 617 public void valueChanged(MSMEvent event) { 618 ElementWrapper element = event.getElement(); 619 if(selected_metadata_element.equals(element)) { 620 GValueModel temp = Gatherer.c_man.getCollection().msm.getValueTree(element); 621 if(temp != null) { 622 vm = temp; 623 tree.setModel(vm); 624 vm.removeTreeModelListener(value_listener); 625 vm.addTreeModelListener(value_listener); 626 setTreeEnabled(true); 627 setSelectedValue(value.getText()); 628 } 629 else { 630 vm = new GValueModel(get("Not_Applicable")); 631 tree.setModel(vm); 632 setTreeEnabled(false); 633 } 634 } 635 } 636 637 public void valueChanged(TreeSelectionEvent event) { 638 if(tree.getSelectionCount() != 0 && !ignore) { 639 TreePath path = tree.getSelectionPath(); 640 GValueNode node = (GValueNode) path.getLastPathComponent(); 641 value.setText(node.getFullPath());//formatPath(tree.getSelectionPath(), false))); 642 value.setCaretPosition(0); 643 validateControls(); 644 } 645 } 646 647 private TreePath addNode(String reference) { 648 StringTokenizer tokenizer = new StringTokenizer(reference, "\\"); 649 GValueModel model = (GValueModel)tree.getModel(); 650 GValueNode current = (GValueNode)model.getRoot(); 651 while(tokenizer.hasMoreElements()) { 652 String token = tokenizer.nextToken(); 653 GValueNode node = (GValueNode)getClosestNode(token, current); 654 if(node == null) { 655 Gatherer.println("Before: '" + current.toString() + "'"); 656 for(int i = 0; i < current.getChildCount(); i++) { 657 Gatherer.println(current.getChildAt(i).toString()); 658 } 659 node = model.addValue(token, current, null); 660 Gatherer.println("After: '" + current.toString() + "'"); 661 for(int i = 0; i < current.getChildCount(); i++) { 662 Gatherer.println(current.getChildAt(i).toString()); 663 } 664 } 665 current = node; 666 } 667 tree.updateUI(); 668 if(current != null) { 669 return new TreePath(current.getPath()); 670 } 671 else { 672 return new TreePath(((GValueNode)model.getRoot()).getPath()); 673 } 674 } 675 /** Returns the given tree path as path formatted string (ie subject\subject\subject). 676 * @param tree The <strong>JTree</strong> the TreePath came from. Used to determine if the root node should be encoded as well. 677 * @param path A <strong>TreePath</strong> that you wish to encode to String. 678 * @param full <i>true</i> if this is the full path (ie a leaf node), <i>false</i> otherwise. 679 * @return A <strong>String</strong> encoding the information from the TreePath. 680 * @see javax.swing.JTree 681 * @see javax.swing.tree.TreePath 682 */ 683 static public String formatPath(JTree tree, TreePath path, boolean full) { 684 String text = ""; 685 int i = 0; 686 if(tree == null || (!tree.isRootVisible() && !full)) { 687 i = 1; 688 } 689 for( ; i < path.getPathCount(); i++) { 690 GValueNode node = (GValueNode)path.getPathComponent(i); 691 text = text + node.toString(); 692 if(node.getChildCount() > 0) { 693 text = text + "\\"; 694 } 695 } 696 if(full && text.endsWith("\\")) { 697 return text.substring(0, text.length() - 1); 698 } 699 return text; 700 } 242 manual_text_edit_event = true; 243 } 244 701 245 702 246 private String get(String key) { … … 711 255 } 712 256 713 private GValueNode getClosestNode(String target, GValueNode current) {714 // We have struck it lucky.715 if(startsWith(current.toString(), target)) {716 return current;717 }718 GValueNode closest = null;719 for(int i = 0; i < current.getChildCount() && closest == null; i++) {720 closest = getClosestNode(target, (GValueNode)current.getChildAt(i));721 }722 return closest;723 }724 725 private TreePath getClosestPath(StringTokenizer tokenizer) {726 if(tokenizer.countTokens() > 0) {727 TreeNode tree_node = (TreeNode)tree.getModel().getRoot();728 if(tree_node instanceof GValueNode) {729 GValueNode current = (GValueNode)tree_node;730 TreePath closest = null;731 while(tokenizer.hasMoreElements() && current != null) {732 current = getClosestNode(tokenizer.nextToken(), current);733 }734 if(current != null) {735 return new TreePath(current.getPath());736 }737 return null;738 }739 }740 return null;741 }742 743 private String getLastValue() {744 if(previous_values.containsKey(selected_metadata_element)) {745 return (String)previous_values.get(selected_metadata_element);746 }747 return "";748 }749 750 private TreePath getParent(TreePath path) {751 if(path.getPathCount() > 1) {752 TreeNode nodes[] = new TreeNode[path.getPathCount() - 1];753 for(int i = 0; i < path.getPathCount() - 1; i++) {754 nodes[i] = (TreeNode)path.getPathComponent(i);755 }756 return new TreePath(nodes);757 }758 return null;759 }760 761 private void searchValues() {762 // Clear any old search results.763 list_model.clear();764 String target = value.getText();765 GValueNode current = (GValueNode)tree.getModel().getRoot();766 Vector search_space = new Vector();767 search_space.add(current);768 for(int i = 0; i < search_space.size(); i++) {769 GValueNode node = (GValueNode)search_space.get(i);770 // Add this nodes children.771 for(int j = 0; j < node.getChildCount(); j++) {772 search_space.add(node.getChildAt(j));773 }774 // And if this node matches add it to list, except for the very775 // first node as that is AssignedValues the root node!776 if(node.toString().indexOf(target) != -1 &&777 node != current) {778 list_model.add(list_model.size(), node);779 }780 }781 }782 257 783 258 private void setTreeEnabled(boolean value) { … … 800 275 } 801 276 802 private boolean startsWith(String longer, String shorter) { 803 if(longer.length() > shorter.length()) { 804 longer = longer.substring(0, shorter.length()); 805 } 806 return longer.equalsIgnoreCase(shorter); 807 } 808 809 private void printTreePaths() { 810 ///ystem.out.println("Tree Paths according to getPath() method."); 811 Vector nodes = new Vector(); 812 nodes.add(tree.getModel().getRoot()); 813 while(nodes.size() > 0) { 814 GValueNode node = (GValueNode)nodes.get(0); 815 nodes.remove(node); 816 for(int i = 0; i < node.getChildCount(); i++) { 817 nodes.add(node.getChildAt(i)); 818 } 819 ///ystem.out.println("TreePath = " + node.getPath()); 820 } 821 } 277 278 /** Returns a TreePath for the node most closely matching the metadata value. */ 279 private TreePath getClosestPath(String val) 280 { 281 // Start at the root of the tree 282 GValueNode tree_node = (GValueNode) tree.getModel().getRoot(); 283 284 // Hierarchical values are separated using '\' 285 StringTokenizer tokenizer = new StringTokenizer(val, "\\"); 286 while (tokenizer.hasMoreTokens()) { 287 String token = tokenizer.nextToken(); 288 289 // All components except the last must match exactly 290 if (tokenizer.hasMoreTokens()) { 291 for (int i = 0; i < tree_node.getChildCount(); i++) { 292 GValueNode child_node = (GValueNode) tree_node.getChildAt(i); 293 if (child_node.toString().equals(token)) { 294 // The matching node has been found, so move onto the next token 295 tree_node = child_node; 296 break; 297 } 298 } 299 } 300 301 // The last component may match partially 302 else { 303 for (int i = 0; i < tree_node.getChildCount(); i++) { 304 GValueNode child_node = (GValueNode) tree_node.getChildAt(i); 305 if (child_node.toString().startsWith(token)) { 306 // The closest node has been found, so return its path 307 return new TreePath(child_node.getPath()); 308 } 309 } 310 311 // Not even a partial match 312 return null; 313 } 314 } 315 316 // If nothing else, return the path of the root node 317 return new TreePath(tree_node.getPath()); 318 } 319 822 320 823 321 /** This function is copied from JTree::setPathToVisible(), and modified so tree rows 824 are always shown flushed left. */ 825 public void scrollTreePathToVisible(TreePath path) { 322 are always shown flushed left. Note: doesn't do accessibleContext stuff. */ 323 private void scrollTreePathToVisible(TreePath path) 324 { 826 325 if (path != null) { 827 326 tree.makeVisible(path); 828 327 829 328 Rectangle bounds = tree.getPathBounds(path); 830 831 329 if (bounds != null) { 832 330 bounds.width += bounds.x; 833 331 bounds.x = 0; 834 332 tree.scrollRectToVisible(bounds); 835 // if (tree.getAccessibleContext() != null) { 836 // ((AccessibleJTree) tree.getAccessibleContext()).fireVisibleDataPropertyChange(); 837 // } 838 } 839 } 840 } 333 } 334 } 335 } 336 841 337 842 338 private class DocumentListenerImpl … … 846 342 validate(); 847 343 } 848 344 849 345 /** Gives notification that there was an insert into the document. */ 850 346 public void insertUpdate(DocumentEvent e) { 851 347 validate(); 852 348 } 853 349 854 350 /** Gives notification that a portion of the document has been removed. */ 855 351 public void removeUpdate(DocumentEvent e) { … … 857 353 } 858 354 859 public void validate() { 860 ignore = true; 861 ///ystem.err.println("Key released."); 862 StringTokenizer tokenizer = new StringTokenizer(value.getText(), "\\"); 863 TreePath closest = getClosestPath(tokenizer); 864 if(closest == previous) { 865 validateControls(); 866 ignore = false; 867 return; 868 } 869 else { 870 // Clear previous 871 if(previous != null) { 872 // We have a brand new match close up the old one. 873 if(closest != null) { 874 if(getParent(previous) != null && 875 !getParent(previous).toString().equals("[AssignedValues]")) { 876 tree.collapsePath(getParent(previous)); 877 } 878 previous = null; 879 } 880 // We haven't got a match, but we did have a matching path to 881 // this point. Move the selection to previous paths parent. 882 else { 883 tree.setSelectionPath(getParent(previous)); 884 } 355 356 /** Ensures that the value text field and value tree are synchronized. */ 357 private void validate() 358 { 359 String value_text = value.getText(); 360 // System.err.println("\n(Validate) Value text: " + value_text); 361 362 // Ignore the validate() with empty text that occurs when value.setText() is used 363 if (!value_text.equals("") || manual_text_edit_event == true) { 364 TreePath closest_path = getClosestPath(value_text); 365 366 // Select the new path in the tree 367 // The tree selection event this causes must be ignored, since it alters value 368 ignore_tree_selection_event = true; 369 tree.setSelectionPath(closest_path); 370 ignore_tree_selection_event = false; 371 372 // If a folder has been specified, make sure it is expanded 373 if (value_text.endsWith("\\") && !tree.isExpanded(closest_path)) { 374 tree.expandPath(closest_path); 885 375 } 886 887 if(closest != null) { 888 tree.setSelectionPath(closest); 889 // tree.scrollPathToVisible(closest); 890 scrollTreePathToVisible(closest); 891 previous = closest; 892 } 893 } 894 ignore = false; 895 validateControls(); 896 } 897 } 898 899 private class ListSelectionListenerImpl 900 implements ListSelectionListener { 901 public void valueChanged(ListSelectionEvent event) { 902 GValueNode node = (GValueNode)list.getSelectedValue(); 903 value.setText(Utility.stripNL(node.toString()));//formatPath(node.getPath(), false))); 904 value.setCaretPosition(0); 905 } 906 } 907 908 private class ValueListener 909 implements TreeModelListener { 910 /* Called when nodes have been modified, but the model hasn't changed. 911 * @param event Everything you ever wanted to know about model changes 912 * in one tidy TreeModelEvent package. 913 */ 914 public void treeNodesChanged(TreeModelEvent event) { 915 update(); 916 } 917 918 /* Called when nodes have been added to the model. 919 * @param event Everything you ever wanted to know about model changes 920 * in one tidy TreeModelEvent package. 921 */ 922 public void treeNodesInserted(TreeModelEvent event) { 923 update(); 924 } 925 926 /* Called when nodes have been removed from the model. 927 * @param event Everything you ever wanted to know about model changes 928 * in one tidy TreeModelEvent package. 929 */ 930 public void treeNodesRemoved(TreeModelEvent event) { 931 update(); 932 } 933 934 /** Called when nodes have been rearranged within the model. 935 * @param event Everything you ever wanted to know about model changes 936 * in one tidy TreeModelEvent package. 937 */ 938 public void treeStructureChanged(TreeModelEvent event) { 939 update(); 940 } 941 942 private void update() { 943 // Don't bother updating if the metaedit tab isn't selected. 944 if(Gatherer.g_man.getSelectedView() == Gatherer.g_man.metaedit_pane) { 945 vm = null; 946 vm = Gatherer.c_man.getCollection().msm.getValueTree((ElementWrapper)em.getSelectedItem()); 947 if(vm != null) { 948 vm.addTreeModelListener(value_listener); 949 } 950 else { 951 vm = new GValueModel(get("Not_Applicable")); 952 } 953 tree.setModel(vm); 954 tree.repaint(); 376 377 // Make sure the path is visible on the screen 378 scrollTreePathToVisible(closest_path); 379 // One call should be enough, but it isn't in some cases (for some reason) 380 scrollTreePathToVisible(closest_path); 381 382 // Update the status of the buttons 383 metaedit.validateControls(); 955 384 } 956 385 }
Note:
See TracChangeset
for help on using the changeset viewer.