| /******************************************************************************* |
| * Copyright (c) 2000, 2005 IBM Corporation 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: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.ui.forms.widgets; |
| |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.custom.ScrolledComposite; |
| import org.eclipse.swt.graphics.Color; |
| import org.eclipse.swt.graphics.Font; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.graphics.Rectangle; |
| 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.ScrollBar; |
| import org.eclipse.ui.internal.forms.widgets.FormUtil; |
| |
| /** |
| * This class is used to provide common scrolling services to a number of |
| * controls in the toolkit. Classes that extend it are not required to implement |
| * any method. |
| * |
| * @since 3.0 |
| */ |
| public abstract class SharedScrolledComposite extends ScrolledComposite { |
| private static final int H_SCROLL_INCREMENT = 5; |
| |
| private static final int V_SCROLL_INCREMENT = 64; |
| |
| private boolean ignoreLayouts = true; |
| |
| private boolean ignoreResizes = false; |
| |
| private boolean expandHorizontal = false; |
| |
| private boolean expandVertical = false; |
| |
| private SizeCache contentCache = new SizeCache(); |
| |
| private boolean reflowPending = false; |
| |
| private boolean delayedReflow = true; |
| |
| /** |
| * Creates the new instance. |
| * |
| * @param parent |
| * the parent composite |
| * @param style |
| * the style to use |
| */ |
| public SharedScrolledComposite(Composite parent, int style) { |
| super(parent, style); |
| addListener(SWT.Resize, new Listener() { |
| public void handleEvent(Event e) { |
| if (!ignoreResizes) { |
| scheduleReflow(false); |
| } |
| } |
| }); |
| initializeScrollBars(); |
| } |
| |
| /** |
| * Sets the foreground of the control and its content. |
| * |
| * @param fg |
| * the new foreground color |
| */ |
| public void setForeground(Color fg) { |
| super.setForeground(fg); |
| if (getContent() != null) |
| getContent().setForeground(fg); |
| } |
| |
| /** |
| * Sets the background of the control and its content. |
| * |
| * @param bg |
| * the new background color |
| */ |
| public void setBackground(Color bg) { |
| super.setBackground(bg); |
| if (getContent() != null) |
| getContent().setBackground(bg); |
| } |
| |
| /** |
| * Sets the font of the form. This font will be used to render the title |
| * text. It will not affect the body. |
| */ |
| public void setFont(Font font) { |
| super.setFont(font); |
| if (getContent() != null) |
| getContent().setFont(font); |
| } |
| |
| /** |
| * Overrides 'super' to pass the proper colors and font |
| */ |
| public void setContent(Control content) { |
| super.setContent(content); |
| if (content != null) { |
| content.setForeground(getForeground()); |
| content.setBackground(getBackground()); |
| content.setFont(getFont()); |
| } |
| } |
| |
| /** |
| * If content is set, transfers focus to the content. |
| */ |
| public boolean setFocus() { |
| boolean result; |
| FormUtil.setFocusScrollingEnabled(this, false); |
| if (getContent() != null) |
| result = getContent().setFocus(); |
| else |
| result = super.setFocus(); |
| FormUtil.setFocusScrollingEnabled(this, true); |
| return result; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.swt.widgets.Composite#layout(boolean) |
| */ |
| public void layout(boolean changed) { |
| if (ignoreLayouts) { |
| return; |
| } |
| |
| ignoreLayouts = true; |
| ignoreResizes = true; |
| super.layout(changed); |
| ignoreResizes = false; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.swt.custom.ScrolledComposite#setExpandHorizontal(boolean) |
| */ |
| public void setExpandHorizontal(boolean expand) { |
| expandHorizontal = expand; |
| super.setExpandHorizontal(expand); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.swt.custom.ScrolledComposite#setExpandVertical(boolean) |
| */ |
| public void setExpandVertical(boolean expand) { |
| expandVertical = expand; |
| super.setExpandVertical(expand); |
| } |
| |
| /** |
| * Recomputes the body layout and the scroll bars. The method should be used |
| * when changes somewhere in the form body invalidate the current layout |
| * and/or scroll bars. |
| * |
| * @param flushCache |
| * if <code>true</code>, drop the cached data |
| */ |
| public void reflow(boolean flushCache) { |
| Composite c = (Composite) getContent(); |
| Rectangle clientArea = getClientArea(); |
| if (c == null) |
| return; |
| |
| contentCache.setControl(c); |
| if (flushCache) { |
| contentCache.flush(); |
| } |
| setRedraw(false); |
| Point newSize = contentCache.computeSize(FormUtil.getWidthHint( |
| clientArea.width, c), FormUtil.getHeightHint(clientArea.height, |
| c)); |
| |
| // Point currentSize = c.getSize(); |
| if (!(expandHorizontal && expandVertical)) { |
| c.setSize(newSize); |
| } |
| |
| setMinSize(newSize); |
| FormUtil.updatePageIncrement(this); |
| |
| ignoreLayouts = false; |
| layout(flushCache); |
| ignoreLayouts = true; |
| |
| contentCache.layoutIfNecessary(); |
| setRedraw(true); |
| } |
| |
| private void updateSizeWhilePending() { |
| Control c = getContent(); |
| Rectangle area = getClientArea(); |
| setMinSize(area.width, c.getSize().y); |
| } |
| |
| private void scheduleReflow(final boolean flushCache) { |
| if (delayedReflow) { |
| if (reflowPending) { |
| updateSizeWhilePending(); |
| return; |
| } |
| getDisplay().asyncExec(new Runnable() { |
| public void run() { |
| if (!isDisposed()) |
| reflow(flushCache); |
| reflowPending = false; |
| } |
| }); |
| reflowPending = true; |
| } else |
| reflow(flushCache); |
| } |
| |
| private void initializeScrollBars() { |
| ScrollBar hbar = getHorizontalBar(); |
| if (hbar != null) { |
| hbar.setIncrement(H_SCROLL_INCREMENT); |
| } |
| ScrollBar vbar = getVerticalBar(); |
| if (vbar != null) { |
| vbar.setIncrement(V_SCROLL_INCREMENT); |
| } |
| FormUtil.updatePageIncrement(this); |
| } |
| |
| /** |
| * Tests if the control uses delayed reflow. |
| * @return <code>true</code> if reflow requests will |
| * be delayed, <code>false</code> otherwise. |
| */ |
| public boolean isDelayedReflow() { |
| return delayedReflow; |
| } |
| |
| /** |
| * Sets the delayed reflow feature. When used, |
| * it will schedule a reflow on resize requests |
| * and reject subsequent reflows until the |
| * scheduled one is performed. This improves |
| * performance by |
| * @param delayedReflow |
| * The delayedReflow to set. |
| */ |
| public void setDelayedReflow(boolean delayedReflow) { |
| this.delayedReflow = delayedReflow; |
| } |
| } |