Now that we know how the windows are constructed and the main classes used for that, it’s time to know more about the action component.
1.2 – Actions components and events management
The user has many ways to do the same action.
For example, for adding a specimen, the user can use the menu bar, or the popup menu.
This part is going to describe what components are used for these actions, how we can build these components, and how we can handle the action.
1.2.1 - Menu Bar
There is one menu bar with 4 choices:
- File, which deals with everything that depends on the taxonomy
- Edit which deals with common action for taxon and specimen
- Taxon which deals with specific taxon actions
- Specimen which deals with specific specimen actions
Once your JmenuBar, with the correct items has been constructed, if you click on an item, nothing happens because there is no ActionListener class implement yet.
In Java, ActionListener is the listener interface for receiving action events. The class that is interested in processing an action event implements this interface, and the object created with that class is registered with a component, using the component's addActionListener method. When the action event occurs, that object's actionPerformed method is invoked.
So first, we have to use the addActionListener on the component (here a JItem) which is supposed to trigger the event by this way:
nameOfTheJItem.addActionListener(new MenuAction(this))
And finishing, to create the class MenuAction.java which implements ActionListener class.
This class can be described by the following manner:
- It is called when the action event occur (here, click on an item)
- It tests the source of the event
- In function of the source, an action is called
Now, when you left click on an item of the menu bar, the action is launched.
Obviously, when you select a taxon, the menu of specimen won’t be enable and conversely. You do this by the method.
nameOfTheJMenu.setEnable(false)
1.2.2 – Popup Menus
There are two different popup menus, one for the specimen and the other for the taxon.
As for the menu bar, if you click on an item of the popup menu, nothing happens. The class PopupMenuAction plays the same role for the popupMenu as the class MenuAction for the menu bar. It implements the action listener for clicking on items.
But there is one more thing to do for the popup menu. You have to set the events that trigger the display of the popup Menu. The user brings up a popup menu by releasing the right mouse button while the cursor is over a component that is popup-enabled. PopupListener class do this work. It’s an extended class of MouseListener class.
For finish, you just have to add a MouseListener to the component which is supposed to enable the display of the popup menu (here the JTree).
aTreeName.addMouseListener(aPopupListener)
Note: If the current selected element is a taxon, taxon popupMenu is displayed and conversely.
1.2.3 – Keyboard events
For catching keyboard events, we choose the easiest solution: the keyboard accelerator.
An accelerator is a key combination that causes a menu item to be chosen, whether or not it's visible. For example, pressing the Alt and X keys makes the first item cut in the edit menu's be chosen, without bringing up any menus.
Here is the way to set up an accelerator (which has for shortcut Alt X)
nameOfItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, ActionEvent.ALT_MASK))
Once bases of interface is defined, it was time to think about representation of taxonomic element into the interface.
1.3 – The JTree
The JTree is the component chosen for representing data in the interface. It allows the user to see the contents of the taxonomy in a Tree structure and to see the modifications that the user makes dynamically.
1.3.1 - General description of the Jtree
With the JTree class, you can display hierarchical data. That’s why we choose it for displaying taxonomy (which is also hierarchic with taxon and specimen).
A JTree object doesn't actually contain the data; it simply provides a view of the data. It’s important to remind this fact for later explications. Here's a picture of a tree:
As the preceding figure shows, JTree displays its data vertically. Each row displayed by the tree contains exactly one item of data, which is called a node. A node can either have children or not. Nodes that can't have children are leaf nodes.
Nodes can have any number of children. Typically, the user can expand and collapse nodes -- making their children visible or invisible -- by clicking them. By default, all nodes except the root node start out collapsed.
A specific node in a tree can be identified either by a TreePath (an object that encapsulates a node and all of its ancestors), or by its display row, where each row in the display area displays one node. An expanded node is a non-leaf node that will displays its children when all its ancestors are expanded. A collapsed node is one which hides them. A hidden node is one which is under a collapsed ancestor.
1.3.2 Modification of the JTree
JTree doesn’t have a lot of methods for changing its structure. In fact, only two things allow its changing:
- add a node which allows to add a node to an other node at the end of a subtree
- remove a node which allow to delete the chosen node
We will come back more precisely later in part x about change of tree structure
1.3.3 - Integration of the JTree into TaxTool Interface
As described in part 1.1, the JTree is located in the TaxToolTreePanel class. Its container is a JSplitPane (which also contains the JScrollPane which displays the URL). JTree is added as any other component in the JSplitPane.
We know now all the choices made for the interface development, the following part will deal with the way for user to interact with data thanks to taxtool and tax services.
2 – Communication between taxtool and data store
Recall: As explained in the first part, Tax Service allows changing data store. TaxTool is used for displaying these data and their changes.
For better comprehension of the continuation, here are some definitions.
Taxonomy Element: It’s either a taxon or a specimen
Taxonomy Services Packed Methods: It is a method defined in TaxTool for simplifying the code’s writing. It consists of regrouping the Tax Service code lines into one methods that we can call into taxonomic service. For example getTaxon(TaxonName) etc…
We have to keep in mind however that when we want to display a taxonomy in the interface, its already exists in the store data, so you have to construct the JTree exactly as the taxonomy is on the store data. So, there must be a link between the taxonomy element and JTree elements (node). For resuming, you have to “convert” Taxonomy element as JTree node.
2.2 - Precision about node in Jtree
To create a new node, we use the instance of DefaultMutableTreeNode class.
DefaultMutableTreeNode provides operations for examining and modifying a node's parent and children and also operations for examining the tree that the node is a part of. This class provides enumerations for efficiently traversing a tree or subtree in various orders or for following the path between two nodes.
The DefaultMutableTreeNode class has this constructor:
public DefaultMutableTreeNode( userObject)
It creates a tree node with no parent, no children, but which allows children, and initializes it with the specified user object.
Thus, we just have to create a class, which contains the info that we want to remind about the taxonomy element in order to convert it into a node without loosing the information. That’s the role of the FileInfo class.
This class has the following constructor:
public FileInfo(String name, String path, String filename, LinkedList children)
name – name of the taxon or the specimen
path – path of the url file
filename – name of the file
children – linked list of taxon children
Obviously, you don’t fill the same argument according to the Taxonomy elements.
For a Taxon:
FileInfo aFileInfo = new FileInfo(aTaxon.getName(), "", "", aTaxon.getChildren())
For a Specimen
FileInfo aFileInfo = new FileInfo(aSpecimen.getName(), urn2.getPath(), urn2.getFileName(), null)
Now, when you want to create a new DefautMutableTreeNode that corresponds to a taxonomy element, you first build an instance of FileInfo for reminding information (as the precedent manner).
Then, you create the node by this manner:
DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(aFileInfo)
Therefore the created node has a file info instance associated.
Now we know how to “convert” a taxonomy elements as a node (which have the necessary information), we can construct a JTree which refers to a taxonomy.
2.2 - Construction and displaying of the JTree
In order to create a newJTree instance, you need to set a root node. So the first thing to do is to handles the root taxon of the taxonomy in order to create the root node. Taxonomy Service Packed Method getRootTaxon(aTaxonomyName) return the FileInfo instance associated to the root taxon. So, as defined before, we create the root node with its file info associated.
Now that we have the root node, we can create the JTree by this way.
tree = new JTree(rootNode)
The JTree exists but its only display the root taxon. If you click on the tree, nothing happen. We have to create a tree events listener.
The TreeAction class implements TreeSelectionListener. If user clicks on the Tree, TreeAction class is executed.
Here is the way how TreeAction works for display and construct the tree.
The user opens a taxonomy, so the root taxon is displayed. Then the user selects the Root node in order to expand it. At the first click, the Tree Action class is called and checks which node is selected. For that, it does:
node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent()
Now we have the node selected, but we also need its file info. It’s done by this way:
FileInfo file = (FileInfo) node.getUserObject()
If it is checked then the selected node (here the root node) is expanded. If it’s not the case, it calls the function expandTreeNode(node,file) which work by this way.
It lists all the children of the current node (thanks to the linked list children of the FileInfo instance), and creates a node for each one and add them into the JTree with selected node as parents.
Now if the user double click another time on the root Node, the root node is expanded. It’s the same principle for all the other nodes when you want to expand them.
Of course, you can only expand nodes that refers to a Taxon. If you click on a specimen, it displays the corresponding URL (if it exists), else it displays a default URL.
To know if it is a specimen or a taxon, we create a service packed methods, which return null if it’s a taxon, which is selected.
So, now we know the way to construct the JTree that refers to a taxonomy, let us see how modify the JTree dynamically.
2.3 - Dynamic Modification of the JTree
JTree is an easy and usefully component for displaying hierarchical data but when you have to change its hierarchy, its not very common. Indeed, JTree has not a lot of methods implement for modification. (see part xx)
Create a Specimen or a Taxon
These two methods are quite close because they both consist of adding a new node to a parent node.
They both call an action window where you set the name of the new element to create.
fig xx: dialog box for adding a specimen
We have seen before (when we construct the JTree) that adding a node in the JTree seems to be easy but in fact, it is not. That’s easy in the precedent case because you add children to a parent node before having expand it, but if you want to add a node to a Tree which is already constructed with expanded node, you have to warn the JTree that its structure has changed, otherwise, the node is created but doesn’t appear in the Tree.
Realisation
First, you have to create the Specimen or the Taxon in the data store. So you create this element by calling taxonomic packed service methods createSpecimen or createTaxon.
Once this is done, you have to create a new node which refers to the created element. So, you get the taxonomy element by the packed methods getTaxon or getSpecimen which return the corresponding File Info. Therefore, you can create the new node aNewNode.
Then you add the node to the parent node parentNode by this way:
parentNode.add(aNewNode)
and you warn the tree that its structure has changed:
((DefaultTreeModel)aTree.getModel()).nodeStructureChanged((TreeNode)parentNode)
The following scheme resumes the adding of a node
Delete a specimen or a taxon
This two methods are also quite close because they both consist of erasing a node.
First you have to remove the node into the tree, thanks to the following methods
model.removeNodeFromParent(currentNode)
Then Remove the element into the taxonomy thanks to the taxonomy packed method deleteTaxon(aTaxonName) or deleteSpecimen(aSpecimen).
Cut and Paste
Cut and paste is an easy method to set once you know how to delete and add a node.
You have to remove the node that you want to cut, and to add to the node where user executes the past command.
You just have to take care that user can only do paste on taxon (because specimen can’t have children).
Promote – Demote
Due to the lack of methods for modifying its structure, promote and demote into a JTree is not very easy to set.
Promote and demote consist of changing the position of a node in a subtree. Promote level up a node and demote level down.
Realisation
You remove all the nodes situated after the node to promote, the nodes to promote, and the node just before it.
You execute the promote packed methods into the taxonomic store so the children linked list of the parent node change.
You add the node to promote.
You explore the linked list of children for adding the other node.
Obviously, you check if it’s possible to promote. Indeed if the node is at the top of the subtree, you can’t promote it. For doing that. we use the row of the node in the subtree.
Demote function-ment is almost the same.
.
Change of Taxonomy Elements properties
For taxon, this method consist of changing its name.
For specimen, you can change URL, or name.
For noticing the change in the interface, you have to create a new node which refers to the element with its news parameter. That’s quite close to promote and demote in fact. You remove the node which changes and you add the new node instead and you add the others nodes.
Additional features
Now we know how the communication between taxtool and data store is done. For finishing the goal of the interface, we just have to let the user edit the name of the files as in an explorer.
It’s quite simple to allow the user to edit name of a node:
When you create the tree you add:
tree.setEditable(true)
But, you have to catch the event of node change of name for calling the tax service change name methods. For this, we have to create a class which implements the TreeModel Listener, plays this role.
When this class is called, you just have to know if it’s a specimen or a taxon and then you call the right methods.
CONCLUSION
MULTI SELECTION DE FICHIER
PBEME AVEC LE LOAD