/* * 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(); } } } } }