Revision: 20250 http://sourceforge.net/p/gate/code/20250 Author: markagreenwood Date: 2017-07-10 14:43:43 +0000 (Mon, 10 Jul 2017) Log Message: ----------- moved the ontology editor into the plugin.... I think
Added Paths: ----------- gate/branches/sawdust2/plugins/Ontology_Tools/src/gate/gui/docview/ gate/branches/sawdust2/plugins/Ontology_Tools/src/gate/gui/docview/OntologyClassView.java gate/branches/sawdust2/plugins/Ontology_Tools/src/gate/gui/docview/OntologyInstanceView.java Removed Paths: ------------- gate/branches/sawdust2/gate-core/src/main/java/gate/gui/docview/OntologyClassView.java gate/branches/sawdust2/gate-core/src/main/java/gate/gui/docview/OntologyInstanceView.java Deleted: gate/branches/sawdust2/gate-core/src/main/java/gate/gui/docview/OntologyClassView.java =================================================================== --- gate/branches/sawdust2/gate-core/src/main/java/gate/gui/docview/OntologyClassView.java 2017-07-10 14:40:48 UTC (rev 20249) +++ gate/branches/sawdust2/gate-core/src/main/java/gate/gui/docview/OntologyClassView.java 2017-07-10 14:43:43 UTC (rev 20250) @@ -1,1117 +0,0 @@ -/** - * Copyright (c) 1995-2012, The University of Sheffield. See the file - * COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt - * - * This file is part of GATE (see http://gate.ac.uk/), and is free - * software, licenced under the GNU Library General Public License, - * Version 2, June 1991 (in the distribution as file licence.html, - * and also available at http://gate.ac.uk/gate/licence.html). - * - * Thomas Heitz - 14/12/2009 - * - * $Id$ - */ - -package gate.gui.docview; - -import gate.Annotation; -import gate.AnnotationSet; -import gate.FeatureMap; -import gate.Gate; -import gate.LanguageResource; -import gate.Resource; -import gate.creole.ontology.OClass; -import gate.creole.ontology.OConstants; -import gate.creole.ontology.OResource; -import gate.creole.ontology.Ontology; -import gate.creole.ontology.OntologyModificationListener; -import gate.creole.ontology.RDFProperty; -import gate.event.CreoleEvent; -import gate.event.CreoleListener; -import gate.gui.MainFrame; -import gate.gui.annedit.AnnotationData; -import gate.gui.annedit.AnnotationDataImpl; -import gate.gui.ontology.OntologyItemComparator; -import gate.util.GateRuntimeException; -import gate.util.OptionsMap; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.FlowLayout; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.Rectangle; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -import java.util.EventObject; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.Vector; - -import javax.swing.AbstractAction; -import javax.swing.AbstractCellEditor; -import javax.swing.BorderFactory; -import javax.swing.DefaultComboBoxModel; -import javax.swing.JCheckBox; -import javax.swing.JComboBox; -import javax.swing.JLabel; -import javax.swing.JMenuItem; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; -import javax.swing.JTree; -import javax.swing.SwingConstants; -import javax.swing.SwingUtilities; -import javax.swing.Timer; -import javax.swing.UIManager; -import javax.swing.border.Border; -import javax.swing.event.MouseInputAdapter; -import javax.swing.event.TreeExpansionEvent; -import javax.swing.event.TreeSelectionEvent; -import javax.swing.event.TreeSelectionListener; -import javax.swing.event.TreeWillExpandListener; -import javax.swing.text.BadLocationException; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.DefaultTreeModel; -import javax.swing.tree.ExpandVetoException; -import javax.swing.tree.TreeCellEditor; -import javax.swing.tree.TreeCellRenderer; -import javax.swing.tree.TreePath; -import javax.swing.tree.TreeSelectionModel; - -/** - * Document view that displays an ontology class tree to annotate a document. - * - * tick the checkbox of a class to show the instances highlighted in the text - * selected class will be used when creating a new annotation from a text - * selection in the document - * take only the first 20 characters of the selection for the instance name - * and add a number if already existing - * allow multiple ontologies to be used at the same time - * put each ontology in a JPanel with triangle icons to hide/show the panel, - * hidden by default - * open only first level of classes when opening an ontology - * load lazily the ontology trees - * context menu for classes to hide/show them, saved in user configuration - */ -@SuppressWarnings("serial") -public class OntologyClassView extends AbstractDocumentView - implements CreoleListener, OntologyModificationListener { - - public OntologyClassView() { - - colorByClassMap = new HashMap<OClass, Color>(); - highlightedClasses = new HashSet<OClass>(); - highlightsDataByClassMap = new HashMap<OClass, List<TextualDocumentView.HighlightData>>(); - treeByOntologyMap = new HashMap<Ontology, JTree>(); - String prefix = getClass().getName() + '.'; - hiddenClassesSet = userConfig.getSet(prefix + "hiddenclasses"); - itemComparator = new OntologyItemComparator(); - } - - @Override - protected void initGUI() { - - // get a pointer to the text view used to display - // the selected annotations - Iterator<DocumentView> centralViewsIter = owner.getCentralViews().iterator(); - while(textView == null && centralViewsIter.hasNext()){ - DocumentView aView = centralViewsIter.next(); - if(aView instanceof TextualDocumentView) - textView = (TextualDocumentView) aView; - } - textArea = textView.getTextView(); - // get a pointer to the instance view - Iterator<DocumentView> horizontalViewsIter = owner.getHorizontalViews().iterator(); - while(instanceView == null && horizontalViewsIter.hasNext()){ - DocumentView aView = horizontalViewsIter.next(); - if (aView instanceof OntologyInstanceView) { - instanceView = (OntologyInstanceView) aView; - } - } - instanceView.setOwner(owner); - - mainPanel = new JPanel(new GridBagLayout()); - GridBagConstraints gbc = new GridBagConstraints(); - gbc.gridx = 0; - treesPanel = new JPanel(); - treesPanel.setLayout(new GridBagLayout()); - // add a disclosure panel for each loaded ontology in the system - boolean isOntologyLoaded = false; - List<LanguageResource> resources = - gate.Gate.getCreoleRegister().getPublicLrInstances(); - for (LanguageResource resource : resources) { - if (resource instanceof Ontology) { - loadOntology((Ontology) resource); - isOntologyLoaded = true; - } - } - gbc.weightx = 1; - gbc.weighty = 1; - gbc.fill = GridBagConstraints.BOTH; - gbc.anchor = GridBagConstraints.NORTHWEST; - mainPanel.add(new JScrollPane(treesPanel), gbc); - setComboBox = new JComboBox<String>(); - setComboBox.setEditable(true); - setComboBox.setToolTipText( - "Annotation set where to load/save the annotations"); - gbc.weighty = 0; - gbc.fill = GridBagConstraints.HORIZONTAL; - gbc.anchor = GridBagConstraints.SOUTH; - mainPanel.add(setComboBox, gbc); - - initListeners(); - - // fill the annotation sets list - List<String> annotationSets = new ArrayList<String>(); - annotationSets.add(""); - annotationSets.addAll(document.getAnnotationSetNames()); - Collections.sort(annotationSets); - setComboBox.setModel(new DefaultComboBoxModel<String>( - new Vector<String>(annotationSets))); - - if (isOntologyLoaded) { - // find the first set that contains annotations used before by this view - selectedSet = ""; - for (int i = 0; i < setComboBox.getItemCount(); i++) { - String setName = setComboBox.getItemAt(i); - if (setColorTreeNodesWhenInstancesFound(setName)) { - selectedSet = setName; - break; - } - } - setComboBox.setSelectedItem(selectedSet); - } else { - messageLabel = new JLabel( - "<html><p><font color=red>Load at least one ontology."); - messageLabel.setHorizontalAlignment(SwingConstants.CENTER); - messageLabel.setBorder(BorderFactory.createEmptyBorder(5, 2, 5, 2)); - messageLabel.setBackground( - UIManager.getColor("Tree.selectionBackground")); - gbc = new GridBagConstraints(); - treesPanel.add(messageLabel, gbc); - } - } - - protected void initListeners() { - - Gate.getCreoleRegister().addCreoleListener(this); - - setComboBox.addItemListener(new ItemListener() { - @Override - public void itemStateChanged(ItemEvent e) { - selectedSet = (String) setComboBox.getSelectedItem(); - setColorTreeNodesWhenInstancesFound(selectedSet); - // unselect annotations - SwingUtilities.invokeLater(new Runnable() { @Override - public void run() { - for (OClass oClass : highlightedClasses) { - if (highlightsDataByClassMap.containsKey(oClass)) { - textView.removeHighlights(highlightsDataByClassMap.get(oClass)); - } - } - highlightsDataByClassMap.clear(); - highlightedClasses.clear(); - // update showing trees - for (JTree tree : treeByOntologyMap.values()) { - if (tree.isShowing()) { - tree.revalidate(); - } - } - }}); - } - }); - - // a listener that stops or restarts a timer which calls an action - mouseStoppedMovingAction = new MouseStoppedMovingAction(); - mouseMovementTimer = new javax.swing.Timer( - MOUSE_MOVEMENT_TIMER_DELAY, mouseStoppedMovingAction); - mouseMovementTimer.setRepeats(false); - textMouseListener = new TextMouseListener(); - } - - @Override - protected void registerHooks() { - textArea.addMouseListener(textMouseListener); - textArea.addMouseMotionListener(textMouseListener); - // reselect annotations - SwingUtilities.invokeLater(new Runnable() { @Override - public void run() { - for (OClass oClass : new HashSet<OClass>(highlightedClasses)) { - if (highlightsDataByClassMap.containsKey(oClass)) { - textView.addHighlights(highlightsDataByClassMap.get(oClass)); - } - } - }}); - // show the instance view at the bottom - if (!instanceView.isActive()) { - owner.setBottomView(owner.horizontalViews.indexOf(instanceView)); - } - } - - @Override - protected void unregisterHooks() { - textArea.removeMouseListener(textMouseListener); - textArea.removeMouseMotionListener(textMouseListener); - // unselect annotations - SwingUtilities.invokeLater(new Runnable() { @Override - public void run() { - for (OClass oClass : highlightedClasses) { - if (highlightsDataByClassMap.containsKey(oClass)) { - textView.removeHighlights(highlightsDataByClassMap.get(oClass)); - } - } - }}); - // hide the instance view at the bottom - if (instanceView.isActive()) { - owner.setBottomView(-1); - } - } - - @Override - public void cleanup() { - super.cleanup(); - Gate.getCreoleRegister().removeCreoleListener(this); - document = null; - // save hidden classes to be reused next time - String prefix = getClass().getName() + '.'; - userConfig.put(prefix + "hiddenclasses", hiddenClassesSet); - } - - @Override - public Component getGUI() { - return mainPanel; - } - - @Override - public int getType() { - return VERTICAL; - } - - @Override - public void resourceLoaded(CreoleEvent e) { - if (e.getResource() instanceof Ontology) { - if (messageLabel != null - && treesPanel.isAncestorOf(messageLabel)) { - treesPanel.remove(messageLabel); - // find the first set that contains annotations used before by this view - selectedSet = ""; - for (int i = 0; i < setComboBox.getItemCount(); i++) { - String setName = setComboBox.getItemAt(i); - if (setColorTreeNodesWhenInstancesFound(setName)) { - selectedSet = setName; - break; - } - } - setComboBox.setSelectedItem(selectedSet); - } - Ontology ontology = (Ontology) e.getResource(); - loadOntology(ontology); - // listen to modification of classes in the ontology to rebuild the tree - ontology.addOntologyModificationListener(this); - } - } - - @Override - public void resourceUnloaded(CreoleEvent e) { - if (e.getResource() instanceof Ontology) { - Ontology ontology = (Ontology) e.getResource(); - JTree tree = treeByOntologyMap.remove(ontology); - for (Component component : treesPanel.getComponents()) { - if (component instanceof JPanel - && ((JPanel) component).isAncestorOf(tree)) { - treesPanel.remove(component); - } - } - treesPanel.revalidate(); - } - } - - @Override - public void datastoreOpened(CreoleEvent e) { /* do nothing */ } - - @Override - public void datastoreCreated(CreoleEvent e) { /* do nothing */ } - - @Override - public void datastoreClosed(CreoleEvent e) { /* do nothing */ } - - @Override - public void resourceRenamed(Resource resource, String oldName, - String newName) { /* do nothing */ } - @Override - public void resourceRelationChanged(Ontology ontology, OResource - resource1, OResource resource2, int eventType) { /* do nothing */ } - - @Override - public void resourcePropertyValueChanged(Ontology ontology, OResource - resource, RDFProperty property, Object value, int eventType) { - /* do nothing */ } - - @Override - public void resourcesRemoved(Ontology ontology, String[] resources) { } - - @Override - public void resourceAdded(Ontology ontology, OResource resource) { - if (resource instanceof OClass) { - final JTree tree = treeByOntologyMap.get(ontology); - DefaultMutableTreeNode node = - (DefaultMutableTreeNode) tree.getModel().getRoot(); - final Enumeration<?> enumeration = node.preorderEnumeration(); - SwingUtilities.invokeLater(new Runnable() { @Override - public void run() { - // traverse the expanded class tree and update all the nodes - while (enumeration.hasMoreElements()) { - DefaultMutableTreeNode node = - (DefaultMutableTreeNode) enumeration.nextElement(); - Object userObject = node.getUserObject(); - if (userObject != null - && !userObject.equals("Loading...")) { - // node already expanded - OClass oClass = (OClass) userObject; - Set<OClass> classes = oClass.getSubClasses( - OConstants.Closure.DIRECT_CLOSURE); - // readd all the children node - addNodes(tree, node, classes, false); - } - } - }}); - } - } - - @Override - public void ontologyReset(Ontology ontology) { /* do nothing */ } - - /** - * Extract annotations that have been created by this view and - * colored the corresponding tree class node if found. - * @param setName the annotation set name to search - * @return true if and only if at least one annotation has been found - */ - protected boolean setColorTreeNodesWhenInstancesFound(String setName) { - boolean returnValue = false; - List<LanguageResource> resources = - gate.Gate.getCreoleRegister().getPublicLrInstances(); - Map<String, Ontology> ontologyMap = new HashMap<String, Ontology>(); - for (LanguageResource resource : resources) { - if (resource instanceof Ontology) { - Ontology ontology = (Ontology) resource; - String ontologyName = ontology.getDefaultNameSpace(); - ontologyName = ontologyName.substring(0, ontologyName.length()-1); - ontologyMap.put(ontologyName, ontology); - } - } - for (Annotation annotation : - document.getAnnotations(setName).get(ANNOTATION_TYPE)) { - FeatureMap features = annotation.getFeatures(); - if (features.get(ONTOLOGY) != null - && features.get(CLASS) != null - && features.get(INSTANCE) != null) { - // find the corresponding ontology - Ontology ontology = ontologyMap.get(features.get(ONTOLOGY)); - if (ontology != null) { - // choose a background color for the annotation type tree node - OClass oClass = ontology.getOClass(ontology - .createOURI((String) features.get(CLASS))); - if (oClass != null) { - colorByClassMap.put(oClass, - AnnotationSetsView.getColor(setName, oClass.getName())); - returnValue = true; - } - } - } - } - return returnValue; - } - - /** - * Add the ontology in a disclosure panel, closed at start. - * @param ontology ontology to display - */ - protected void loadOntology(final Ontology ontology) { - - // create the class tree - final JTree tree = new JTree(new Object[]{"Loading..."}); - treeByOntologyMap.put(ontology, tree); - tree.setRootVisible(false); - tree.setShowsRootHandles(true); - tree.setEditable(true); - tree.getSelectionModel().setSelectionMode( - TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); - - final JPanel treePanel = new JPanel(new BorderLayout()); - final JCheckBox disclosureCheckBox = new JCheckBox( - ontology.getName(), MainFrame.getIcon("closed"), false); - disclosureCheckBox.setSelectedIcon(MainFrame.getIcon("expanded")); - treePanel.add(disclosureCheckBox, BorderLayout.NORTH); - - // show/hide the tree when clicking the disclosure checkbox - disclosureCheckBox.addActionListener(new ActionListener() { - boolean isTreeBuilt = false; - @Override - public void actionPerformed(ActionEvent e) { - if (disclosureCheckBox.isSelected()) { - if (!isTreeBuilt) { - tree.expandRow(0); // expands "Loading..." node - buildClassTree(tree, ontology); - isTreeBuilt = true; - } - treePanel.add(tree, BorderLayout.CENTER); - } else { - treePanel.remove(tree); - } - treesPanel.repaint(); - } - }); - - // context menu to show root classes - disclosureCheckBox.addMouseListener(new MouseAdapter() { - @Override - public void mousePressed(MouseEvent e) { processMouseEvent(e); } - @Override - public void mouseReleased(MouseEvent e) { processMouseEvent(e); } - @Override - public void mouseClicked(MouseEvent e) { processMouseEvent(e); } - protected void processMouseEvent(MouseEvent e) { - JPopupMenu popup = new JPopupMenu(); - if (e.isPopupTrigger()) { - popup.add(new JMenuItem( - new AbstractAction("Show all root classes") { - @Override - public void actionPerformed(ActionEvent e) { - if (!disclosureCheckBox.isSelected()) { - disclosureCheckBox.doClick(); - } - hiddenClassesSet.clear(); - DefaultMutableTreeNode node = (DefaultMutableTreeNode) - tree.getModel().getRoot(); - final Set<OClass> classes = ontology.getOClasses(true); - // add first level nodes to the tree - addNodes(tree, node, classes, false); - } - })); - popup.show(e.getComponent(), e.getX(), e.getY()); - } - } - }); - - // when a class is selected in the tree update the instance table - tree.getSelectionModel().addTreeSelectionListener( - new TreeSelectionListener() { - @Override - public void valueChanged(TreeSelectionEvent e) { - if (e.getNewLeadSelectionPath() == null) { - if (treeByOntologyMap.get(selectedClass.getOntology()).equals(tree)){ - // only nullify selectedClass if unselect from the same tree - selectedClass = null; - } - } else { - if (tree.getSelectionCount() == 1) { // a class is selected - DefaultMutableTreeNode node = (DefaultMutableTreeNode) - e.getNewLeadSelectionPath().getLastPathComponent(); - selectedClass = (OClass) node.getUserObject(); - } else { // several classes are selected - selectedClass = null; - } - // clear selection in other trees - for (JTree aTree : treeByOntologyMap.values()) { - if (!aTree.equals(tree)) { - aTree.clearSelection(); - } - } - } - instanceView.updateInstanceTable(selectedClass); - } - } - ); - - // context menu to hide/show classes - tree.addMouseListener(new MouseAdapter() { - @Override - public void mousePressed(MouseEvent e) { - TreePath path = tree.getClosestPathForLocation(e.getX(), e.getY()); - if (e.isPopupTrigger() - && !tree.isPathSelected(path)) { - // if right click outside the selection then reset selection - tree.getSelectionModel().setSelectionPath(path); - } - processMouseEvent(e); - } - @Override - public void mouseReleased(MouseEvent e) { - processMouseEvent(e); - } - @Override - public void mouseClicked(MouseEvent e) { - processMouseEvent(e); - } - protected void processMouseEvent(MouseEvent e) { - JPopupMenu popup = new JPopupMenu(); - if (!e.isPopupTrigger()) { return; } - popup.add(new JMenuItem( - new AbstractAction("Hide selected classes") { - @Override - public void actionPerformed(ActionEvent e) { - DefaultTreeModel treeModel = (DefaultTreeModel) tree.getModel(); - TreePath[] selectedPaths = tree.getSelectionPaths(); - for (TreePath selectedPath : selectedPaths) { - DefaultMutableTreeNode node = (DefaultMutableTreeNode) - selectedPath.getLastPathComponent(); - if (node.getParent() != null) { - treeModel.removeNodeFromParent(node); - Object userObject = node.getUserObject(); - OClass oClass = (OClass) userObject; - hiddenClassesSet.add(oClass.getONodeID().toString()); - } - } - } - })); - - if (tree.getSelectionCount() == 1) { - popup.add(new JMenuItem(new AbstractAction("Show all sub classes") { - @Override - public void actionPerformed(ActionEvent e) { - DefaultMutableTreeNode node = (DefaultMutableTreeNode) - tree.getSelectionPath().getLastPathComponent(); - Object userObject = node.getUserObject(); - OClass oClass = (OClass) userObject; - Set<OClass> classes = oClass.getSubClasses( - OClass.Closure.DIRECT_CLOSURE); - addNodes(tree, node, classes, false); - } - })); - } - popup.show(e.getComponent(), e.getX(), e.getY()); - } - }); - - GridBagConstraints gbc = new GridBagConstraints(); - gbc.fill = GridBagConstraints.BOTH; - gbc.anchor = GridBagConstraints.NORTHWEST; - gbc.gridx = 0; - gbc.weightx = 1; - gbc.weighty = 1; - treesPanel.add(treePanel, gbc); - } - - /** - * Build the class tree from the ontology. - * Based on {@link gate.gui.ontology.OntologyEditor#rebuildModel()}. - * @param tree tree to build - * @param ontology ontology to use - */ - protected void buildClassTree(final JTree tree, Ontology ontology) { - if (ontology == null) { return; } - - // listener to lazily create children nodes - tree.addTreeWillExpandListener(new TreeWillExpandListener() { - @Override - public void treeWillExpand(TreeExpansionEvent event) - throws ExpandVetoException { - DefaultMutableTreeNode node = (DefaultMutableTreeNode) - event.getPath().getLastPathComponent(); - DefaultMutableTreeNode nodeFirstChild = - (DefaultMutableTreeNode) node.getChildAt(0); - if (nodeFirstChild.getUserObject().equals("Loading...")) { - // if this node has not already been expanded - node.removeAllChildren(); - Object userObject = node.getUserObject(); - OClass oClass = (OClass) userObject; - Set<OClass> classes = - oClass.getSubClasses(OClass.Closure.DIRECT_CLOSURE); - // add children nodes to the current tree node - addNodes(tree, node, classes, true); - } - } - @Override - public void treeWillCollapse(TreeExpansionEvent event) - throws ExpandVetoException { /* do nothing */ } - }); - - final DefaultMutableTreeNode node = new DefaultMutableTreeNode(null, true); - final Set<OClass> classes = ontology.getOClasses(true); - // add first level nodes to the tree - addNodes(tree, node, classes, true); - SwingUtilities.invokeLater(new Runnable() { @Override - public void run() { - tree.setModel(new DefaultTreeModel(node)); - tree.setCellRenderer(new ClassTreeCellRenderer()); - tree.setCellEditor(new ClassTreeCellEditor(tree)); - DefaultMutableTreeNode node = (DefaultMutableTreeNode) - tree.getModel().getRoot(); - Enumeration<?> enumeration = node.children(); - // expand tree until second level - while (enumeration.hasMoreElements()) { - node = (DefaultMutableTreeNode) enumeration.nextElement(); - tree.expandPath(new TreePath(node.getPath())); - } - }}); - } - - /** - * Add children nodes to the parent node in the tree. - * @param tree tree to update - * @param parent parent node - * @param newChildren children classes to add - * @param filterClasses if children nodes contain hidden classes - * then don't add them. - */ - protected void addNodes(JTree tree, DefaultMutableTreeNode parent, - Set<OClass> newChildren, - boolean filterClasses) { - // list the existing children classes of the parent node - List<OClass> children = new ArrayList<OClass>(); - for (int i = 0; i < parent.getChildCount(); i++) { - DefaultMutableTreeNode node = - (DefaultMutableTreeNode) parent.getChildAt(i); - Object userObject = node.getUserObject(); - if (userObject instanceof OClass) { - OClass oClass = (OClass) userObject; - children.add(oClass); - } else if (userObject.equals("Loading...")) { - parent.removeAllChildren(); - children.clear(); - break; - } - } - int index = -1; - DefaultTreeModel treeModel = (DefaultTreeModel) tree.getModel(); - List<OClass> subClasses = new ArrayList<OClass>(newChildren); - Collections.sort(subClasses, itemComparator); - // for each children classes to add to the parent node - for (OClass subClass : subClasses) { - index++; - if (index > parent.getChildCount()) { index = parent.getChildCount(); } - if (filterClasses) { - if (hiddenClassesSet.contains(subClass.getONodeID().toString())) { - // this class is filtered so skip it - continue; - } - } else { - hiddenClassesSet.remove(subClass.getONodeID().toString()); - } - DefaultMutableTreeNode subNode = new DefaultMutableTreeNode(subClass); - if (!filterClasses || !children.contains(subClass)) { - if (!subClass.getSubClasses(OClass.Closure.DIRECT_CLOSURE).isEmpty()) { - subNode.insert(new DefaultMutableTreeNode("Loading..."), 0); - } - } - if (!children.contains(subClass)) { - // add the children node if not already existing - treeModel.insertNodeInto(subNode, parent, index); - } - } - tree.expandPath(new TreePath(parent.getPath())); - } - - /** - * A mouse listener used for events in the text view. - * Stop or restart the timer that will call {@link MouseStoppedMovingAction}. - * Based on {@link AnnotationSetsView.TextMouseListener}. - */ - protected class TextMouseListener extends MouseInputAdapter { - @Override - public void mouseDragged(MouseEvent e){ - //do not create annotations while dragging - mouseMovementTimer.stop(); - } - @Override - public void mouseMoved(MouseEvent e){ - //this triggers select annotation leading to edit annotation or new - //annotation actions - //ignore movement if CTRL pressed or dragging - int modEx = e.getModifiersEx(); - if((modEx & MouseEvent.CTRL_DOWN_MASK) != 0){ - mouseMovementTimer.stop(); - return; - } - if((modEx & MouseEvent.BUTTON1_DOWN_MASK) != 0){ - mouseMovementTimer.stop(); - return; - } - //check the text location is real - int textLocation = textArea.viewToModel(e.getPoint()); - try { - Rectangle viewLocation = textArea.modelToView(textLocation); - //expand the rectangle a bit - int error = 10; - viewLocation = new Rectangle(viewLocation.x - error, - viewLocation.y - error, - viewLocation.width + 2*error, - viewLocation.height + 2*error); - if(viewLocation.contains(e.getPoint())){ - mouseStoppedMovingAction.setTextLocation(textLocation); - }else{ - mouseStoppedMovingAction.setTextLocation(-1); - } - } - catch(BadLocationException ble) { - throw new GateRuntimeException(ble); - }finally{ - mouseMovementTimer.restart(); - } - } - @Override - public void mouseExited(MouseEvent e){ - mouseMovementTimer.stop(); - } - } - - /** - * Add the text selection to the filter instance table to enable creating - * a new instance from the selection or adding it as a new label to an - * existing instance. - * Based on {@link AnnotationSetsView.MouseStoppedMovingAction}. - */ - protected class MouseStoppedMovingAction extends AbstractAction { - @Override - public void actionPerformed(ActionEvent evt) { - List<LanguageResource> resources = - gate.Gate.getCreoleRegister().getPublicLrInstances(); - Map<String, Ontology> ontologyMap = new HashMap<String, Ontology>(); - for (LanguageResource resource : resources) { - if (resource instanceof Ontology) { - Ontology ontology = (Ontology) resource; - String ontologyName = ontology.getDefaultNameSpace(); - ontologyName = ontologyName.substring(0, ontologyName.length()-1); - ontologyMap.put(ontologyName, ontology); - } - } - // check for annotations at mouse location - String setName = (String) setComboBox.getSelectedItem(); - for (Annotation annotation : document.getAnnotations(setName) - .get(ANNOTATION_TYPE).get(Math.max(0l, textLocation-1), - Math.min(document.getContent().size(), textLocation+1))) { - final FeatureMap features = annotation.getFeatures(); - if (features.get(ONTOLOGY) != null - && features.get(CLASS) != null - && features.get(INSTANCE) != null) { - // find the corresponding ontology - final Ontology ontology = - ontologyMap.get(features.get(ONTOLOGY)); - if (ontology != null) { - OClass oClass = ontology.getOClass(ontology - .createOURI((String) features.get(CLASS))); - // find if the annotation class is highlighted - if (oClass != null - && highlightedClasses.contains(oClass)) { - final JTree tree = treeByOntologyMap.get(ontology); - DefaultMutableTreeNode node = - (DefaultMutableTreeNode) tree.getModel().getRoot(); - Enumeration<?> nodesEnum = node.preorderEnumeration(); - boolean done = false; - // traverse the class tree - while(!done && nodesEnum.hasMoreElements()) { - node = (DefaultMutableTreeNode) nodesEnum.nextElement(); - done = node.getUserObject() instanceof OClass - && node.getUserObject().equals(oClass); - } - if (done) { - // select the class in the tree - TreePath nodePath = new TreePath(node.getPath()); - tree.setSelectionPath(nodePath); - tree.scrollPathToVisible(nodePath); - SwingUtilities.invokeLater(new Runnable() { @Override - public void run() { - // select the annotation in the instances table - instanceView.selectInstance(ontology.getOInstance( - ontology.createOURI((String) features.get(INSTANCE)))); - }}); - break; - } - } - } - } - } - - int start = textArea.getSelectionStart(); - int end = textArea.getSelectionEnd(); - String selectedText = textArea.getSelectedText(); - if (textLocation == -1 - || selectedClass == null - || selectedText == null - || start > textLocation - || end < textLocation - || start == end) { - return; - } - // remove selection - textArea.setSelectionStart(start); - textArea.setSelectionEnd(start); - instanceView.addSelectionToFilter(selectedSet, selectedText, start, end); - } - - public void setTextLocation(int textLocation){ - this.textLocation = textLocation; - } - int textLocation; - } - - public void setClassHighlighted(final OClass oClass, boolean isHighlighted) { - final JTree tree = treeByOntologyMap.get(oClass.getOntology()); - if (isHighlighted) { - // find all annotations for the class - final List<AnnotationData> annotationsData = - new ArrayList<AnnotationData>(); - AnnotationSet annotationSet = document.getAnnotations(selectedSet); - String ontologyName = oClass.getOntology().getDefaultNameSpace(); - ontologyName = ontologyName.substring(0, ontologyName.length()-1); - for (Annotation annotation : annotationSet.get(ANNOTATION_TYPE)) { - FeatureMap features = annotation.getFeatures(); - if (features.get(ONTOLOGY) != null - && features.get(ONTOLOGY).equals(ontologyName) - && features.get(CLASS) != null - && features.get(CLASS).equals(oClass.getONodeID().toString()) - && features.get(INSTANCE) != null) { - annotationsData.add(new AnnotationDataImpl(annotationSet,annotation)); - } - } - highlightedClasses.add(oClass); - if (annotationsData.isEmpty()) { - // no instance annotation for this class - colorByClassMap.remove(oClass); - SwingUtilities.invokeLater(new Runnable() { @Override - public void run() { - if (highlightsDataByClassMap.containsKey(oClass)) { - textView.removeHighlights(highlightsDataByClassMap.get(oClass)); - } - highlightsDataByClassMap.remove(oClass); - tree.repaint(); - }}); - } else { - final Color color; - if (colorByClassMap.containsKey(oClass)) { - color = colorByClassMap.get(oClass); - } else { - color = AnnotationSetsView.getColor(selectedSet,oClass.getName()); - colorByClassMap.put(oClass, color); - } - SwingUtilities.invokeLater(new Runnable() { @Override - public void run() { - highlightsDataByClassMap.put(oClass, - textView.addHighlights(annotationsData, color)); - tree.repaint(); - }}); - } - } else { // if (!isHighlighted) - highlightedClasses.remove(oClass); - SwingUtilities.invokeLater(new Runnable() { @Override - public void run() { - if (highlightsDataByClassMap.containsKey(oClass)) { - textView.removeHighlights(highlightsDataByClassMap.get(oClass)); - } - tree.repaint(); - }}); - } - } - - /** - * To see if it's worth using it to optimise highlights display. - * @param set set - * @param annotation annotation - * @param oClass class - * @param tree tree - */ - public void highlightInstance(AnnotationSet set, Annotation annotation, - final OClass oClass, final JTree tree) { - final AnnotationData annotationData = new AnnotationDataImpl(set, annotation); - final List<TextualDocumentView.HighlightData> highlightsData = highlightsDataByClassMap.containsKey(oClass) ? - highlightsDataByClassMap.get(oClass) : new ArrayList<TextualDocumentView.HighlightData>(); - highlightedClasses.add(oClass); - final Color color; - if (colorByClassMap.containsKey(oClass)) { - color = colorByClassMap.get(oClass); - } else { - color = AnnotationSetsView.getColor(set.getName(),oClass.getName()); - colorByClassMap.put(oClass, color); - } - SwingUtilities.invokeLater(new Runnable() { @Override - public void run() { - highlightsData.add(textView.addHighlight(annotationData, color)); - highlightsDataByClassMap.put(oClass, highlightsData); - tree.repaint(); - }}); - } - - protected class ClassTreeCellRenderer extends JPanel - implements TreeCellRenderer { - - protected Object userObject; - protected JCheckBox checkBox; - protected JLabel label; - private Color selectionColor = - UIManager.getColor("Tree.selectionBackground"); - private Color backgroundColor = UIManager.getColor("Tree.textBackground"); - private Border normalBorder = - BorderFactory.createLineBorder(backgroundColor, 1); - private Border selectionBorder = - BorderFactory.createLineBorder(selectionColor, 1); - - protected Object getUserObject() { - return userObject; - } - - protected JCheckBox getCheckBox() { - return checkBox; - } - - public ClassTreeCellRenderer() { - setLayout(new FlowLayout(FlowLayout.LEFT, 2, 0)); - setBorder(normalBorder); - setOpaque(true); - setBackground(backgroundColor); - checkBox = new JCheckBox(); - checkBox.setMargin(new Insets(0, 0, 0, 0)); - checkBox.setOpaque(true); - checkBox.setBackground(backgroundColor); - add(checkBox); - label = new JLabel(); - label.setOpaque(true); - label.setBackground(backgroundColor); - add(label); - } - - @Override - public Component getTreeCellRendererComponent(JTree tree, Object value, - boolean isSelected, boolean isExpanded, - boolean isLeaf, int row, boolean hasFocus) { - DefaultMutableTreeNode node = (DefaultMutableTreeNode) value; - userObject = node.getUserObject(); - if (node.getUserObject() == null) { return this; } - OClass oClass = (OClass) node.getUserObject(); - checkBox.setSelected(highlightedClasses.contains(oClass)); - checkBox.setBackground(isSelected ? selectionColor : backgroundColor); - label.setText(oClass.getName()); - label.setBackground(colorByClassMap.containsKey(oClass) ? - colorByClassMap.get(oClass) : isSelected ? - selectionColor : backgroundColor); - setBackground(isSelected ? selectionColor : backgroundColor); - setBorder(isSelected ? selectionBorder : normalBorder); - - return this; - } - } - - protected class ClassTreeCellEditor extends AbstractCellEditor - implements TreeCellEditor { - - ClassTreeCellRenderer renderer = new ClassTreeCellRenderer(); - JTree tree; - - public ClassTreeCellEditor(JTree tree) { - this.tree = tree; - } - - @Override - public Object getCellEditorValue() { - boolean isSelected = renderer.getCheckBox().isSelected(); - Object userObject = renderer.getUserObject(); - OClass oClass = (OClass) userObject; - // show/hide highlights according to the checkbox state - setClassHighlighted(oClass, isSelected); - return userObject; - } - - @Override - public boolean isCellEditable(EventObject event) { - boolean returnValue = false; - if (event instanceof MouseEvent) { - MouseEvent mouseEvent = (MouseEvent) event; - TreePath path = tree.getPathForLocation(mouseEvent.getX(), - mouseEvent.getY()); - if (path != null) { - Object node = path.getLastPathComponent(); - if ((node != null) && (node instanceof DefaultMutableTreeNode)) { - Rectangle r = tree.getPathBounds(path); - int x = mouseEvent.getX() - r.x; - JCheckBox checkbox = renderer.getCheckBox(); - // checks if the mouse click was on the checkbox not the label - returnValue = x > 0 && x < checkbox.getPreferredSize().width; - } - } - } - return returnValue; - } - - @Override - public Component getTreeCellEditorComponent(final JTree tree, Object value, - boolean selected, boolean expanded, boolean leaf, int row) { - - // reuse renderer as an editor - Component editor = renderer.getTreeCellRendererComponent(tree, value, - true, expanded, leaf, row, true); - - // stop editing when checkbox has state changed - renderer.getCheckBox().addItemListener(new ItemListener() { - @Override - public void itemStateChanged(ItemEvent itemEvent) { - stopCellEditing(); - } - }); - - return editor; - } - } - - public String getSelectedSet() { - return selectedSet; - } - - // external resources - protected TextualDocumentView textView; - protected JTextArea textArea; - protected OntologyInstanceView instanceView; - - // UI components - protected JPanel mainPanel; - protected JLabel messageLabel; - protected JPanel treesPanel; - protected JComboBox<String> setComboBox; - - // local objects - /** Class that has the lead selection in the focused ontology tree. */ - protected OClass selectedClass; - /** Classes highlighted in the document with their checkboxes ticked - * in the class tree. */ - protected Set<OClass> highlightedClasses; - /** Colors for class and their instances only if the latter exist. */ - protected Map<OClass, Color> colorByClassMap; - /** HighlightData list for each class. */ - protected Map<OClass, List<TextualDocumentView.HighlightData>> highlightsDataByClassMap; - /** Link trees with their ontologies. */ - protected Map<Ontology, JTree> treeByOntologyMap; - /** Classes to hide in the trees. */ - protected LinkedHashSet<String> hiddenClassesSet; - /** Annotation set name where to read/save the instance annotations. */ - protected String selectedSet; - protected OntologyItemComparator itemComparator; - protected MouseStoppedMovingAction mouseStoppedMovingAction; - protected TextMouseListener textMouseListener; - protected Timer mouseMovementTimer; - protected static final int MOUSE_MOVEMENT_TIMER_DELAY = 500; - protected OptionsMap userConfig = Gate.getUserConfig(); - - // constants for annotation feature, annotation type - protected static final String ONTOLOGY = - gate.creole.ANNIEConstants.LOOKUP_ONTOLOGY_FEATURE_NAME; - protected static final String CLASS = - gate.creole.ANNIEConstants.LOOKUP_CLASS_FEATURE_NAME; - protected static final String INSTANCE = - gate.creole.ANNIEConstants.LOOKUP_INSTANCE_FEATURE_NAME; - protected static final String ANNOTATION_TYPE = "Mention"; -} Deleted: gate/branches/sawdust2/gate-core/src/main/java/gate/gui/docview/OntologyInstanceView.java =================================================================== --- gate/branches/sawdust2/gate-core/src/main/java/gate/gui/docview/OntologyInstanceView.java 2017-07-10 14:40:48 UTC (rev 20249) +++ gate/branches/sawdust2/gate-core/src/main/java/gate/gui/docview/OntologyInstanceView.java 2017-07-10 14:43:43 UTC (rev 20250) @@ -1,897 +0,0 @@ -/** - * Copyright (c) 1995-2012, The University of Sheffield. See the file - * COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt - * - * This file is part of GATE (see http://gate.ac.uk/), and is free - * software, licenced under the GNU Library General Public License, - * Version 2, June 1991 (in the distribution as file licence.html, - * and also available at http://gate.ac.uk/gate/licence.html). - * - * Thomas Heitz - 17/12/2009 - * - * $Id$ - */ - -package gate.gui.docview; - -import gate.Annotation; -import gate.AnnotationSet; -import gate.Factory; -import gate.gui.Handle; -import gate.gui.MainFrame; -import gate.gui.ontology.OntologyEditor; -import gate.swing.XJTable; -import gate.creole.ontology.*; -import gate.util.InvalidOffsetException; -import gate.util.GateRuntimeException; -import gate.util.Out; -import gate.util.Strings; - -import javax.swing.*; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; -import javax.swing.table.DefaultTableCellRenderer; -import javax.swing.table.DefaultTableModel; -import javax.swing.table.TableCellEditor; -import java.awt.*; -import java.awt.event.*; -import java.text.Collator; -import java.util.*; -import java.util.List; -import java.util.Timer; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Document view that shows two tables: one instances and one for properties. - * The instances table is linked with the OntologyClassView class selection - * and the properties table is linked with the instances view. - * <br> - * Two buttons allow to add a new instance from the text selection in the - * document or as a new label for the selected instance. - * <br> - * You can filter the instances table, delete instances and set properties - * that are defined in the ontology as object properties. - */ -@SuppressWarnings("serial") -public class OntologyInstanceView extends AbstractDocumentView { - - public OntologyInstanceView() { - - instances = new HashSet<OInstance>(); - setProperties = new HashSet<ObjectProperty>(); - properties = new HashSet<ObjectProperty>(); - classesByPropertyMap = new HashMap<String, Set<OClass>>(); - } - - @Override - protected void initGUI() { - - // get a pointer to the text view used to display - // the selected annotations - Iterator<DocumentView> centralViewsIter = owner.getCentralViews().iterator(); - while(textView == null && centralViewsIter.hasNext()){ - DocumentView aView = centralViewsIter.next(); - if(aView instanceof TextualDocumentView) - textView = (TextualDocumentView) aView; - } - // get a pointer to the class view - Iterator<DocumentView> verticalViewsIter = owner.getVerticalViews().iterator(); - while(classView == null && verticalViewsIter.hasNext()){ - DocumentView aView = verticalViewsIter.next(); - if (aView instanceof OntologyClassView) { - classView = (OntologyClassView) aView; - } - } - classView.setOwner(owner); - - mainPanel = new JPanel(new BorderLayout()); - - // filter and buttons at the top - JPanel filterPanel = new JPanel(new GridBagLayout()); - GridBagConstraints gbc = new GridBagConstraints(); - JLabel filterLabel = new JLabel("Filter: "); - filterPanel.add(filterLabel, gbc); - gbc.fill = GridBagConstraints.HORIZONTAL; - gbc.weightx = 1; - filterPanel.add(filterTextField = new JTextField(20), gbc); - gbc.fill = GridBagConstraints.NONE; - gbc.weightx = 0; - filterTextField.setToolTipText("Filter the instance table on labels"); - clearFilterButton = new JButton(); - clearFilterButton.setBorder(BorderFactory.createEmptyBorder()); - filterPanel.add(clearFilterButton, gbc); - hiddenInstancesLabel = new JLabel(" 0 hidden "); - filterPanel.add(hiddenInstancesLabel, gbc); - JPanel filterButtonsPanel = new JPanel(); - newInstanceButton = new JButton("New Inst."); - newInstanceButton.setEnabled(false); - newInstanceButton.setToolTipText("New instance from the selection"); - newInstanceButton.setMnemonic(KeyEvent.VK_N); - filterButtonsPanel.add(newInstanceButton); - addLabelButton = new JButton("Add to Selected Inst."); - addLabelButton.setEnabled(false); - addLabelButton.setToolTipText( - "Add label from selection to the selected instance"); - addLabelButton.setMnemonic(KeyEvent.VK_A); - filterButtonsPanel.add(addLabelButton); - filterPanel.add(filterButtonsPanel, gbc); - - mainPanel.add(filterPanel, BorderLayout.NORTH); - - // tables at the bottom - JPanel tablesPanel = new JPanel(new GridLayout(1, 2)); - instanceTable = new XJTable() { - @Override - public boolean isCellEditable(int row, int column) { - return false; - } - }; - DefaultTableModel model = new DefaultTableModel(); - model.addColumn("Instance"); - model.addColumn("Labels"); - instanceTable.setModel(model); - tablesPanel.add(new JScrollPane(instanceTable)); - propertyTable = new XJTable(){ - @Override - public boolean isCellEditable(int row, int column) { - // property values are editable - return convertColumnIndexToModel(column) == 1; - } - }; - model = new DefaultTableModel(); - model.addColumn("Property"); - model.addColumn("Value"); - propertyTable.setModel(model); - tablesPanel.add(new JScrollPane(propertyTable)); - - mainPanel.add(tablesPanel, BorderLayout.CENTER); - - initListeners(); - } - - protected void initListeners() { - - clearFilterButton.setAction( - new AbstractAction("", MainFrame.getIcon("exit.gif")) { - { this.putValue(MNEMONIC_KEY, KeyEvent.VK_BACK_SPACE); - this.putValue(SHORT_DESCRIPTION, "Clear text field"); } - @Override - public void actionPerformed(ActionEvent e) { - filterTextField.setText(""); - filterTextField.requestFocusInWindow(); - } - }); - - // when an instance is selected, update the property table - instanceTable.getSelectionModel().addListSelectionListener( - new ListSelectionListener() { - @Override - public void valueChanged(ListSelectionEvent e) { - if (e.getValueIsAdjusting()) { return; } - updatePropertyTable(); - addLabelButton.setEnabled(newInstanceButton.isEnabled() - && selectedInstance != null); - } - } - ); - - // when typing a character in the instance table, use it for filtering - instanceTable.addKeyListener(new KeyAdapter() { - @Override - public void keyTyped(KeyEvent e) { - if (e.getKeyChar() != KeyEvent.VK_TAB - && e.getKeyChar() != KeyEvent.VK_SPACE - && e.getKeyChar() != KeyEvent.VK_BACK_SPACE - && e.getKeyChar() != KeyEvent.VK_DELETE) { - filterTextField.requestFocusInWindow(); - filterTextField.setText(String.valueOf(e.getKeyChar())); - } - } - }); - - // context menu to delete instances - instanceTable.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent evt) { - processMouseEvent(evt); - } - @Override - public void mousePressed(MouseEvent evt) { - JTable table = (JTable) evt.getSource(); - int row = table.rowAtPoint(evt.getPoint()); - if (evt.isPopupTrigger() - && !table.isRowSelected(row)) { - // if right click outside the selection then reset selection - table.getSelectionModel().setSelectionInterval(row, row); - } - processMouseEvent(evt); - } - @Override - public void mouseReleased(MouseEvent evt) { - processMouseEvent(evt); - } - protected void processMouseEvent(MouseEvent evt) { - final JTable table = (JTable) evt.getSource(); - int row = table.rowAtPoint(evt.getPoint()); - if (row >= 0) { - if (evt.isPopupTrigger()) { - // context menu - JPopupMenu popup = new JPopupMenu(); - if (table.getSelectedRowCount() == 1) { - popup.add(new ShowInstanceInOntologyEditorAction()); - popup.addSeparator(); - } - if (table.getSelectedRowCount() > 0) { - popup.add(new DeleteSelectedInstanceAction()); - } - if (popup.getComponentCount() > 0) { - popup.show(table, evt.getX(), evt.getY()); - } - } - } - } - }); - - // context menu to delete properties - propertyTable.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent evt) { - processMouseEvent(evt); - } - @Override - public void mousePressed(MouseEvent evt) { - JTable table = (JTable) evt.getSource(); - int row = table.rowAtPoint(evt.getPoint()); - if (evt.isPopupTrigger() - && !table.isRowSelected(row)) { - // if right click outside the selection then reset selection - table.getSelectionModel().setSelectionInterval(row, row); - } - processMouseEvent(evt); - } - @Override - public void mouseReleased(MouseEvent evt) { - processMouseEvent(evt); - } - protected void processMouseEvent(MouseEvent evt) { - final JTable table = (JTable) evt.getSource(); - int row = table.rowAtPoint(evt.getPoint()); - if (row >= 0) { - if (evt.isPopupTrigger()) { - // context menu - JPopupMenu popup = new JPopupMenu(); - if (table.getSelectedRowCount() > 0) { - popup.add(new DeleteSelectedPropertyAction()); - } - if (popup.getComponentCount() > 0) { - popup.show(table, evt.getX(), evt.getY()); - } - } - } - } - }); - - // show only the rows containing the text from filterTextField - filterTextField.getDocument().addDocumentListener(new DocumentListener() { - private Timer timer = new Timer("Instance view table rows filter", true); - private TimerTask timerTask; - @Override - public void changedUpdate(DocumentEvent e) { /* do nothing */ } - @Override - public void insertUpdate(DocumentEvent e) { update(); } - @Override - public void removeUpdate(DocumentEvent e) { update(); } - private void update() { - if (timerTask != null) { timerTask.cancel(); } - Date timeToRun = new Date(System.currentTimeMillis() + 300); - timerTask = new TimerTask() { @Override - public void run() { - updateInstanceTable(selectedClass); - }}; - // add a delay - timer.schedule(timerTask, timeToRun); - } - }); - - // Up/Down key events in filterTextField are transferred to the table - filterTextField.addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_UP - || e.getKeyCode() == KeyEvent.VK_DOWN - || e.getKeyCode() == KeyEvent.VK_PAGE_UP - || e.getKeyCode() == KeyEvent.VK_PAGE_DOWN) { - instanceTable.dispatchEvent(e); - } - } - }); - } - - @Override - protected void registerHooks() { - // show the class view at the right - if (!classView.isActive()) { - owner.setRightView(owner.verticalViews.indexOf(classView)); - } - } - - @Override - protected void unregisterHooks() { - // hide the class view at the right - if (classView.isActive()) { - owner.setRightView(-1); - } - } - - @Override - public Component getGUI() { - return mainPanel; - } - - @Override - public int getType() { - return HORIZONTAL; - } - - /** - * Update the instance table for the class and ontology selected. - * @param selectedClass class selected - */ - public void updateInstanceTable(OClass selectedClass) { - this.selectedClass = selectedClass; - instances.clear(); - Set<OInstance> allInstances = new HashSet<OInstance>(); - final DefaultTableModel tableModel = new DefaultTableModel(); - tableModel.addColumn("Instance"); - tableModel.addColumn("Labels"); - if (selectedClass != null) { - selectedOntology = selectedClass.getOntology(); - allInstances.addAll(selectedOntology.getOInstances( - selectedClass, OConstants.Closure.TRANSITIVE_CLOSURE)); - String filter = filterTextField.getText() - .trim().toLowerCase(Locale.ENGLISH); - for (OInstance instance : allInstances) { - Set<AnnotationProperty> properties = - instance.getSetAnnotationProperties(); - boolean hasLabelProperty = false; - instances.add(instance); - for (AnnotationProperty property : properties) { - if (property.getName().equals("label")) { - hasLabelProperty = true; - List<Literal> values = - instance.getAnnotationPropertyValues(property); - Set<String> labels = new HashSet<String>(); - boolean matchFilter = false; - for (Literal value : values) { - labels.add(value.getValue()); - if (value.getValue().toLowerCase().indexOf(filter) != -1) { - matchFilter = true; - } - } - if (matchFilter) { - tableModel.addRow(new Object[]{instance.getName(), - Strings.toString(labels)}); - } else { - instances.remove(instance); - } - } - } - if (!hasLabelProperty) { - // add instance row without label property - tableModel.addRow(new Object[]{instance.getName(), ""}); - } - } - } - final int hiddenInstances = allInstances.size() - instances.size(); - SwingUtilities.invokeLater(new Runnable() { @Override - public void run() { - hiddenInstancesLabel.setText(" " + hiddenInstances + " hidden "); - instanceTable.setModel(tableModel); - if (instanceTable.getRowCount() > 0) { - instanceTable.setRowSelectionInterval(0, 0); - } - }}); - } - - protected void updatePropertyTable() { - selectedInstance = null; - final DefaultTableModel tableModel = new DefaultTableModel(); - tableModel.addColumn("Property"); - tableModel.addColumn("Value"); - if (instanceTable.getSelectedRow() != -1) { - String selectedValue = (String) instanceTable.getValueAt( - instanceTable.getSelectedRow(), - instanceTable.convertColumnIndexToView(0)); - for (OInstance instance : instances) { - if (instance.getName().equals(selectedValue)) { - // found the instance matching the name in the table - selectedInstance = instance; - setProperties.clear(); - properties.clear(); - // get all object properties that can be set for this instance - Set<OClass> classes = - instance.getOClasses(OConstants.Closure.DIRECT_CLOSURE); - for (OClass oClass : classes) { - for (RDFProperty property : - oClass.getPropertiesWithResourceAsDomain()) { - if (property instanceof ObjectProperty) { - properties.add((ObjectProperty) property); - Set<String> ranges = new HashSet<String>(); - Set<OClass> rangeClasses = new HashSet<OClass>(); - for (OResource range : - ((ObjectProperty) property).getRange()) { - ranges.add(range.getName()); - rangeClasses.add((OClass) range); - } - if (ranges.isEmpty()) { - ranges.add("All classes"); - } - classesByPropertyMap.put(property.getName(), rangeClasses); - tableModel.addRow(new Object[]{property.getName(), - Strings.toString(ranges)}); - } - } - } - // get all set object properties and values for this instance - for (ObjectProperty objectProperty : - instance.getSetObjectProperties()) { - setProperties.add(objectProperty); - for (OInstance oInstance : - instance.getObjectPropertyValues(objectProperty)) { - tableModel.addRow(new Object[]{objectProperty.getName(), - oInstance.getONodeID().getResourceName()}); - } - } - break; - } - } - } - SwingUtilities.invokeLater(new Runnable() { @Override - public void run() { - propertyTable.setModel(tableModel); - propertyTable.getColumnModel().getColumn(1) - .setCellEditor(new PropertyValueCellEditor()); - propertyTable.getColumnModel().getColumn(0) - .setCellRenderer(new DefaultTableCellRenderer() { - @Override - public Component getTableCellRendererComponent(JTable table, Object - value, boolean isSelected, boolean hasFocus, int row, int column) { - super.getTableCellRendererComponent( - table, value, isSelected, hasFocus, row, column); - setBackground(table.getBackground()); - Object nextValue = table.getModel().getValueAt(row, 1); - if (nextValue != null && ((String)nextValue).startsWith("[")) { - // change color for rows that have no values set - setBackground(new Color(252, 252, 176)); - } - return this; - } - }); - propertyTable.getColumnModel().getColumn(1) - .setCellRenderer(new DefaultTableCellRenderer() { - @Override - public Component getTableCellRendererComponent(JTable table, Object - value, boolean isSelected, boolean hasFocus, int row, int column) { - super.getTableCellRendererComponent( - table, value, isSelected, hasFocus, row, column); - setBackground(table.getBackground()); - if (value != null && ((String)value).startsWith("[")) { - // change color for rows that have no values set - setBackground(new Color(252, 252, 176)); - } - return this; - } - }); - }}); - } - - /** - * Create a new annotation and instance from a text selection. - * Use the text selected as the instance property label. - * - * @param selectedSet name of the selected annotation set - * @param selectedText selection - * @param start selection start offset - * @param end selection end offset - */ - protected void addSelectionToFilter(final String selectedSet, - final String selectedText, final int start, final int end) { - newInstanceButton.setAction( - new AbstractAction(newInstanceButton.getText()) { - { this.putValue(MNEMONIC_KEY, KeyEvent.VK_N); - this.putValue(SHORT_DESCRIPTION, newInstanceButton.getToolTipText()); } - @Override - public void actionPerformed(ActionEvent e) { - createFromSelection(selectedSet, selectedText, start, end, true); - filterTextField.setText(""); -// filterTextField.setBackground( -// UIManager.getColor("TextField.background")); - } - }); - newInstanceButton.setEnabled(true); - addLabelButton.setAction( - new AbstractAction(addLabelButton.getText()) { - { this.putValue(MNEMONIC_KEY, KeyEvent.VK_A); - this.putValue(SHORT_DESCRIPTION, addLabelButton.getToolTipText()); } - @Override - public void actionPerformed(ActionEvent e) { - createFromSelection(selectedSet, selectedText, start, end, false); - filterTextField.setText(""); -// filterTextField.setBackground( -// UIManager.getColor("TextField.background")); - } - }); - filterTextField.setText(selectedText); - filterTextField.selectAll(); - filterTextField.requestFocusInWindow(); - addLabelButton.setEnabled(selectedInstance != null); -// filterTextField.setBackground(new Color(252, 255, 194)); -// filterTextField.setBackground( -// UIManager.getColor("TextField.background")); - } - - /** - * Create a new annotation and instance or label from a text selection. - * Use the text selected as the instance property label. - * - * @param selectedSet name of the selected annotation set - * @param selectedText selection - * @param start selection start offset - * @param end selection end offset - * @param newInstance true if it will create a new instance otherwise - * it will add a new label to the selected instance - */ - protected void createFromSelection(String selectedSet, String selectedText, - int start, int end, boolean newInstance) { - newInstanceButton.setEnabled(false); - addLabelButton.setEnabled(false); - AnnotationProperty annotationProperty; - RDFProperty property = selectedOntology.getProperty( - selectedOntology.createOURIForName("label")); - if (property == null) { - // create a property 'label' if it doesn't exist - annotationProperty = selectedOntology.addAnnotationProperty( - selectedOntology.createOURIForName("label")); - } else if (property instanceof AnnotationProperty) { - // get the existing property 'label' - annotationProperty = (AnnotationProperty) property; - } else { - Out.prln("There is already a property 'label' " + - "that is not an annotation property!"); - return; - } - OInstance instance = selectedInstance; - if (newInstance) { - // squeeze spaces, replace spaces and HTML characters with underscores - String instanceName = selectedText.replaceAll("\\s+", "_"); - instanceName = instanceName.replaceAll("<>\"&", "_"); - // take only the first 20 characters of the selection - if (instanceName.length() > 100) { - instanceName = instanceName.substring(0, 100); - } - OURI instanceOURI = selectedOntology.createOURIForName(instanceName); - for (int i = 0; selectedOntology.containsOInstance(instanceOURI) - && i < Integer.MAX_VALUE; i++) { - // instance name already existing so suffix with a number - instanceOURI = selectedOntology.createOURIForName(instanceName+'_'+i); - } - // create a new instance from the text selected - instance = selectedOntology.addOInstance(instanceOURI, selectedClass); - } - // add a property 'label' with the selected text as value - instance.addAnnotationPropertyValue(annotationProperty, - new Literal(selectedText)); - AnnotationSet set = document.getAnnotations(selectedSet); - - try { - String ontology = selectedOntology.getDefaultNameSpace(); - // to be compatible with KIM and OAT which have - // ontology feature without ending # - ontology = ontology.substring(0, ontology.length()-1); - features = Factory.newFeatureMap(); - features.put(ONTOLOGY, ontology); - features.put(CLASS, selectedClass.getONodeID().toString()); - features.put(INSTANCE, instance.getONodeID().toString()); - // create a new annotation from the text selected - set.add((long) start, (long) end, ANNOTATION_TYPE, features); - } catch(InvalidOffsetException e) { - throw new GateRuntimeException(e); - } - classView.setClassHighlighted(selectedClass, false); - classView.setClassHighlighted(selectedClass, true); -// classView.selectInstance(set, set.get(id), selectedClass); - updateInstanceTable(selectedClass); - } - - /** - * Select an instance in the instance table if it exists.. - * @param oInstance instance to be selected - */ - public void selectInstance(OInstance oInstance) { - for (int row = 0; row < instanceTable.getRowCount(); row++) { - if (oInstance.getONodeID().toString().endsWith( - (String) instanceTable.getValueAt(row, 0))) { - int rowModel = instanceTable.rowViewToModel(row); - instanceTable.getSelectionModel() - .setSelectionInterval(rowModel, rowModel); - break; - } - } - } - - protected class PropertyValueCellEditor extends AbstractCellEditor - implements TableCellEditor, ActionListener { - private JComboBox<String> valueComboBox; - private Collator comparator; - private String oldValue; - private Map<String, OInstance> nameInstanceMap; - private Pattern instanceLabelsPattern; - - private PropertyValueCellEditor() { - valueComboBox = new JComboBox<String>(); - valueComboBox.setMaximumRowCount(10); - valueComboBox.addActionListener(this); - comparator = Collator.getInstance(); - comparator.setStrength(java.text.Collator.TERTIARY); - nameInstanceMap = new HashMap<String, OInstance>(); - instanceLabelsPattern = Pattern.compile("^(.+) \\[.*\\]$"); - } - - @Override - public Component getTableCellEditorComponent(JTable table, Object value, - boolean isSelected, int row, int column) { - oldValue = (String) value; - TreeSet<String> ts = new TreeSet<String>(comparator); - Set<OClass> classes = classesByPropertyMap.get(propertyTable.getModel().getValueAt(row, 0)); - if (classes.isEmpty()) { classes = selectedOntology.getOClasses(false); } - for (OClass oClass : classes) { - // get all the classes that belong to the property domain - Set<OInstance> instances = selectedOntology.getOInstances( - oClass, OConstants.Closure.TRANSITIVE_CLOSURE); - for (OInstance instance : instances) { - Set<String> labelSet = new HashSet<String>(); - Set<AnnotationProperty> properties = - instance.getSetAnnotationProperties(); - for (AnnotationProperty property : properties) { - if (property.getName().equals("label")) { - List<Literal> labels = - instance.getAnnotationPropertyValues(property); - for (Literal label : labels) { - labelSet.add(label.getValue()); - } - } - } - // for each class add their instance names and labels list - ts.add(instance.getName() + " " + Strings.toString(labelSet)); - nameInstanceMap.put(instance.getName(), instance); - } - } - DefaultComboBoxModel<String> dcbm = new DefaultComboBoxModel<String>(ts.toArray(new String[ts.size()])); - valueComboBox.setModel(dcbm); - valueComboBox.setSelectedItem(propertyTable.getValueAt(row, column)); - return valueComboBox; - } - - @Override - public Object getCellEditorValue() { - return valueComboBox.getSelectedItem(); - } - - @Override - protected void fireEditingStopped() { - String newValue = (String) getCellEditorValue(); - if (newValue == null) { - fireEditingCanceled(); - return; - } - Matcher matcher = instanceLabelsPattern.matcher(newValue); - // remove the list of labels from the selected instance value - if (matcher.matches()) { newValue = matcher.group(1); } - super.fireEditingStopped(); - String selectedProperty = (String) propertyTable.getModel().getValueAt( - propertyTable.getSelectedRow(), 0); - // search the object property to set - for (ObjectProperty objectProperty : setProperties) { - // verify that the property value correspond - if (objectProperty.getName().equals(selectedProperty)) { - for (OInstance oInstance : - selectedInstance.getObjectPropertyValues(objectProperty)) { - String value = oInstance.getONodeID().getResourceName(); - if (value.equals(oldValue)) { - // property already existing, remove it first - selectedInstance.removeObjectPropertyValue( - objectProperty, oInstance); - try { - // set the new value for the selected object property - selectedInstance.addObjectPropertyValue( - objectProperty, nameInstanceMap.get(newValue)); - } catch (InvalidValueException e) { - e.printStackTrace(); - } - updatePropertyTable(); - return; - } - } - } - } - for (ObjectProperty objectProperty : properties) { - if (objectProperty.getName().equals(selectedProperty)) { - try { - // set the new value for the selected object property - selectedInstance.addObjectPropertyValue( - objectProperty, nameInstanceMap.get(newValue)); - } catch (InvalidValueException e) { - e.printStackTrace(); - } - updatePropertyTable(); - return; - } - } - } - - // TODO: itemlistener may be better - @Override - public void actionPerformed(ActionEvent e) { - if (getCellEditorValue() == null) { - fireEditingCanceled(); - } else { - fireEditingStopped(); - } - } - } - - protected class ShowInstanceInOntologyEditorAction extends AbstractAction { - public ShowInstanceInOntologyEditorAction() { - super("Show In Ontology Editor"); - } - - @Override - public void actionPerformed(ActionEvent event) { - // show the ontology editor if not already displayed - SwingUtilities.invokeLater(new Runnable() { @Override - public void run() { - final Handle handle = MainFrame.getInstance().select(selectedOntology); - if (handle == null) { return; } - // wait some time for the ontology editor to be displayed - Date timeToRun = new Date(System.currentTimeMillis() + 1000); - Timer timer = new Timer("Ontology Instance View Timer", true); - timer.schedule(new TimerTask() { @Override - public void run() { - String instanceName = (String) instanceTable.getModel() - .getValueAt(instanceTable.getSelectedRow(), 0); - for (OInstance oInstance : instances) { - if (oInstance.getName().equals(instanceName)) { - // found the corresponding instance in the ontology - JComponent largeView = handle.getLargeView(); - if (largeView != null - && largeView instanceof JTabbedPane - && ((JTabbedPane)largeView).getSelectedComponent() != null) { - ((OntologyEditor) ((JTabbedPane) largeView) - .getSelectedComponent()) - .selectResourceInClassTree(oInstance); - } - break; - } - } - }}, timeToRun); - }}); - } - } - - protected class DeleteSelectedInstanceAction extends AbstractAction { - public DeleteSelectedInstanceAction() { - super(instanceTable.getSelectedRowCount() > 1 ? - "Delete instances" : "Delete instance"); - putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("shift DELETE")); - } - - @Override - public void actionPerformed(ActionEvent e) { - String ontology = selectedOntology.getDefaultNameSpace(); - ontology = ontology.substring(0, ontology.length()-1); - for (OInstance oInstance : instances) { - for (int selectedRow : instanceTable.getSelectedRows()) { - if (oInstance.getName().equals( - instanceTable.getModel().getValueAt(selectedRow, 0))) { - selectedOntology.removeOInstance(oInstance); - // find annotations related to this instance - AnnotationSet annotationSet = - document.getAnnotations(classView.getSelectedSet()); - for (Annotation annotation : - annotationSet.get(ANNOTATION_TYPE)) { - if (annotation.getFeatures().containsKey(ONTOLOGY) - && annotation.getFeatures().get(ONTOLOGY) - .equals(ontology) - && annotation.getFeatures().containsKey(CLASS) - && annotation.getFeatures().get(CLASS) - .equals(selectedClass.getONodeID().toString()) - && annotation.getFeatures().containsKey(INSTANCE) - && annotation.getFeatures().get(INSTANCE) - .equals(oInstance.getONodeID().toString())) { - // delete the annotation - annotationSet.remove(annotation); - } - } - } - } - } - classView.setClassHighlighted(selectedClass, false); - classView.setClassHighlighted(selectedClass, true); - updateInstanceTable(selectedClass); - } - } - - protected class DeleteSelectedPropertyAction extends AbstractAction { - public DeleteSelectedPropertyAction() { - super(propertyTable.getSelectedRowCount() > 1 ? - "Delete properties" : "Delete property"); - putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("shift DELETE")); - } - - @Override - public void actionPerformed(ActionEvent e) { - for (ObjectProperty objectProperty : setProperties) { - for (int selectedRow : propertyTable.getSelectedRows()) { - // find the property that matches the first column value - if (objectProperty.getName().equals( - propertyTable.getModel().getValueAt(selectedRow, 0))) { - for (OInstance oInstance : selectedInstance - .getObjectPropertyValues(objectProperty)) { - String value = oInstance.getONodeID() - .getResourceName(); - // find the value that matches the second column value - if (value.equals(propertyTable.getModel() - .getValueAt(selectedRow, 1))) { - // delete the property - selectedInstance.removeObjectPropertyValue( - objectProperty, oInstance); - break; - } - } - } - } - } - updatePropertyTable(); - } - } - - // external resources - protected Ontology selectedOntology; - protected TextualDocumentView textView; - protected OntologyClassView classView; - - // UI components - protected JPanel mainPanel; - protected JTextField filterTextField; - protected JButton clearFilterButton; - protected JLabel hiddenInstancesLabel; - protected JButton newInstanceButton; - protected JButton addLabelButton; - protected XJTable instanceTable; - protected XJTable propertyTable; - - // local objects - /** Class that has the lead selection in the focused tree. */ - protected OClass selectedClass; - /** Instance selected in the instance table. */ - protected OInstance selectedInstance; - /** Instances in the instance table for the selected class and filter. */ - protected Set<OInstance> instances; - /** Properties set in the property table for the selected class and filter. */ - protected Set<ObjectProperty> setProperties; - /** Properties in the instance table for the selected class and filter. */ - protected Set<ObjectProperty> properties; - protected Map<String, Set<OClass>> classesByPropertyMap; - - // constants for annotation feature, annotation type - protected static final String ONTOLOGY = - gate.creole.ANNIEConstants.LOOKUP_ONTOLOGY_FEATURE_NAME; - protected static final String CLASS = - gate.creole.ANNIEConstants.LOOKUP_CLASS_FEATURE_NAME; - protected static final String INSTANCE = - gate.creole.ANNIEConstants.LOOKUP_INSTANCE_FEATURE_NAME; - protected static final String ANNOTATION_TYPE = "Mention"; -} Copied: gate/branches/sawdust2/plugins/Ontology_Tools/src/gate/gui/docview/OntologyClassView.java (from rev 20249, gate/branches/sawdust2/gate-core/src/main/java/gate/gui/docview/OntologyClassView.java) =================================================================== --- gate/branches/sawdust2/plugins/Ontology_Tools/src/gate/gui/docview/OntologyClassView.java (rev 0) +++ gate/branches/sawdust2/plugins/Ontology_Tools/src/gate/gui/docview/OntologyClassView.java 2017-07-10 14:43:43 UTC (rev 20250) @@ -0,0 +1,1117 @@ +/** + * Copyright (c) 1995-2012, The University of Sheffield. See the file + * COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt + * + * This file is part of GATE (see http://gate.ac.uk/), and is free + * software, licenced under the GNU Library General Public License, + * Version 2, June 1991 (in the distribution as file licence.html, + * and also available at http://gate.ac.uk/gate/licence.html). + * + * Thomas Heitz - 14/12/2009 + * + * $Id$ + */ + +package gate.gui.docview; + +import gate.Annotation; +import gate.AnnotationSet; +import gate.FeatureMap; +import gate.Gate; +import gate.LanguageResource; +import gate.Resource; +import gate.creole.ontology.OClass; +import gate.creole.ontology.OConstants; +import gate.creole.ontology.OResource; +import gate.creole.ontology.Ontology; +import gate.creole.ontology.OntologyModificationListener; +import gate.creole.ontology.RDFProperty; +import gate.event.CreoleEvent; +import gate.event.CreoleListener; +import gate.gui.MainFrame; +import gate.gui.annedit.AnnotationData; +import gate.gui.annedit.AnnotationDataImpl; +import gate.gui.ontology.OntologyItemComparator; +import gate.util.GateRuntimeException; +import gate.util.OptionsMap; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.FlowLayout; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.EventObject; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Vector; + +import javax.swing.AbstractAction; +import javax.swing.AbstractCellEditor; +import javax.swing.BorderFactory; +import javax.swing.DefaultComboBoxModel; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.JTree; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.Timer; +import javax.swing.UIManager; +import javax.swing.border.Border; +import javax.swing.event.MouseInputAdapter; +import javax.swing.event.TreeExpansionEvent; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.event.TreeWillExpandListener; +import javax.swing.text.BadLocationException; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.ExpandVetoException; +import javax.swing.tree.TreeCellEditor; +import javax.swing.tree.TreeCellRenderer; +import javax.swing.tree.TreePath; +import javax.swing.tree.TreeSelectionModel; + +/** + * Document view that displays an ontology class tree to annotate a document. + * + * tick the checkbox of a class to show the instances highlighted in the text + * selected class will be used when creating a new annotation from a text + * selection in the document + * take only the first 20 characters of the selection for the instance name + * and add a number if already existing + * allow multiple ontologies to be used at the same time + * put each ontology in a JPanel with triangle icons to hide/show the panel, + * hidden by default + * open only first level of classes when opening an ontology + * load lazily the ontology trees + * context menu for classes to hide/show them, saved in user configuration + */ +@SuppressWarnings("serial") +public class OntologyClassView extends AbstractDocumentView + implements CreoleListener, OntologyModificationListener { + + public OntologyClassView() { + + colorByClassMap = new HashMap<OClass, Color>(); + highlightedClasses = new HashSet<OClass>(); + highlightsDataByClassMap = new HashMap<OClass, List<TextualDocumentView.HighlightData>>(); + treeByOntologyMap = new HashMap<Ontology, JTree>(); + String prefix = getClass().getName() + '.'; + hiddenClassesSet = userConfig.getSet(prefix + "hiddenclasses"); + itemComparator = new OntologyItemComparator(); + } + + @Override + protected void initGUI() { + + // get a pointer to the text view used to display + // the selected annotations + Iterator<DocumentView> centralViewsIter = owner.getCentralViews().iterator(); + while(textView == null && centralViewsIter.hasNext()){ + DocumentView aView = centralViewsIter.next(); + if(aView instanceof TextualDocumentView) + textView = (TextualDocumentView) aView; + } + textArea = textView.getTextView(); + // get a pointer to the instance view + Iterator<DocumentView> horizontalViewsIter = owner.getHorizontalViews().iterator(); + while(instanceView == null && horizontalViewsIter.hasNext()){ + DocumentView aView = horizontalViewsIter.next(); + if (aView instanceof OntologyInstanceView) { + instanceView = (OntologyInstanceView) aView; + } + } + instanceView.setOwner(owner); + + mainPanel = new JPanel(new GridBagLayout()); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridx = 0; + treesPanel = new JPanel(); + treesPanel.setLayout(new GridBagLayout()); + // add a disclosure panel for each loaded ontology in the system + boolean isOntologyLoaded = false; + List<LanguageResource> resources = + gate.Gate.getCreoleRegister().getPublicLrInstances(); + for (LanguageResource resource : resources) { + if (resource instanceof Ontology) { + loadOntology((Ontology) resource); + isOntologyLoaded = true; + } + } + gbc.weightx = 1; + gbc.weighty = 1; + gbc.fill = GridBagConstraints.BOTH; + gbc.anchor = GridBagConstraints.NORTHWEST; + mainPanel.add(new JScrollPane(treesPanel), gbc); + setComboBox = new JComboBox<String>(); + setComboBox.setEditable(true); + setComboBox.setToolTipText( + "Annotation set where to load/save the annotations"); + gbc.weighty = 0; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.anchor = GridBagConstraints.SOUTH; + mainPanel.add(setComboBox, gbc); + + initListeners(); + + // fill the annotation sets list + List<String> annotationSets = new ArrayList<String>(); + annotationSets.add(""); + annotationSets.addAll(document.getAnnotationSetNames()); + Collections.sort(annotationSets); + setComboBox.setModel(new DefaultComboBoxModel<String>( + new Vector<String>(annotationSets))); + + if (isOntologyLoaded) { + // find the first set that contains annotations used before by this view + selectedSet = ""; + for (int i = 0; i < setComboBox.getItemCount(); i++) { + String setName = setComboBox.getItemAt(i); + if (setColorTreeNodesWhenInstancesFound(setName)) { + selectedSet = setName; + break; + } + } + setComboBox.setSelectedItem(selectedSet); + } else { + messageLabel = new JLabel( + "<html><p><font color=red>Load at least one ontology."); + messageLabel.setHorizontalAlignment(SwingConstants.CENTER); + messageLabel.setBorder(BorderFactory.createEmptyBorder(5, 2, 5, 2)); + messageLabel.setBackground( + UIManager.getColor("Tree.selectionBackground")); + gbc = new GridBagConstraints(); + treesPanel.add(messageLabel, gbc); + } + } + + protected void initListeners() { + + Gate.getCreoleRegister().addCreoleListener(this); + + setComboBox.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + selectedSet = (String) setComboBox.getSelectedItem(); + setColorTreeNodesWhenInstancesFound(selectedSet); + // unselect annotations + SwingUtilities.invokeLater(new Runnable() { @Override + public void run() { + for (OClass oClass : highlightedClasses) { + if (highlightsDataByClassMap.containsKey(oClass)) { + textView.removeHighlights(highlightsDataByClassMap.get(oClass)); + } + } + highlightsDataByClassMap.clear(); + highlightedClasses.clear(); + // update showing trees + for (JTree tree : treeByOntologyMap.values()) { + if (tree.isShowing()) { + tree.revalidate(); + } + } + }}); + } + }); + + // a listener that stops or restarts a timer which calls an action + mouseStoppedMovingAction = new MouseStoppedMovingAction(); + mouseMovementTimer = new javax.swing.Timer( + MOUSE_MOVEMENT_TIMER_DELAY, mouseStoppedMovingAction); + mouseMovementTimer.setRepeats(false); + textMouseListener = new TextMouseListener(); + } + + @Override + protected void registerHooks() { + textArea.addMouseListener(textMouseListener); + textArea.addMouseMotionListener(textMouseListener); + // reselect annotations + SwingUtilities.invokeLater(new Runnable() { @Override + public void run() { + for (OClass oClass : new HashSet<OClass>(highlightedClasses)) { + if (highlightsDataByClassMap.containsKey(oClass)) { + textView.addHighlights(highlightsDataByClassMap.get(oClass)); + } + } + }}); + // show the instance view at the bottom + if (!instanceView.isActive()) { + owner.setBottomView(owner.horizontalViews.indexOf(instanceView)); + } + } + + @Override + protected void unregisterHooks() { + textArea.removeMouseListener(textMouseListener); + textArea.removeMouseMotionListener(textMouseListener); + // unselect annotations + SwingUtilities.invokeLater(new Runnable() { @Override + public void run() { + for (OClass oClass : highlightedClasses) { + if (highlightsDataByClassMap.containsKey(oClass)) { + textView.removeHighlights(highlightsDataByClassMap.get(oClass)); + } + } + }}); + // hide the instance view at the bottom + if (instanceView.isActive()) { + owner.setBottomView(-1); + } + } + + @Override + public void cleanup() { + super.cleanup(); + Gate.getCreoleRegister().removeCreoleListener(this); + document = null; + // save hidden classes to be reused next time + String prefix = getClass().getName() + '.'; + userConfig.put(prefix + "hiddenclasses", hiddenClassesSet); + } + + @Override + public Component getGUI() { + return mainPanel; + } + + @Override + public int getType() { + return VERTICAL; + } + + @Override + public void resourceLoaded(CreoleEvent e) { + if (e.getResource() instanceof Ontology) { + if (messageLabel != null + && treesPanel.isAncestorOf(messageLabel)) { + treesPanel.remove(messageLabel); + // find the first set that contains annotations used before by this view + selectedSet = ""; + for (int i = 0; i < setComboBox.getItemCount(); i++) { + String setName = setComboBox.getItemAt(i); + if (setColorTreeNodesWhenInstancesFound(setName)) { + selectedSet = setName; + break; + } + } + setComboBox.setSelectedItem(selectedSet); + } + Ontology ontology = (Ontology) e.getResource(); + loadOntology(ontology); + // listen to modification of classes in the ontology to rebuild the tree + ontology.addOntologyModificationListener(this); + } + } + + @Override + public void resourceUnloaded(CreoleEvent e) { + if (e.getResource() instanceof Ontology) { + Ontology ontology = (Ontology) e.getResource(); + JTree tree = treeByOntologyMap.remove(ontology); + for (Component component : treesPanel.getComponents()) { + if (component instanceof JPanel + && ((JPanel) component).isAncestorOf(tree)) { + treesPanel.remove(component); + } + } + treesPanel.revalidate(); + } + } + + @Override + public void datastoreOpened(CreoleEvent e) { /* do nothing */ } + + @Override + public void datastoreCreated(CreoleEvent e) { /* do nothing */ } + + @Override + public void datastoreClosed(CreoleEvent e) { /* do nothing */ } + + @Override + public void resourceRenamed(Resource resource, String oldName, + String newName) { /* do nothing */ } + @Override + public void resourceRelationChanged(Ontology ontology, OResource + resource1, OResource resource2, int eventType) { /* do nothing */ } + + @Override + public void resourcePropertyValueChanged(Ontology ontology, OResource + resource, RDFProperty property, Object value, int eventType) { + /* do nothing */ } + + @Override + public void resourcesRemoved(Ontology ontology, String[] resources) { } + + @Override + public void resourceAdded(Ontology ontology, OResource resource) { + if (resource instanceof OClass) { + final JTree tree = treeByOntologyMap.get(ontology); + DefaultMutableTreeNode node = + (DefaultMutableTreeNode) tree.getModel().getRoot(); + final Enumeration<?> enumeration = node.preorderEnumeration(); + SwingUtilities.invokeLater(new Runnable() { @Override + public void run() { + // traverse the expanded class tree and update all the nodes + while (enumeration.hasMoreElements()) { + DefaultMutableTreeNode node = + (DefaultMutableTreeNode) enumeration.nextElement(); + Object userObject = node.getUserObject(); + if (userObject != null + && !userObject.equals("Loading...")) { + // node already expanded + OClass oClass = (OClass) userObject; + Set<OClass> classes = oClass.getSubClasses( + OConstants.Closure.DIRECT_CLOSURE); + // readd all the children node + addNodes(tree, node, classes, false); + } + } + }}); + } + } + + @Override + public void ontologyReset(Ontology ontology) { /* do nothing */ } + + /** + * Extract annotations that have been created by this view and + * colored the corresponding tree class node if found. + * @param setName the annotation set name to search + * @return true if and only if at least one annotation has been found + */ + protected boolean setColorTreeNodesWhenInstancesFound(String setName) { + boolean returnValue = false; + List<LanguageResource> resources = + gate.Gate.getCreoleRegister().getPublicLrInstances(); + Map<String, Ontology> ontologyMap = new HashMap<String, Ontology>(); + for (LanguageResource resource : resources) { + if (resource instanceof Ontology) { + Ontology ontology = (Ontology) resource; + String ontologyName = ontology.getDefaultNameSpace(); + ontologyName = ontologyName.substring(0, ontologyName.length()-1); + ontologyMap.put(ontologyName, ontology); + } + } + for (Annotation annotation : + document.getAnnotations(setName).get(ANNOTATION_TYPE)) { + FeatureMap features = annotation.getFeatures(); + if (features.get(ONTOLOGY) != null + && features.get(CLASS) != null + && features.get(INSTANCE) != null) { + // find the corresponding ontology + Ontology ontology = ontologyMap.get(features.get(ONTOLOGY)); + if (ontology != null) { + // choose a background color for the annotation type tree node + OClass oClass = ontology.getOClass(ontology + .createOURI((String) features.get(CLASS))); + if (oClass != null) { + colorByClassMap.put(oClass, + AnnotationSetsView.getColor(setName, oClass.getName())); + returnValue = true; + } + } + } + } + return returnValue; + } + + /** + * Add the ontology in a disclosure panel, closed at start. + * @param ontology ontology to display + */ + protected void loadOntology(final Ontology ontology) { + + // create the class tree + final JTree tree = new JTree(new Object[]{"Loading..."}); + treeByOntologyMap.put(ontology, tree); + tree.setRootVisible(false); + tree.setShowsRootHandles(true); + tree.setEditable(true); + tree.getSelectionModel().setSelectionMode( + TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); + + final JPanel treePanel = new JPanel(new BorderLayout()); + final JCheckBox disclosureCheckBox = new JCheckBox( + ontology.getName(), MainFrame.getIcon("closed"), false); + disclosureCheckBox.setSelectedIcon(MainFrame.getIcon("expanded")); + treePanel.add(disclosureCheckBox, BorderLayout.NORTH); + + // show/hide the tree when clicking the disclosure checkbox + disclosureCheckBox.addActionListener(new ActionListener() { + boolean isTreeBuilt = false; + @Override + public void actionPerformed(ActionEvent e) { + if (disclosureCheckBox.isSelected()) { + if (!isTreeBuilt) { + tree.expandRow(0); // expands "Loading..." node + buildClassTree(tree, ontology); + isTreeBuilt = true; + } + treePanel.add(tree, BorderLayout.CENTER); + } else { + treePanel.remove(tree); + } + treesPanel.repaint(); + } + }); + + // context menu to show root classes + disclosureCheckBox.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { processMouseEvent(e); } + @Override + public void mouseReleased(MouseEvent e) { processMouseEvent(e); } + @Override + public void mouseClicked(MouseEvent e) { processMouseEvent(e); } + protected void processMouseEvent(MouseEvent e) { + JPopupMenu popup = new JPopupMenu(); + if (e.isPopupTrigger()) { + popup.add(new JMenuItem( + new AbstractAction("Show all root classes") { + @Override + public void actionPerformed(ActionEvent e) { + if (!disclosureCheckBox.isSelected()) { + disclosureCheckBox.doClick(); + } + hiddenClassesSet.clear(); + DefaultMutableTreeNode node = (DefaultMutableTreeNode) + tree.getModel().getRoot(); + final Set<OClass> classes = ontology.getOClasses(true); + // add first level nodes to the tree + addNodes(tree, node, classes, false); + } + })); + popup.show(e.getComponent(), e.getX(), e.getY()); + } + } + }); + + // when a class is selected in the tree update the instance table + tree.getSelectionModel().addTreeSelectionListener( + new TreeSelectionListener() { + @Override + public void valueChanged(TreeSelectionEvent e) { + if (e.getNewLeadSelectionPath() == null) { + if (treeByOntologyMap.get(selectedClass.getOntology()).equals(tree)){ + // only nullify selectedClass if unselect from the same tree + selectedClass = null; + } + } else { + if (tree.getSelectionCount() == 1) { // a class is selected + DefaultMutableTreeNode node = (DefaultMutableTreeNode) + e.getNewLeadSelectionPath().getLastPathComponent(); + selectedClass = (OClass) node.getUserObject(); + } else { // several classes are selected + selectedClass = null; + } + // clear selection in other trees + for (JTree aTree : treeByOntologyMap.values()) { + if (!aTree.equals(tree)) { + aTree.clearSelection(); + } + } + } + instanceView.updateInstanceTable(selectedClass); + } + } + ); + + // context menu to hide/show classes + tree.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + TreePath path = tree.getClosestPathForLocation(e.getX(), e.getY()); + if (e.isPopupTrigger() + && !tree.isPathSelected(path)) { + // if right click outside the selection then reset selection + tree.getSelectionModel().setSelectionPath(path); + } + processMouseEvent(e); + } + @Override + public void mouseReleased(MouseEvent e) { + processMouseEvent(e); + } + @Override + public void mouseClicked(MouseEvent e) { + processMouseEvent(e); + } + protected void processMouseEvent(MouseEvent e) { + JPopupMenu popup = new JPopupMenu(); + if (!e.isPopupTrigger()) { return; } + popup.add(new JMenuItem( + new AbstractAction("Hide selected classes") { + @Override + public void actionPerformed(ActionEvent e) { + DefaultTreeModel treeModel = (DefaultTreeModel) tree.getModel(); + TreePath[] selectedPaths = tree.getSelectionPaths(); + for (TreePath selectedPath : selectedPaths) { + DefaultMutableTreeNode node = (DefaultMutableTreeNode) + selectedPath.getLastPathComponent(); + if (node.getParent() != null) { + treeModel.removeNodeFromParent(node); + Object userObject = node.getUserObject(); + OClass oClass = (OClass) userObject; + hiddenClassesSet.add(oClass.getONodeID().toString()); + } + } + } + })); + + if (tree.getSelectionCount() == 1) { + popup.add(new JMenuItem(new AbstractAction("Show all sub classes") { + @Override + public void actionPerformed(ActionEvent e) { + DefaultMutableTreeNode node = (DefaultMutableTreeNode) + tree.getSelectionPath().getLastPathComponent(); + Object userObject = node.getUserObject(); + OClass oClass = (OClass) userObject; + Set<OClass> classes = oClass.getSubClasses( + OClass.Closure.DIRECT_CLOSURE); + addNodes(tree, node, classes, false); + } + })); + } + popup.show(e.getComponent(), e.getX(), e.getY()); + } + }); + + GridBagConstraints gbc = new GridBagConstraints(); + gbc.fill = GridBagConstraints.BOTH; @@ Diff output truncated at 100000 characters. @@ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ GATE-cvs mailing list GATE-cvs@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/gate-cvs