/* * DBeaver - Universal Database Manager * Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org) * Copyright (C) 2011-2012 Eugene Fradkin (eugene.fradkin@gmail.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jkiss.dbeaver.ui.dialogs.driver; import org.eclipse.jface.viewers.*; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.TreeColumn; import org.jkiss.dbeaver.model.DBIcon; import org.jkiss.dbeaver.model.DBPImage; import org.jkiss.dbeaver.registry.DataSourceProviderDescriptor; import org.jkiss.dbeaver.registry.DataSourceProviderRegistry; import org.jkiss.dbeaver.registry.driver.DriverDescriptor; import org.jkiss.dbeaver.ui.DBeaverIcons; import org.jkiss.dbeaver.ui.UIUtils; import org.jkiss.utils.CommonUtils; import java.util.*; /** * DriverTreeViewer * * @author Serge Rider */ public class DriverTreeViewer extends TreeViewer implements ISelectionChangedListener, IDoubleClickListener { private Object site; private List<DataSourceProviderDescriptor> providers; private Font boldFont; private final Map<String,DriverCategory> categories = new HashMap<>(); private final List<Object> driverList = new ArrayList<>(); public static class DriverCategory { final String name; final List<DriverDescriptor> drivers = new ArrayList<>(); public DriverCategory(String name) { this.name = name; } public String getName() { return name; } public List<DriverDescriptor> getDrivers() { return drivers; } @Override public String toString() { return name; } @Override public boolean equals(Object obj) { return obj instanceof DriverCategory && ((DriverCategory) obj).name.equals(name); } @Override public int hashCode() { return name.hashCode(); } } public DriverTreeViewer(Composite parent, int style) { super(parent, style); boldFont = UIUtils.makeBoldFont(parent.getFont()); parent.addDisposeListener(new DisposeListener() { @Override public void widgetDisposed(DisposeEvent e) { UIUtils.dispose(boldFont); } }); } public void initDrivers(Object site, List<DataSourceProviderDescriptor> providers, boolean expandRecent) { // getTree().setHeaderVisible(true); this.site = site; this.providers = providers; if (this.providers == null) { this.providers = DataSourceProviderRegistry.getInstance().getDataSourceProviders(); } TreeColumn nameColumn = new TreeColumn(getTree(), SWT.LEFT); nameColumn.setText("Name"); TreeColumn usersColumn = new TreeColumn(getTree(), SWT.LEFT); usersColumn.setText("#"); this.setContentProvider(new ViewContentProvider()); this.setLabelProvider(new ViewLabelProvider()); this.addSelectionChangedListener(this); this.addDoubleClickListener(this); this.getControl().setLayoutData(new GridData(GridData.FILL_BOTH)); Collection<Object> drivers = collectDrivers(); this.setInput(drivers); this.expandAll(); getTree().addListener(SWT.Resize, new Listener() { volatile boolean resizing = false; @Override public void handleEvent(Event event) { if (resizing) { return; } resizing = true; try { UIUtils.packColumns(getTree(), true, new float[] {0.9f, 0.1f}); } finally { resizing = false; } } }); if (expandRecent) { // Expand used driver categories for (Object driver : drivers) { if (driver instanceof DriverCategory && getConnectionCount(driver) > 0) { expandToLevel(driver, ALL_LEVELS); } else { collapseToLevel(driver, ALL_LEVELS); } } } else { this.collapseAll(); } } @Override public void refresh() { collectDrivers(); super.refresh(); } private Collection<Object> collectDrivers() { for (DriverCategory category : categories.values()) { category.drivers.clear(); } driverList.clear(); for (DataSourceProviderDescriptor provider : providers) { List<DriverDescriptor> drivers = provider.getEnabledDrivers(); for (DriverDescriptor driver : drivers) { String category = driver.getCategory(); if (CommonUtils.isEmpty(category)) { driverList.add(driver); } else { DriverCategory driverCategory = categories.get(category); if (driverCategory == null) { driverCategory = new DriverCategory(category); categories.put(category, driverCategory); } if (!driverList.contains(driverCategory)) { driverList.add(driverCategory); } driverCategory.drivers.add(driver); } } } Collections.sort(driverList, new Comparator<Object>() { @Override public int compare(Object o1, Object o2) { int count1 = getConnectionCount(o1); int count2 = getConnectionCount(o2); if (count1 == count2) { String name1 = o1 instanceof DriverDescriptor ? ((DriverDescriptor) o1).getName() : ((DriverCategory)o1).getName(); String name2 = o2 instanceof DriverDescriptor ? ((DriverDescriptor) o2).getName() : ((DriverCategory)o2).getName(); return name1.compareToIgnoreCase(name2); } else { return count2 - count1; } } }); for (DriverCategory category : categories.values()) { Collections.sort(category.drivers, new Comparator<DriverDescriptor>() { @Override public int compare(DriverDescriptor o1, DriverDescriptor o2) { return o1.getName().compareToIgnoreCase(o2.getName()); } }); } return driverList; } public int getConnectionCount(Object obj) { if (obj instanceof DataSourceProviderDescriptor) { int count = 0; for (DriverDescriptor driver : ((DataSourceProviderDescriptor) obj).getEnabledDrivers()) { count += driver.getUsedBy().size(); } return count; } else if (obj instanceof DriverCategory) { int count = 0; for (DriverDescriptor driver : ((DriverCategory) obj).drivers) { count += driver.getUsedBy().size(); } return count; } else if (obj instanceof DriverDescriptor) { return ((DriverDescriptor) obj).getUsedBy().size(); } else { return 0; } } class ViewContentProvider implements ITreeContentProvider { @Override public void inputChanged(Viewer v, Object oldInput, Object newInput) { } @Override public void dispose() { } @Override public Object[] getElements(Object parent) { return getChildren(parent); } @Override public Object getParent(Object child) { if (child instanceof DriverDescriptor) { DriverDescriptor driver = (DriverDescriptor) child; if (driver.getCategory() != null) { return categories.get(driver.getCategory()); } } return null; } @Override public Object[] getChildren(Object parent) { if (parent instanceof Collection) { return ((Collection) parent).toArray(); } else if (parent instanceof DriverCategory) { return ((DriverCategory) parent).getDrivers().toArray(); } else { return new Object[0]; } } @Override public boolean hasChildren(Object parent) { if (parent instanceof DriverCategory) { return !((DriverCategory) parent).drivers.isEmpty(); } return false; } } class ViewLabelProvider extends CellLabelProvider implements ILabelProvider { @Override public void update(ViewerCell cell) { switch (cell.getColumnIndex()) { case 0: cell.setText(getText(cell.getElement())); break; case 1: final int count = getConnectionCount(cell.getElement()); cell.setText(count <= 0 ? "" : String.valueOf(count)); break; default: cell.setText(""); break; } DBPImage image = getImage(cell.getElement(), cell.getColumnIndex()); if (image != null) { cell.setImage(DBeaverIcons.getImage(image)); } if (cell.getElement() instanceof DriverDescriptor && !((DriverDescriptor)cell.getElement()).getUsedBy().isEmpty()) { //cell.setFont(boldFont); } else { cell.setFont(null); } } public String getDescription(Object obj) { if (obj instanceof DataSourceProviderDescriptor) { return ((DataSourceProviderDescriptor) obj).getDescription(); } else if (obj instanceof DriverDescriptor) { return ((DriverDescriptor) obj).getDescription(); } else { return ""; } } public DBPImage getImage(Object obj, int index) { if (index != 0) { return null; } DBPImage defImage = DBIcon.TREE_PAGE; if (obj instanceof DataSourceProviderDescriptor) { DBPImage icon = ((DataSourceProviderDescriptor) obj).getIcon(); if (icon != null) { return icon; } defImage = DBIcon.TREE_FOLDER; } else if (obj instanceof DriverCategory) { return DBIcon.TREE_DATABASE_CATEGORY; } else if (obj instanceof DriverDescriptor) { DBPImage icon = ((DriverDescriptor) obj).getIcon(); if (icon != null) { return icon; } } return defImage; } @Override public Image getImage(Object element) { return DBeaverIcons.getImage(getImage(element, 0)); } @Override public String getText(Object element) { if (element instanceof DataSourceProviderDescriptor) { return ((DataSourceProviderDescriptor) element).getName(); } else if (element instanceof DriverCategory) { return ((DriverCategory) element).name; } else if (element instanceof DriverDescriptor) { return ((DriverDescriptor) element).getName(); } else { return element.toString(); } } } @Override public void selectionChanged(SelectionChangedEvent event) { if (site instanceof ISelectionChangedListener) { ((ISelectionChangedListener)site).selectionChanged(event); } } @Override public void doubleClick(DoubleClickEvent event) { if (site instanceof IDoubleClickListener) { ((IDoubleClickListener)site).doubleClick(event); } IStructuredSelection selection = (IStructuredSelection) event.getSelection(); if (!selection.isEmpty()) { Object element = selection.getFirstElement(); if (element instanceof DriverCategory || element instanceof DataSourceProviderDescriptor) { if (Boolean.TRUE.equals(getExpandedState(element))) { super.collapseToLevel(element, 1); } else { super.expandToLevel(element, 1); } } } } }