![JAR search and dependency download from the Maven repository](/logo.png)
org.datacleaner.panels.SchemaTreePanel Maven / Gradle / Ivy
/**
* DataCleaner (community edition)
* Copyright (C) 2014 Free Software Foundation, Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.datacleaner.panels;
import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.inject.Inject;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.SwingWorker;
import javax.swing.event.DocumentEvent;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.SimpleAttributeSet;
import org.datacleaner.connection.Datastore;
import org.datacleaner.guice.InjectorBuilder;
import org.datacleaner.util.DCDocumentListener;
import org.datacleaner.util.WidgetUtils;
import org.datacleaner.widgets.LoadingIcon;
import org.datacleaner.widgets.tree.SchemaTree;
import org.jdesktop.swingx.JXTextField;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Strings;
import com.google.inject.Injector;
/**
* Panel that wraps the {@link SchemaTree} as well as actions around it for
* searching/filtering etc.
*/
public class SchemaTreePanel extends DCPanel {
private static final long serialVersionUID = 1L;
private static final Logger logger = LoggerFactory.getLogger(SchemaTreePanel.class);
private static final String DEFAULT_SEARCH_FIELD_TEXT = "Search component library...";
private final InjectorBuilder _injectorBuilder;
private final JXTextField _searchTextField;
private final JComponent _resetSearchButton;
private JComponent _updatePanel;
private SchemaTree _schemaTree;
@Inject
protected SchemaTreePanel(final InjectorBuilder injectorBuilder) {
super(WidgetUtils.COLOR_DEFAULT_BACKGROUND);
_injectorBuilder = injectorBuilder;
_searchTextField = createSearchTextField();
_resetSearchButton = createResetSearchButton();
setLayout(new BorderLayout());
setBorder(WidgetUtils.BORDER_EMPTY);
setDatastore(null, false);
setFocusable(true);
}
/**
* Method invoked when this panel is not longer shown to the user (typically
* because there is no longer any open datastore / job).
*
* Note: This method is here because the {@link #removeNotify()} method is
* not invoked by the layout manager of the parent window.
*/
public void onPanelHiding() {
resetSearch();
// remove children to notify them
removeAll();
updateParentPanel();
}
public void setDatastore(final Datastore datastore, final boolean expandTree) {
removeAll();
if (datastore == null) {
add(new DCPanel().setPreferredSize(150, 150), BorderLayout.CENTER);
return;
}
add(new LoadingIcon().setPreferredSize(150, 150), BorderLayout.CENTER);
// load the schema tree in the background because it will retrieve
// metadata about the datastore (might take several seconds)
new SwingWorker() {
@Override
protected SchemaTree doInBackground() throws Exception {
final Injector injector = _injectorBuilder.with(Datastore.class, datastore).createInjector();
return injector.getInstance(SchemaTree.class);
}
protected void done() {
try {
_schemaTree = get();
final JScrollPane schemaTreeScroll = WidgetUtils.scrolleable(_schemaTree);
schemaTreeScroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
_schemaTree.addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(final ComponentEvent e) {
updateParentPanel();
}
});
_schemaTree.setFocusable(true);
_schemaTree.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(final KeyEvent e) {
if (_searchTextField.isFocusOwner()) {
// let the normal search text work as it should
return;
}
final char keyChar = e.getKeyChar();
switch (keyChar) {
case KeyEvent.VK_ESCAPE:
case KeyEvent.VK_DELETE:
_searchTextField.setText("");
break;
case KeyEvent.VK_BACK_SPACE:
try {
final Document document = _searchTextField.getDocument();
final int index = document.getLength() - 1;
if (index >= 0) {
document.remove(index, 1);
}
} catch (final BadLocationException ex) {
logger.debug("Document.remove() failed", ex);
}
break;
default:
if (!e.isActionKey() && Character.isLetter(keyChar)) {
try {
final Document document = _searchTextField.getDocument();
document.insertString(document.getLength(), "" + keyChar,
SimpleAttributeSet.EMPTY);
} catch (final BadLocationException ex) {
logger.debug("Document.insertString({}) failed", keyChar, ex);
}
}
}
}
});
removeAll();
add(schemaTreeScroll, BorderLayout.CENTER);
final DCPanel searchComponent = new DCPanel(WidgetUtils.BG_COLOR_BRIGHTEST);
searchComponent.setLayout(new BorderLayout());
searchComponent.add(_searchTextField, BorderLayout.CENTER);
searchComponent.add(_resetSearchButton, BorderLayout.EAST);
add(searchComponent, BorderLayout.SOUTH);
_schemaTree.expandStandardPaths();
if (expandTree) {
_schemaTree.expandSelectedData();
}
updateParentPanel();
} catch (final Exception e) {
throw new RuntimeException(e);
}
}
}.execute();
}
private JComponent createResetSearchButton() {
final JLabel resetSearchFieldIcon = new JLabel("X");
resetSearchFieldIcon.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
resetSearchFieldIcon.setBorder(WidgetUtils.BORDER_EMPTY);
resetSearchFieldIcon.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(final MouseEvent e) {
resetSearch();
}
});
return resetSearchFieldIcon;
}
public void resetSearch() {
final String currentText = _searchTextField.getText();
if (Strings.isNullOrEmpty(currentText)) {
// do nothing
return;
}
_searchTextField.setText("");
_schemaTree.filter("");
}
protected JXTextField createSearchTextField() {
final JXTextField searchTextField = new JXTextField(DEFAULT_SEARCH_FIELD_TEXT);
searchTextField.addFocusListener(new FocusAdapter() {
@Override
public void focusGained(final FocusEvent e) {
final int length = searchTextField.getText().length();
searchTextField.select(length, length);
}
});
searchTextField.getDocument().addDocumentListener(new DCDocumentListener() {
@Override
protected void onChange(final DocumentEvent event) {
_schemaTree.filter(searchTextField.getText());
}
});
searchTextField.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(final KeyEvent e) {
if (e.getKeyChar() == KeyEvent.VK_ESCAPE) {
searchTextField.setText("");
}
}
});
searchTextField.setBorder(WidgetUtils.BORDER_EMPTY);
return searchTextField;
}
private void updateParentPanel() {
if (_updatePanel != null) {
_updatePanel.updateUI();
}
}
public void setUpdatePanel(final JComponent updatePanel) {
_updatePanel = updatePanel;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy