/* * DBeaver - Universal Database Manager * Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org) * * 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.controls; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.views.properties.*; import org.jkiss.dbeaver.model.preferences.DBPPropertyDescriptor; import org.jkiss.dbeaver.utils.RuntimeUtils; import org.jkiss.dbeaver.runtime.properties.PropertiesContributor; import org.jkiss.dbeaver.runtime.properties.ILazyPropertyLoadListener; import org.jkiss.utils.ArrayUtils; import java.util.Iterator; public class PropertyPageStandard extends PropertySheetPage implements ILazyPropertyLoadListener, IPropertySourceProvider { private static class PropertySourceCache { Object object; IPropertySource propertySource; boolean cached; public PropertySourceCache(Object object) { if (object instanceof IPropertySource) { // Sometimes IPropertySource wrapper (e.g. PropertySourceEditable) may be used instead of real object this.object = ((IPropertySource)object).getEditableValue(); } else { this.object = object; } } } private PropertySourceCache[] curSelection = null; public PropertyPageStandard() { setSorter( new PropertySheetSorter() { @Override public int compare(IPropertySheetEntry entryA, IPropertySheetEntry entryB) { // No damn sorting return 0; } } ); setPropertySourceProvider(this); // Register lazy load listener PropertiesContributor.getInstance().addLazyListener(this); } @Override public void dispose() { // Unregister lazy load listener PropertiesContributor.getInstance().removeLazyListener(this); super.dispose(); } @Override public void handlePropertyLoad(Object object, DBPPropertyDescriptor property, Object propertyValue, boolean completed) { // Make page refresh if our main object was updated if (!ArrayUtils.isEmpty(curSelection) && !getControl().isDisposed()) { for (PropertySourceCache cache : curSelection) { if ((cache.propertySource != null && cache.propertySource.getEditableValue() == object) || cache.object == object) { refresh(); return; } } } //System.out.println("HEY: " + object + " | " + propertyId + " | " + propertyValue + " : " + completed); } @Override public void selectionChanged(IWorkbenchPart part, ISelection selection) { // Create objects cache if (selection instanceof IStructuredSelection) { IStructuredSelection ss = (IStructuredSelection)selection; curSelection = new PropertySourceCache[ss.size()]; if (ss.size() == 1) { curSelection[0] = new PropertySourceCache(ss.getFirstElement()); } else { int index = 0; for (Iterator<?> iter = ss.iterator(); iter.hasNext(); ) { curSelection[index++] = new PropertySourceCache(iter.next()); } } } getControl().setRedraw(false); try { super.selectionChanged(part, selection); } finally { getControl().setRedraw(true); } } @Override public IPropertySource getPropertySource(Object object) { if (object == null || object.getClass().isPrimitive() || object instanceof CharSequence || object instanceof Number || object instanceof Boolean) { // Just for better performance return null; } // Seek in cached property sources // Without cache we'll fall in infinite recursion when refreshing lazy props // (get prop source from adapter, load props, load lazy props -> refresh -> get prop source from adapter, etc). if (!ArrayUtils.isEmpty(curSelection)) { for (PropertySourceCache cache : curSelection) { if (cache.object == object) { if (!cache.cached) { cache.propertySource = RuntimeUtils.getObjectAdapter(object, IPropertySource.class); cache.cached = true; } return cache.propertySource; } } } return RuntimeUtils.getObjectAdapter(object, IPropertySource.class); } }