/****************************************************************************
* Copyright (c) 2008, 2009 Jeremy Dowdall
* 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:
* Jeremy Dowdall <jeremyd@aspencloud.com> - initial API and implementation
*****************************************************************************/
package org.eclipse.nebula.cwt.v;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.ListIterator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Listener;
public class VPanel extends VControl {
Composite widget;
List<VControl> children = new ArrayList<VControl>();
private VLayout layout = null;
private boolean isTopLevel = false;
private Listener topLevelListener;
public VPanel(Composite parent, int style) {
this((VPanel) null, style & ~SWT.BORDER);
isTopLevel = true;
composite = parent;
topLevelListener = new Listener() {
public void handleEvent(Event event) {
switch(event.type) {
case SWT.Dispose:
dispose(false);
break;
// case SWT.FocusIn:
// setFocus();
// break;
case SWT.Paint:
paintControl(event);
break;
}
}
};
composite.addListener(SWT.Dispose, topLevelListener);
composite.addListener(SWT.FocusIn, topLevelListener);
composite.addListener(SWT.Paint, topLevelListener);
composite.setLayout(new Layout() {
protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
return VPanel.this.computeSize(wHint, hHint, flushCache);
}
protected void layout(Composite composite, boolean flushCache) {
VPanel.this.setBounds(composite.getClientArea());
VPanel.this.layout(flushCache);
}
});
VTracker.addTopLevelPanel(this);
composite.setData("cwt_vcontrol", this);
}
public VPanel(VPanel panel, int style) {
super(panel, style);
marginTop = marginBottom = marginLeft = marginRight = 0;
setLayout(new VGridLayout());
setPainter(new VPanelPainter());
}
void addChild(VControl child) {
if(!children.contains(child)) {
children.add(child);
}
}
@Override
public Point computeSize(int wHint, int hHint, boolean changed) {
return layout.computeSize(this, wHint, hHint, changed);
}
@Override
public void dispose() {
dispose(true);
}
/**
* If the dispose request comes from the Composite via the topLevelListener,
* then do not dispose the Composite again - controls recieving the
* Composite's dispose event after this VPanel will be in danger of dealing
* with a disposed control before they are ready.
* @param disposeComposite
*/
private void dispose(boolean disposeComposite) {
if(isTopLevel) {
if(composite != null && !composite.isDisposed()) {
composite.removeListener(SWT.Dispose, topLevelListener);
composite.removeListener(SWT.FocusIn, topLevelListener);
composite.removeListener(SWT.Paint, topLevelListener);
}
}
for(VControl child : children.toArray(new VControl[children.size()])) {
child.dispose();
}
super.dispose();
if(isTopLevel && disposeComposite) {
if(composite != null && !composite.isDisposed()) {
composite.dispose();
}
}
}
public int getBorderWidth() {
if(isTopLevel) {
return composite.getBorderWidth();
} else {
return 1;
}
}
public VControl[] getChildren() {
return children.toArray(new VControl[children.size()]);
}
public VControl getControl(int x, int y) {
return getControl(x, y, false);
}
public VControl getControl(int x, int y, boolean includePanels) {
if(bounds.contains(x, y)) {
for(ListIterator<VControl> iter = children.listIterator(children.size()); iter.hasPrevious(); ) {
VControl child = iter.previous();
if(child.getVisible() && child.getBounds().contains(x, y)) {
if(includePanels && child instanceof VPanel) {
return ((VPanel) child).getControl(x, y, true);
} else {
return child;
}
}
}
return this;
}
return null;
}
public VLayout getLayout() {
return layout;
}
@SuppressWarnings("unchecked")
public <T extends VLayout> T getLayout(Class<T> clazz) {
return (T) layout;
}
@Override
public Type getType() {
return VControl.Type.Panel;
}
@Override
public Composite getWidget() {
if(widget != null) {
return widget;
}
if(parent != null) {
return parent.getWidget();
}
return composite;
}
public void layout() {
layout(true);
}
public void layout(boolean changed) {
layout.layout(this, changed);
redraw();
}
void move(VControl above, VControl below) {
if(above == null) {
children.remove(below);
children.add(below);
} else if(below == null) {
children.remove(above);
children.add(0, above);
} else {
int ix = children.indexOf(below);
children.remove(above);
children.add(ix, above);
}
}
@Override
protected boolean redrawOnActivate() {
return false;
}
@Override
protected boolean redrawOnDeactivate() {
return false;
}
void removeChild(VControl child) {
children.remove(child);
}
void removeVChild(VControl vchild) {
children.remove(vchild);
}
public void setActivatable(boolean activatable) {
super.setActivatable(activatable);
for(VControl child : children) {
child.setActivatable(activatable);
}
}
@Override
public void setBounds(int x, int y, int width, int height) {
super.setBounds(x, y, width, height);
layout();
}
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
for(VControl child : children) {
child.setEnabled(enabled);
}
}
@Override
protected boolean setFocus(boolean focus) {
if(focus) {
for(VControl child : children) {
if(VTracker.instance().setFocusControl(child)) {
return true;
}
}
return false;
} else {
for(VControl child : children) {
child.setFocus(false);
}
return true;
}
}
public void setLayout(VLayout layout) {
this.layout = layout;
}
@Override
public void setLayoutData(GridData data) {
if(isTopLevel) {
composite.setLayoutData(data);
} else {
super.setLayoutData(data);
}
}
@Override
public void setSize(Point size) {
super.setSize(size);
layout();
}
@Override
public void setVisibility(int visibility) {
for(VControl child : children) {
child.setVisibility(visibility);
}
super.setVisibility(visibility);
}
@Override
public void setVisible(boolean visible) {
super.setVisible(visible);
for(VControl child : children) {
if(child instanceof VNative) {
child.setVisible(visible);
}
}
}
public void setWidget(Composite widget) {
this.widget = widget;
this.widget.addListener(SWT.KeyDown, new Listener() {
public void handleEvent(Event event) {
}
});
// this.widget.addListener(SWT.FocusIn, new Listener() {
// public void handleEvent(Event event) {
// VPanel.this.getWidget().setFocus();
// }
// });
}
public void sort(Comparator<VControl> comparator) {
Collections.sort(children, comparator);
}
}