/** * Constructor initialises the table and a popup tool, as well as initialising the required GUI * elements. It adds action listeners for the three main buttons, which include basic user input * validation checking. */ public TableAttributeEditor(JFrame MyOwner) { // As usual, it is insanely hard to get the swing components to display // and work properly. If JTable is not displayed in a scroll pane no headers are // displayed, and you have to do it manually. (If you *do* display it // in a scrollbar, in this instance, it screws up sizing) // The broken header mis-feature is only mentioned in the tutorial, // not in the api doco - go figure. super(); owner = MyOwner; // final JPanel mainPanel = (JPanel)this; tableData = new AttributeTableModel(); attributeTable = new JTable(tableData); // attributeTable.setRowHeight(20); // This may be needed, depends on how fussy people get about // the bottom of letters like 'y' getting cut off when the cell is selected - bug 3013. popupTableTool = new SmartPopupTableTool(attributeTable, tableData, (JXplorerBrowser) owner); // Set the renderer for the attribute type... final AttributeTypeCellRenderer typeRenderer = new AttributeTypeCellRenderer(); attributeTable.setDefaultRenderer(AttributeNameAndType.class, typeRenderer); // Set the renderer for the attribute value... final AttributeValueCellRenderer valueRenderer = new AttributeValueCellRenderer(); attributeTable.setDefaultRenderer(AttributeValue.class, valueRenderer); // Set the editor for the attribute value... myEditor = new AttributeValueCellEditor(owner); attributeTable.setDefaultEditor(AttributeValue.class, myEditor); attributeTable.getTableHeader().setReorderingAllowed(false); currentDN = null; JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); buttonPanel.add( submit = new CBButton( CBIntText.get("Submit"), CBIntText.get("Submit your changes to the Directory."))); buttonPanel.add( reset = new CBButton( CBIntText.get("Reset"), CBIntText.get("Reset this entry i.e. cancels any changes."))); buttonPanel.add( changeClass = new CBButton( CBIntText.get("Change Classes"), CBIntText.get("Change the Object Class of this entry."))); buttonPanel.add( opAttrs = new CBButton( CBIntText.get("Properties"), CBIntText.get("View the Operational Attributes of this entry."))); // I don't really understand why we have to do this... // but without it these buttons over ride the default // button (Search Bar's search button), if they have // been clicked and the user hits the enter key? opAttrs.setDefaultCapable(false); submit.setDefaultCapable(false); reset.setDefaultCapable(false); changeClass.setDefaultCapable(false); setLayout(new BorderLayout(10, 10)); tableScroller = new JScrollPane(); attributeTable.setBackground(Color.white); tableScroller.setPreferredSize(new Dimension(300, 285)); tableScroller.setViewportView(attributeTable); add(tableScroller, BorderLayout.CENTER); add(buttonPanel, BorderLayout.SOUTH); if ("true".equals(JXConfig.getProperty("lock.read.only"))) title = CBIntText.get("Table Viewer"); else title = CBIntText.get("Table Editor"); setVisible(true); // triggers adding operational attributes of the current entry. opAttrs.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { displayOperationalAttributes(); } }); reset.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { myEditor.stopCellEditing(); // tableData.reset(); displayEntry(originalEntry, dataSource, false); } }); submit.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { doSubmit(); } }); // This allows the user to change the objectclass attribute. // This is pretty tricky, because it changes what attributes are available. changeClass.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { changeClass(); } }); attributeTable.addMouseListener( new MouseAdapter() { public void mousePressed(MouseEvent e) { if (!doPopupStuff(e)) super.mousePressed(e); } public void mouseReleased(MouseEvent e) { if (!doPopupStuff(e)) super.mouseReleased(e); } // TODO need to have a way to call this from a keystroke... public boolean doPopupStuff(MouseEvent e) { if (e.isPopupTrigger() == false) return false; int row = attributeTable.rowAtPoint(new Point(e.getX(), e.getY())); attributeTable.clearSelection(); attributeTable.addRowSelectionInterval(row, row); attributeTable.repaint(); popupTableTool.registerCurrentRow( (AttributeNameAndType) attributeTable.getValueAt(row, 0), (AttributeValue) attributeTable.getValueAt(row, 1), row, tableData.getRDN()); // active path also set by valueChanged popupTableTool.show(attributeTable, e.getX(), e.getY()); popupTableTool.registerCellEditor(myEditor); // TE: for bug fix 3107. return true; } }); }
private void displayEntry( DXEntry entry, DataBrokerQueryInterface ds, boolean storeOriginalEntry) { myEditor.stopCellEditing(); // checkedDN = null; // hack - resets promptForSave. // Store original Entry for reset if (entry != null && storeOriginalEntry && entry.getStatus() == DXEntry.NORMAL) originalEntry = new DXEntry(entry); // Set the globals... currentEntry = entry; dataSource = ds; if (entry != null && entry.size() == 0) { // If there is an entry and its size is zero - it's probably a virtual entry. // We need to give the user the option of adding an object class to it i.e. so that // it can be added to the directory as a real entry. // // Disable all the buttons except the 'Change Class' button - but rename this button // to 'Add Class' so the user hopefully has a bit more of an idea about what is going on. // Sets editor to a blank screen... tableData.clear(); // Disable all buttons except the 'Change Class' button - rename this one... submit.setEnabled(false); reset.setEnabled(false); changeClass.setText(CBIntText.get("Add Class")); changeClass.setEnabled(true); opAttrs.setEnabled(false); virtualEntry = true; return; } virtualEntry = false; // Isn't a virtual entry... if (entry != null) currentDN = entry.getDN(); // May have been changed to 'Add Class'... changeClass.setText(CBIntText.get("Change Class")); // Some quick faffing around, to see if we're coming back from a // change classes operation. if (classChangedOriginalEntry != null) { // If they have the same name, then we're reviewing the same entry - otherwise we've moved on if (entry == null || entry.getDN().equals(classChangedOriginalEntry.getDN()) == false) classChangedOriginalEntry = null; } /* * Check that we're not displaying a new entry, and leaving unsaved changes * behind. * * This turns out to be quite tricky, and involves a bunch 'o special cases. * * First check whether the table data has changed (if not, do nothing) * -> if the new entry is null, prompt user to save * -> OR if the DN has changed, and it wasn't due to a rename, prompt user to save * */ if (tableData.changedByUser()) // user made changes - were they saved? (i.e., are we { // displaying the result of those changes?) boolean prompt = false; DXEntry oldEntry = tableData.getOldEntry(); if (oldEntry != null) { /* * The code below is simply checking to see if the name of the * new entry is different from the old entry, and if it is, * whether that's due to the old entry being renamed. */ if (entry == null) { prompt = true; } // TE: added the isEmpty check see bug: 3194. else if (!oldEntry.getDN().isEmpty() && entry.getDN().equals(oldEntry.getDN()) == false) { DN oldParent = oldEntry.getDN().getParent(); DN newParent = entry.getDN().getParent(); if (oldParent.equals(newParent) == false) { prompt = true; } else { if (entry.getDN().getLowestRDN().equals(tableData.getRDN()) == false) { prompt = true; } } } if (prompt) // yes, there is a risk of data loss - prompt the user. { checkForUnsavedChanges(); // see if the user wants to save their data } } } myEditor.setDataSource( ds); // Sets the DataBrokerQueryInterface in AttributeValueCellEditor used to get the syntax // of attributes. // only enable buttons if DataBrokerQueryInterface // is valid *and* we can modify data... if (dataSource == null || entry == null || dataSource.isModifiable() == false) { setReadWrite(false, entry); } else { setReadWrite(true, entry); } // myEditor.stopCellEditing(); if (entry != null) { entry.expandAllAttributes(); currentDN = entry.getDN(); tableData.insertAttributes(entry); popupTableTool.setDN(currentDN); // Sets the DN in SmartPopupTableTool. myEditor.setDN( currentDN); // Sets the DN in the attributeValueCellEditor which can be used to identify // the entry that is being modified/ } else { tableData.clear(); // Sets editor to a blank screen. } tableScroller.getVerticalScrollBar().setValue(0); // Sets the scroll bar back to the top. }