blob: a09f82526e3d43ad233287e5a468a7c8e5e0824d [file] [log] [blame]
/*
* Copyright (c) 2008, 2009, 2011, 2012, 2015 Eike Stepper (Berlin, Germany) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Eike Stepper - initial API and implementation
*/
package org.eclipse.net4j.util.ui.views;
import org.eclipse.net4j.util.ObjectUtil;
import org.eclipse.net4j.util.internal.ui.bundle.OM;
import org.eclipse.net4j.util.internal.ui.messages.Messages;
import org.eclipse.net4j.util.ui.UIUtil;
import org.eclipse.net4j.util.ui.actions.SafeAction;
import org.eclipse.net4j.util.ui.actions.SashLayoutAction;
import org.eclipse.net4j.util.ui.widgets.CoolBarComposite;
import org.eclipse.net4j.util.ui.widgets.SashComposite;
import org.eclipse.jface.action.IContributionManager;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
/**
* @author Eike Stepper
* @since 2.0
*/
public abstract class MasterDetailsView extends MultiViewersView
{
private StructuredViewer master;
private CTabFolder detailsFolder;
private Object currentMasterElement = new Object();
private String[] detailTitles;
private CTabItem[] detailItems;
private StructuredViewer[] details;
private int currentDetailIndex;
private SashComposite sash;
public MasterDetailsView()
{
}
public StructuredViewer getMaster()
{
return master;
}
public StructuredViewer[] getDetails()
{
return details;
}
public String[] getDetailTitles()
{
return detailTitles;
}
public Object getCurrentMasterElement()
{
return currentMasterElement;
}
public int getCurrentDetailIndex()
{
return currentDetailIndex;
}
public String getCurrentDetailTitle()
{
if (detailTitles == null || currentDetailIndex == -1)
{
return null;
}
return detailTitles[currentDetailIndex];
}
@Override
protected Control createUI(Composite parent)
{
sash = new SashComposite(parent, SWT.NONE, 10, 50, true)
{
@Override
protected Control createControl1(Composite parent)
{
master = createMaster(parent);
return master.getControl();
}
@Override
protected Control createControl2(Composite parent)
{
return new CoolBarComposite(parent, SWT.NONE)
{
@Override
protected Control createUI(Composite parent)
{
// Styles: CLOSE, TOP, BOTTOM, FLAT, BORDER, SINGLE, MULTI
detailsFolder = new CTabFolder(parent, SWT.BOTTOM | SWT.FLAT);
detailsFolder.setLayoutData(UIUtil.createGridData());
adjustDetails(null);
detailsFolder.addSelectionListener(new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent e)
{
String title = detailsFolder.getSelection().getText();
int detailIndex = indexOf(detailItems, title);
if (detailIndex != currentDetailIndex)
{
currentDetailIndex = detailIndex;
updateCoolBar();
}
}
});
return detailsFolder;
}
@Override
protected void fillCoolBar(IContributionManager manager)
{
MasterDetailsView.this.fillCoolBar(manager);
manager.add(new RefreshAction());
}
};
}
};
sash.setVertical(true);
setCurrentViewer(master);
master.addSelectionChangedListener(new ISelectionChangedListener()
{
public void selectionChanged(SelectionChangedEvent event)
{
try
{
masterSelectionChanged(event);
}
catch (Error ex)
{
OM.LOG.error(ex);
throw ex;
}
catch (RuntimeException ex)
{
OM.LOG.error(ex);
throw ex;
}
}
});
return sash;
}
@Override
protected void fillLocalPullDown(IMenuManager manager)
{
super.fillLocalPullDown(manager);
manager.add(new Separator("group1")); //$NON-NLS-1$
manager.add(new SashLayoutAction.LayoutMenu(sash));
manager.add(new Separator("group2")); //$NON-NLS-1$
manager.add(new RefreshAction());
}
protected void masterSelectionChanged(SelectionChangedEvent event)
{
IStructuredSelection selection = (IStructuredSelection)master.getSelection();
Object masterElement = selection.getFirstElement();
adjustDetails(masterElement);
}
protected void adjustDetails(Object masterElement)
{
if (ObjectUtil.equals(masterElement, currentMasterElement))
{
return;
}
// Temporarily remember old values
String oldDetailTitle = detailItems == null || currentDetailIndex < 0 ? null
: detailItems[currentDetailIndex].getText();
StructuredViewer[] oldDetails = details;
CTabItem[] oldDetailItems = detailItems;
// Initialize new values
detailTitles = getDetailTitles(masterElement);
details = new StructuredViewer[detailTitles.length];
detailItems = new CTabItem[detailTitles.length];
for (int i = 0; i < detailTitles.length; i++)
{
String title = detailTitles[i];
int oldIndex = indexOf(oldDetailItems, title);
if (oldIndex != -1)
{
details[i] = oldDetails[oldIndex];
oldDetailItems[oldIndex].setControl(null);
oldDetailItems[oldIndex].dispose();
oldDetailItems[oldIndex] = null;
}
else
{
details[i] = createDetail(detailsFolder, title);
}
detailItems[i] = new CTabItem(detailsFolder, SWT.NONE, i);
detailItems[i].setText(title);
detailItems[i].setControl(details[i].getControl());
}
// Cleanup
if (oldDetailItems != null)
{
for (CTabItem item : oldDetailItems)
{
if (item != null)
{
item.dispose();
}
}
}
currentMasterElement = masterElement;
for (StructuredViewer viewer : details)
{
setDetailInput(viewer, masterElement);
}
currentDetailIndex = indexOf(detailItems, oldDetailTitle);
if (currentDetailIndex == -1 && details.length > 0)
{
currentDetailIndex = 0;
}
if (currentDetailIndex != -1)
{
detailsFolder.setSelection(currentDetailIndex);
}
}
protected void setDetailInput(StructuredViewer viewer, Object input)
{
if (input != viewer.getInput())
{
viewer.setInput(input);
}
}
protected void fillCoolBar(IContributionManager manager)
{
}
protected abstract StructuredViewer createMaster(Composite parent);
protected abstract StructuredViewer createDetail(Composite parent, String title);
protected abstract String[] getDetailTitles(Object masterElement);
public static int indexOf(CTabItem[] items, String title)
{
if (items != null)
{
for (int i = 0; i < items.length; i++)
{
CTabItem item = items[i];
if (item != null && ObjectUtil.equals(item.getText(), title))
{
return i;
}
}
}
return -1;
}
/**
* @author Eike Stepper
*/
protected final class RefreshAction extends SafeAction
{
public RefreshAction()
{
super(Messages.getString("MasterDetailsView_2"), Messages.getString("MasterDetailsView_3"), //$NON-NLS-1$ //$NON-NLS-2$
OM.getImageDescriptor("icons/full/etool16/refresh.gif")); //$NON-NLS-1$
}
@Override
protected void safeRun() throws Exception
{
StructuredViewer viewer = getCurrentViewer();
if (viewer != null)
{
viewer.refresh();
}
}
}
}