blob: 00ad9a4ad258527fdb4379b51ea503c8c5b41175 [file] [log] [blame]
/*
* Copyright (c) 2007-2009, 2011, 2012 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.widgets;
import org.eclipse.net4j.util.event.IListener;
import org.eclipse.net4j.util.event.INotifier;
import org.eclipse.net4j.util.event.Notifier;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Sash;
/**
* @author Eike Stepper
*/
public abstract class SashComposite extends Composite implements INotifier
{
private final SashListener sashListener = new SashListener();
private final Notifier notifier = new Notifier();
private int limit;
private int percent;
private boolean borders;
private boolean vertical;
private Sash sash;
private Control control1;
private Control control2;
private FormData sashData;
private FormData control1Data;
private FormData control2Data;
public SashComposite(Composite parent, int style, int limit, int percent)
{
this(parent, style, limit, percent, false);
}
public SashComposite(Composite parent, int style, int limit, int percent, boolean borders)
{
super(parent, style);
setLayout(new FormLayout());
this.limit = limit;
this.percent = percent;
this.borders = borders;
control1Data = new FormData();
control1 = borders ? new OneBorderComposite(this)
{
@Override
protected Control createUI(Composite parent)
{
return createControl1(parent);
}
} : createControl1(this);
control1.setLayoutData(control1Data);
sashData = new FormData();
sash = createSash(this);
sash.setLayoutData(sashData);
control2Data = new FormData();
control2 = borders ? new OneBorderComposite(this)
{
@Override
protected Control createUI(Composite parent)
{
return createControl2(parent);
}
} : createControl2(this);
control2.setLayoutData(control2Data);
init();
}
/**
* @since 2.0
*/
@Override
public void dispose()
{
sash.removeListener(SWT.Selection, sashListener);
super.dispose();
}
/**
* @since 2.0
*/
public void addListener(IListener listener)
{
notifier.addListener(listener);
}
/**
* @since 2.0
*/
public IListener[] getListeners()
{
return notifier.getListeners();
}
/**
* @since 2.0
*/
public boolean hasListeners()
{
return notifier.hasListeners();
}
/**
* @since 2.0
*/
public void removeListener(IListener listener)
{
notifier.removeListener(listener);
}
public boolean isVertical()
{
return vertical;
}
public void setVertical(boolean vertical)
{
if (this.vertical != vertical)
{
this.vertical = vertical;
Sash newSash = createSash(this);
newSash.moveBelow(control1);
newSash.setLayoutData(sash.getLayoutData());
sash.removeListener(SWT.Selection, sashListener);
sash.setLayoutData(null);
sash.dispose();
sash = newSash;
init();
layout();
IListener[] listeners = notifier.getListeners();
if (listeners != null)
{
notifier.fireEvent(new OrientationChangedEvent(vertical), listeners);
}
}
}
public Sash getSash()
{
return sash;
}
public Control getControl1()
{
return borders ? ((OneBorderComposite)control1).getClientControl() : control1;
}
public Control getControl2()
{
return borders ? ((OneBorderComposite)control2).getClientControl() : control2;
}
protected void init()
{
if (borders)
{
((OneBorderComposite)control1).setBorderPosition(SWT.RIGHT);
((OneBorderComposite)control2).setBorderPosition(SWT.LEFT);
}
control1Data.left = new FormAttachment(0, 0);
control1Data.right = new FormAttachment(sash, 0);
control1Data.top = new FormAttachment(0, 0);
control1Data.bottom = new FormAttachment(100, 0);
sashData.left = new FormAttachment(percent, 0);
sashData.right = null;
sashData.top = new FormAttachment(0, 0);
sashData.bottom = new FormAttachment(100, 0);
control2Data.left = new FormAttachment(sash, 0);
control2Data.right = new FormAttachment(100, 0);
control2Data.top = new FormAttachment(0, 0);
control2Data.bottom = new FormAttachment(100, 0);
if (vertical)
{
swap();
}
}
protected void swap()
{
if (borders)
{
((OneBorderComposite)control1).swapBorderPosition();
((OneBorderComposite)control2).swapBorderPosition();
}
swap(control1Data);
swap(sashData);
swap(control2Data);
}
protected void swap(FormData formData)
{
FormAttachment tmp1 = formData.left;
formData.left = formData.top;
formData.top = tmp1;
FormAttachment tmp2 = formData.right;
formData.right = formData.bottom;
formData.bottom = tmp2;
}
protected Sash createSash(Composite parent)
{
Sash sash = new Sash(parent, vertical ? SWT.HORIZONTAL : SWT.VERTICAL);
sash.addListener(SWT.Selection, sashListener);
return sash;
}
protected abstract Control createControl1(Composite parent);
protected abstract Control createControl2(Composite parent);
/**
* @author Eike Stepper
* @since 2.0
*/
public class OrientationChangedEvent extends org.eclipse.net4j.util.event.Event
{
private static final long serialVersionUID = 1L;
private boolean vertical;
public OrientationChangedEvent(boolean vertical)
{
super(SashComposite.this);
}
@Override
public SashComposite getSource()
{
return (SashComposite)super.getSource();
}
public boolean isVertical()
{
return vertical;
}
}
/**
* @author Eike Stepper
*/
private final class SashListener implements Listener
{
public SashListener()
{
}
public void handleEvent(Event e)
{
Rectangle sashRect = sash.getBounds();
Rectangle shellRect = getClientArea();
if (!vertical)
{
int right = shellRect.width - sashRect.width - limit;
e.x = Math.max(Math.min(e.x, right), limit);
if (e.x != sashRect.x)
{
sashData.left = new FormAttachment(0, e.x);
layout();
}
}
else
{
int bottom = shellRect.height - sashRect.height - limit;
e.y = Math.max(Math.min(e.y, bottom), limit);
if (e.y != sashRect.y)
{
sashData.top = new FormAttachment(0, e.y);
layout();
}
}
}
}
}