diff options
| author | Stephan Wahlbrink | 2018-09-13 17:51:36 +0000 |
|---|---|---|
| committer | Stephan Wahlbrink | 2021-08-23 20:41:04 +0000 |
| commit | c13eae0702030a7701770df5049d6ba2f43e680c (patch) | |
| tree | d8891d5e922172834d57fa1890d3e27ac0c54bc7 | |
| parent | 4cbc67134557a5a9fa5dc4c88c009a0c4ff77a90 (diff) | |
| download | org.eclipse.statet-r-c13eae0702030a7701770df5049d6ba2f43e680c.tar.gz org.eclipse.statet-r-c13eae0702030a7701770df5049d6ba2f43e680c.tar.xz org.eclipse.statet-r-c13eae0702030a7701770df5049d6ba2f43e680c.zip | |
Bug 575578: [R-DataEditor] Make use of ExpandableComposite added in
ecommons
Change-Id: I8bd2fa6e4bf755ecd6902974e730364dd42dca86
5 files changed, 9 insertions, 1457 deletions
diff --git a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/datafilterview/ExpandableRowComposite.java b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/datafilterview/ExpandableRowComposite.java deleted file mode 100644 index 677b7cbb..00000000 --- a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/datafilterview/ExpandableRowComposite.java +++ /dev/null @@ -1,1321 +0,0 @@ -/*=============================================================================# - # Copyright (c) 2000, 2021 IBM Corporation and others. - # - # This program and the accompanying materials are made available under the - # terms of the Eclipse Public License 2.0 which is available at - # https://www.eclipse.org/legal/epl-2.0. - # - # SPDX-License-Identifier: EPL-2.0 - # - # Contributors: - # IBM Corporation - org.eclipse.ui.forms: initial API and implementation - # Kai Nacke - org.eclipse.ui.forms: Bug 202382 - # Bryan Hunt - org.eclipse.ui.forms: Bug 245457 - # Didier Villevalois - org.eclipse.ui.forms: Bug 178534 - # Alena Laskavaia - org.eclipse.ui.forms: Bug 481604 - # Ralf Petter <ralf.petter@gmail.com> - org.eclipse.ui.forms: Bug 183675 - # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation - #=============================================================================*/ - -// org.eclipse.ui.forms.widgets.ExpandableComposite -// a2318aea7aeb731a6b1cadf0e85dd1e1287f4dd1 -// removed textClient -// without changed layout for wrapping controls (2016-2017) - -package org.eclipse.statet.internal.r.ui.datafilterview; - -import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert; - -import org.eclipse.core.runtime.Assert; -import org.eclipse.core.runtime.Platform; -import org.eclipse.jface.action.LegacyActionTools; -import org.eclipse.osgi.service.environment.Constants; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.FocusEvent; -import org.eclipse.swt.events.FocusListener; -import org.eclipse.swt.events.KeyAdapter; -import org.eclipse.swt.events.KeyEvent; -import org.eclipse.swt.events.PaintEvent; -import org.eclipse.swt.events.TraverseEvent; -import org.eclipse.swt.events.TraverseListener; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.Font; -import org.eclipse.swt.graphics.FontMetrics; -import org.eclipse.swt.graphics.GC; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.widgets.Canvas; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Layout; -import org.eclipse.swt.widgets.Listener; -import org.eclipse.swt.widgets.Menu; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.ui.forms.events.ExpansionEvent; -import org.eclipse.ui.forms.events.HyperlinkAdapter; -import org.eclipse.ui.forms.events.HyperlinkEvent; -import org.eclipse.ui.forms.events.IExpansionListener; -import org.eclipse.ui.forms.widgets.FormToolkit; -import org.eclipse.ui.forms.widgets.Hyperlink; -import org.eclipse.ui.forms.widgets.ILayoutExtension; -import org.eclipse.ui.forms.widgets.Section; -import org.eclipse.ui.forms.widgets.SharedScrolledComposite; -import org.eclipse.ui.forms.widgets.SizeCache; -import org.eclipse.ui.forms.widgets.Twistie; - -import org.eclipse.statet.jcommons.collections.CopyOnWriteIdentityListSet; -import org.eclipse.statet.jcommons.collections.ImIdentityList; -import org.eclipse.statet.jcommons.lang.NonNullByDefault; -import org.eclipse.statet.jcommons.lang.Nullable; - - -/** - * This composite is capable of expanding or collapsing a single client that is - * its direct child. The composite renders an expansion toggle affordance - * (according to the chosen style), and a title that also acts as a hyperlink - * (can be selected and is traversable). The client is laid out below the title - * when expanded, or hidden when collapsed. - * <p> - * The widget can be instantiated as-is, or subclassed to modify some aspects of - * it. * - * <p> - * Since 3.1, left/right arrow keys can be used to control the expansion state. - * If several expandable composites are created in the same parent, up/down - * arrow keys can be used to traverse between them. Expandable text accepts - * mnemonics and mnemonic activation will toggle the expansion state. - * - * <p> - * While expandable composite recognize that different styles can be used to - * render the title bar, and even defines the constants for these styles - * (<code>TITLE_BAR</code> and <code>SHORT_TITLE_BAR</code>) the actual painting - * is done in the subclasses. - * - * @see Section - */ -@NonNullByDefault -public class ExpandableRowComposite extends Canvas { - - - private static class Toggle extends Twistie { - - public Toggle(final Composite parent, final int style) { - super(parent, style); - } - - public void setHover(final boolean on) { - this.hover= on; - } - - public boolean getHover() { - return this.hover; - } - - @Override - protected void paint(final PaintEvent e) { - // don't paint focus - final GC gc= e.gc; - final Rectangle clientArea= getClientArea(); - if (clientArea.width == 0 || clientArea.height == 0) { - return; - } - paintHyperlink(gc); - } - - } - - - /** - * If this style is used, a twistie will be used to render the expansion - * toggle. - */ - public static final int TWISTIE= 1 << 1; - - /** - * If this style is used, the title text will be rendered as a hyperlink - * that can individually accept focus. Otherwise, it will still act like a - * hyperlink, but only the toggle control will accept focus. - */ - public static final int FOCUS_TITLE= 1 << 3; - - /** - * If this style is used, the client origin will be vertically aligned with - * the title text. Otherwise, it will start at x= 0. - */ - public static final int CLIENT_INDENT= 1 << 4; - - /** - * If this style is used, computed size of the composite will take the - * client width into consideration only in the expanded state. Otherwise, - * client width will always be taken into account. - */ - public static final int COMPACT= 1 << 5; - - /** - * If this style is used, the control will be created in the expanded state. - * This state can later be changed programmatically or by the user if - * TWISTIE or TREE_NODE style is used. - */ - public static final int EXPANDED= 1 << 6; - - /** - * If this style is used, title bar decoration will be painted behind the - * text. - */ - public static final int TITLE_BAR= 1 << 8; - - /** - * If this style is used, a short version of the title bar decoration will - * be painted behind the text. This style is useful when a more discrete - * option is needed for the title bar. - * - * @since 3.1 - */ - public static final int SHORT_TITLE_BAR= 1 << 9; - - /** - * By default, text client is right-aligned. If this style is used, it will - * be positioned after the text control and vertically centered with it. - */ - public static final int LEFT_TEXT_CLIENT_ALIGNMENT= 1 << 13; - - /** - * By default, a focus box is painted around the title when it receives focus. - * If this style is used, the focus box will not be painted. This style does - * not apply when FOCUS_TITLE is used. - * @since 3.5 - */ - public static final int NO_TITLE_FOCUS_BOX= 1 << 14; - - public static final int IMAGE= 1 << 30; - - - /** - * The toggle widget used to expand the composite. - */ - protected @Nullable Toggle toggle; - - /** - * The text label for the title. - */ - protected @Nullable Control textLabel; - - private static final int IGAP= 4; - private static final int IVGAP= 3; - - private static final Point NULL_SIZE= new Point(0, 0); - - private static final int VSPACE= 3; - - private static final int SEPARATOR_HEIGHT= 2; - - private int expansionStyle= TWISTIE | FOCUS_TITLE | EXPANDED; - - private boolean expanded; - - private @Nullable Label imageLabel; - - private Control client; - - private final CopyOnWriteIdentityListSet<IExpansionListener> listeners= new CopyOnWriteIdentityListSet<>(); - - private @Nullable Color titleBarForeground; - - private final Rectangle titleHeaderRegion= new Rectangle(0, 0, 0, 0); - - - private class ExpandableLayout extends Layout implements ILayoutExtension { - - /** - * Width of the margin that will be added around the control (default is 0). - */ - private int marginWidth= 0; - - /** - * Height of the margin that will be added around the control (default is - * 0). - */ - private int marginHeight= 0; - - /** - * Horizontal margin around the inside of the title bar area when TITLE_BAR - * or SHORT_TITLE_BAR style is used. This variable is not used otherwise. - */ - private int titleBarTextMarginWidth= 6; - - /** - * Vertical spacing between the title area and the description control - * (default is 0). The description control is normally placed at the new - * line as defined in the font used to render it. This value will be added - * to it. - */ - public int descriptionVerticalSpacing= 0; - - /** - * Vertical spacing between the title area and the composite client control - * (default is 3). - */ - public int clientVerticalSpacing= 3; - - - private final SizeCache toggleCache= new SizeCache(); - - private final SizeCache textClientCache= new SizeCache(); - - private final SizeCache textLabelCache= new SizeCache(); - - private final SizeCache descriptionCache= new SizeCache(); - - private final SizeCache clientCache= new SizeCache(); - - - private void initCache(final boolean shouldFlush) { - this.toggleCache.setControl(ExpandableRowComposite.this.toggle); - this.textLabelCache.setControl(ExpandableRowComposite.this.textLabel); - this.descriptionCache.setControl(getDescriptionControl()); - this.clientCache.setControl(ExpandableRowComposite.this.client); - - if (shouldFlush) { - this.toggleCache.flush(); - this.textClientCache.flush(); - this.textLabelCache.flush(); - this.descriptionCache.flush(); - this.clientCache.flush(); - } - } - - @Override - protected void layout(final Composite parent, final boolean changed) { - initCache(changed); - - final var toggle= ExpandableRowComposite.this.toggle; - final var imageLabel= ExpandableRowComposite.this.imageLabel; - final var textLabel= ExpandableRowComposite.this.textLabel; - - final Rectangle clientArea= parent.getClientArea(); - int thmargin= 0; - int tvmargin= 0; - - if (hasTitleBar()) { - thmargin= this.titleBarTextMarginWidth; - tvmargin= IVGAP; - } - int x= this.marginWidth + thmargin; - int y= this.marginHeight + tvmargin; - Point toggleSize= NULL_SIZE; - if (toggle != null) { - toggleSize= this.toggleCache.computeSize(SWT.DEFAULT, SWT.DEFAULT); - } - Point imageSize= NULL_SIZE; - if (imageLabel != null) { - imageSize= imageLabel.computeSize(16, 16); - } - int toggleWidth= clientArea.width - this.marginWidth - this.marginWidth - thmargin - thmargin; - if (toggleSize.x > 0) { - toggleWidth-= toggleSize.x + IGAP; - } - if (imageSize.x > 0) { - toggleWidth-= imageSize.x; - } - - Point size= NULL_SIZE; - if (textLabel != null) { - size= this.textLabelCache.computeSize(toggleWidth, SWT.DEFAULT); - - if (textLabel instanceof Label) { - final Point defSize= this.textLabelCache.computeSize(SWT.DEFAULT, - SWT.DEFAULT); - if (defSize.y == size.y) { - // One line - pick the smaller of the two widths - size.x= Math.min(defSize.x, size.x); - } - } - } - int theaderHeight; - { final GC gc= new GC(ExpandableRowComposite.this); - gc.setFont(getFont()); - final FontMetrics fm= gc.getFontMetrics(); - theaderHeight= fm.getHeight(); - gc.dispose(); - - if (imageSize.y > theaderHeight) { - theaderHeight= imageSize.y; - } - } - if (toggle != null) { - int ty= theaderHeight / 2 - toggleSize.y / 2 + 1; - ty= Math.max(ty, 0); - ty+= this.marginHeight + tvmargin; - toggle.setLocation(x, ty); - toggle.setSize(toggleSize); - x+= toggleSize.x + IGAP; - } - if (imageLabel != null) { - final int iy= theaderHeight / 2 - imageSize.y / 2; - imageLabel.setBounds(x, iy, imageSize.x, imageSize.y); - } - if (textLabel != null) { - int ty= theaderHeight / 2 - size.y / 2; - int tx= x; - if (imageLabel != null) { - tx+= imageSize.x + IGAP; - } - if (Constants.WS_GTK.equals(Platform.getWS())) { - size.x+= 1; // See Bug 342610 - } - - this.textLabelCache.setBounds(tx, ty, size.x, size.y); - } - int tbarHeight= theaderHeight; - if (size.y > tbarHeight) { - tbarHeight= size.y; - } - y+= tbarHeight; - if (hasTitleBar()) { - y+= tvmargin; - } - final Control separatorControl= getSeparatorControl(); - if (separatorControl != null) { - y+= VSPACE; - separatorControl.setBounds(this.marginWidth, y, - clientArea.width - this.marginWidth - this.marginWidth, - SEPARATOR_HEIGHT); - y+= SEPARATOR_HEIGHT; - } - if (ExpandableRowComposite.this.expanded - && ExpandableRowComposite.this.client != null) { - int areaWidth= clientArea.width - this.marginWidth - thmargin; - int cx= this.marginWidth + thmargin; - if ((ExpandableRowComposite.this.expansionStyle & CLIENT_INDENT) != 0) { - cx= x; - } - areaWidth-= cx; - if (getDescriptionControl() != null) { - if (ExpandableRowComposite.this.expanded) { - y+= VSPACE; - } - final Point dsize= this.descriptionCache.computeSize(areaWidth, SWT.DEFAULT); - y+= this.descriptionVerticalSpacing; - this.descriptionCache.setBounds(cx, y, areaWidth, dsize.y); - y+= dsize.y + this.clientVerticalSpacing; - } - y+= this.clientVerticalSpacing; - final int cwidth= areaWidth; - final int cheight= clientArea.height - this.marginHeight - - this.marginHeight - y; - this.clientCache.setBounds(cx, y, cwidth, cheight); - } - - ExpandableRowComposite.this.titleHeaderRegion.x= this.marginWidth; - ExpandableRowComposite.this.titleHeaderRegion.y= this.marginHeight; - ExpandableRowComposite.this.titleHeaderRegion.width= clientArea.width - this.marginWidth - this.marginWidth; - ExpandableRowComposite.this.titleHeaderRegion.height= theaderHeight; - } - - @Override - protected Point computeSize(final Composite parent, final int wHint, final int hHint, - final boolean changed) { - initCache(changed); - - final var toggle= ExpandableRowComposite.this.toggle; - final var imageLabel= ExpandableRowComposite.this.imageLabel; - final var textLabel= ExpandableRowComposite.this.textLabel; - - int width= 0, height= 0; - Point toggleSize= NULL_SIZE; - int toggleWidth= 0; - if (toggle != null) { - toggleSize= this.toggleCache.computeSize(SWT.DEFAULT, SWT.DEFAULT); - toggleWidth= toggleSize.x + IGAP; - } - int thmargin= 0; - int tvmargin= 0; - - Point imageSize= NULL_SIZE; - if (imageLabel != null) { - imageSize= imageLabel.computeSize(16, 16); - } - - if (hasTitleBar()) { - thmargin= this.titleBarTextMarginWidth; - tvmargin= IVGAP; - } - int innerwHint= wHint; - if (innerwHint != SWT.DEFAULT) { - innerwHint-= toggleWidth + this.marginWidth + this.marginWidth + thmargin + thmargin; - if (imageSize.x > 0) { - innerwHint-= imageSize.x + IGAP; - } - } - - int innertHint= innerwHint; - - Point size= NULL_SIZE; - if (textLabel != null) { - size= this.textLabelCache.computeSize(innertHint, SWT.DEFAULT); - - if (textLabel instanceof Label) { - final Point defSize= this.textLabelCache.computeSize(SWT.DEFAULT, SWT.DEFAULT); - if (defSize.y == size.y) { - // One line - pick the smaller of the two widths - size.x= Math.min(defSize.x, size.x); - } - } - } - - if (toggleWidth > 0) { - width+= toggleWidth; - } - if (imageSize.x > 0) { - width+= imageSize.x + IGAP; - } - if (size.x > 0) { - width+= size.x; - } - if (toggleSize.y > height) { - height= toggleSize.y; - } - if (imageSize.y > height) { - height= imageSize.y; - } - if (size.y > height) { - height= size.y; - } - final Control separatorControl= getSeparatorControl(); - if (separatorControl != null) { - height+= VSPACE + SEPARATOR_HEIGHT; - } - - if (wHint < width && size.x > 50) { - width-= size.x - 50; - } - - // if (hasTitleBar()) - // height+= VSPACE; - if ((ExpandableRowComposite.this.expanded || (ExpandableRowComposite.this.expansionStyle & COMPACT) == 0) - && ExpandableRowComposite.this.client != null) { - int cwHint= wHint; - int clientIndent= 0; - if ((ExpandableRowComposite.this.expansionStyle & CLIENT_INDENT) != 0) { - clientIndent= toggleWidth; - } - - if (cwHint != SWT.DEFAULT) { - cwHint-= this.marginWidth + this.marginWidth + thmargin + thmargin; - } - final Point csize= this.clientCache.computeSize(cwHint, SWT.DEFAULT); - if (getDescriptionControl() != null) { - int dwHint= cwHint; - if (dwHint == SWT.DEFAULT) { - dwHint= csize.x; - if ((ExpandableRowComposite.this.expansionStyle & CLIENT_INDENT) != 0) { - dwHint-= toggleWidth; - } - } - final Point dsize= this.descriptionCache.computeSize(dwHint, SWT.DEFAULT); - width= Math.max(width, dsize.x + clientIndent); - if (ExpandableRowComposite.this.expanded) { - if (separatorControl != null) { - height+= VSPACE; - } - height+= this.descriptionVerticalSpacing + dsize.y; - } - } - width= Math.max(width, csize.x + clientIndent); - if (ExpandableRowComposite.this.expanded) { - height+= this.clientVerticalSpacing; - height+= csize.y; - } - } - - final Point result= new Point(width + this.marginWidth + this.marginWidth - + thmargin + thmargin, height + this.marginHeight + this.marginHeight - + tvmargin + tvmargin); - return result; - } - - @Override - public int computeMinimumWidth(final Composite parent, final boolean changed) { - return computeSize(parent, 0, SWT.DEFAULT, changed).x; - } - - @Override - public int computeMaximumWidth(final Composite parent, final boolean changed) { - return computeSize(parent, SWT.DEFAULT, SWT.DEFAULT, changed).x; - } - - } - - - /** - * Creates an expandable composite using a TWISTIE toggle. - * - * @param parent - * the parent composite - * @param style - * SWT style bits - */ - public ExpandableRowComposite(final Composite parent, final int style) { - this(parent, style, TWISTIE); - } - - /** - * Creates the expandable composite in the provided parent. - * - * @param parent - * the parent - * @param style - * the control style (as expected by SWT subclass) - * @param expansionStyle - * the style of the expansion widget (TREE_NODE, TWISTIE, - * CLIENT_INDENT, COMPACT, FOCUS_TITLE, - * LEFT_TEXT_CLIENT_ALIGNMENT, NO_TITLE) - */ - public ExpandableRowComposite(final Composite parent, final int style, final int expansionStyle) { - super(parent, style); - this.expansionStyle= expansionStyle; - if ((expansionStyle & TITLE_BAR) != 0) { - setBackgroundMode(SWT.INHERIT_DEFAULT); - } - super.setLayout(new ExpandableLayout()); - if (hasTitleBar()) { - addPaintListener(this::onPaint); - } - - final Toggle toggle; - final Label imageLabel; - final Control textLabel; - if ((expansionStyle & TWISTIE) != 0) { - toggle= new Toggle(this, SWT.NULL); - } - else { - toggle= null; - this.expanded= true; - } - if ((expansionStyle & EXPANDED) != 0) { - this.expanded= true; - } - this.toggle= toggle; - if (toggle != null) { - toggle.setExpanded(this.expanded); - toggle.addHyperlinkListener(new HyperlinkAdapter() { - @Override - public void linkActivated(final HyperlinkEvent e) { - toggleState(); - } - }); - toggle.addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(final KeyEvent e) { - if (e.keyCode == SWT.ARROW_UP) { - verticalMove(false); - e.doit= false; - } - else if (e.keyCode == SWT.ARROW_DOWN) { - verticalMove(true); - e.doit= false; - } - } - }); - if ((getExpansionStyle() & FOCUS_TITLE) == 0) { - toggle.addFocusListener(new FocusListener() { - @Override - public void focusGained(final FocusEvent e) { - final var textLabel= ExpandableRowComposite.this.textLabel; - if (textLabel != null) { - textLabel.redraw(); - } - } - @Override - public void focusLost(final FocusEvent e) { - final var textLabel= ExpandableRowComposite.this.textLabel; - if (textLabel != null) { - textLabel.redraw(); - } - } - }); - } - } - if ((expansionStyle & IMAGE) != 0) { - imageLabel= new Label(this, SWT.NONE); - } - else { - imageLabel= null; - } - this.imageLabel= imageLabel; - if ((expansionStyle & FOCUS_TITLE) != 0) { - final Hyperlink link= new Hyperlink(this, SWT.NONE); - link.addHyperlinkListener(new HyperlinkAdapter() { - @Override - public void linkActivated(final HyperlinkEvent e) { - programmaticToggleState(); - } - }); - textLabel= link; - } - else { - final Label label= new Label(this, SWT.NONE); - if (!isFixedStyle()) { - final Listener listener= new Listener() { - @Override - public void handleEvent(final Event e) { - switch (e.type) { - case SWT.Paint: - if (ExpandableRowComposite.this.toggle != null - && (getExpansionStyle() & NO_TITLE_FOCUS_BOX) == 0) { - paintTitleFocus(e.gc); - } - break; - case SWT.Resize: - updateLabelTrim(); - break; - } - } - }; - label.addListener(SWT.Paint, listener); - label.addListener(SWT.Resize, listener); - } - textLabel= label; - } - this.textLabel= textLabel; - if (textLabel != null) { - textLabel.setMenu(getMenu()); - textLabel.addTraverseListener(new TraverseListener() { - @Override - public void keyTraversed(final TraverseEvent e) { - if (e.detail == SWT.TRAVERSE_MNEMONIC) { - // steal the mnemonic - if (!isVisible() || !isEnabled()) { - return; - } - if (e.character != 0 - && e.character == LegacyActionTools.extractMnemonic(getText())) { - e.doit= false; - if (!isFixedStyle()) { - programmaticToggleState(); - } - setFocus(); - } - } - } - }); - } - { // Complete Title header - final Listener listener= new Listener() { - @Override - public void handleEvent(final Event event) { - int x= event.x; - int y= event.y; - if (event.widget != ExpandableRowComposite.this) { - final Point p= ((Control)event.widget).getLocation(); - x+= p.x; - y+= p.y; - } - switch (event.type) { - case SWT.MouseDown: - if (ExpandableRowComposite.this.titleHeaderRegion.contains(x, y)) { - final var toggle= ExpandableRowComposite.this.toggle; - if (toggle != null) { - toggle.setFocus(); - } - } - break; - case SWT.MouseUp: - if (ExpandableRowComposite.this.titleHeaderRegion.contains(x, y) - && event.button == 1) { -// textLabel.setCursor(FormsResources.getBusyCursor()); - programmaticToggleState(); -// textLabel.setCursor(null); - } - break; - case SWT.MouseEnter: - case SWT.MouseMove: - case SWT.MouseExit: - if (ExpandableRowComposite.this.titleHeaderRegion.contains(x, y)) { - final var toggle= ExpandableRowComposite.this.toggle; - if (toggle != null && !toggle.getHover()) { - toggle.setHover(true); - toggle.redraw(); - } - } - else { - final var toggle= ExpandableRowComposite.this.toggle; - if (toggle != null && toggle.getHover()) { - toggle.setHover(false); - toggle.redraw(); - } - } - break; -// case SWT.Paint: -// if (toggle != null && (getExpansionStyle() & NO_TITLE_FOCUS_BOX) == 0) { -// paintTitleFocus(event.gc); -// } -// break; - } - } - }; - addListener(SWT.MouseDown, listener); - addListener(SWT.MouseUp, listener); - addListener(SWT.MouseEnter, listener); - addListener(SWT.MouseMove, listener); - addListener(SWT.MouseExit, listener); - if (imageLabel != null) { - imageLabel.addListener(SWT.MouseDown, listener); - imageLabel.addListener(SWT.MouseUp, listener); - imageLabel.addListener(SWT.MouseEnter, listener); - imageLabel.addListener(SWT.MouseExit, listener); - } - if (textLabel != null) { - textLabel.addListener(SWT.MouseDown, listener); - textLabel.addListener(SWT.MouseUp, listener); - textLabel.addListener(SWT.MouseEnter, listener); - textLabel.addListener(SWT.MouseExit, listener); - } - } - } - - - @Override - public boolean forceFocus() { - return false; - } - - /** - * Overrides 'super' to pass the menu to the text label. - * - * @param menu - * the menu from the parent to attach to this control. - */ - @Override - public void setMenu(final @Nullable Menu menu) { - final var toggle= this.toggle; - final var imageLabel= this.imageLabel; - final var textLabel= this.textLabel; - if (toggle != null) { - toggle.setMenu(menu); - } - if (imageLabel != null) { - imageLabel.setMenu(menu); - } - if (textLabel != null) { - textLabel.setMenu(menu); - } - - super.setMenu(menu); - } - - /** - * Prevents assignment of the layout manager - expandable composite uses its - * own layout. - */ - @Override - public final void setLayout(final @Nullable Layout layout) { - } - - /** - * Sets the background of all the custom controls in the expandable. - */ - @Override - public void setBackground(final @Nullable Color color) { - super.setBackground(color); - - if ((getExpansionStyle() & TITLE_BAR) == 0) { - final var toggle= this.toggle; - final var imageLabel= this.imageLabel; - final var textLabel= this.textLabel; - if (toggle != null) { - toggle.setBackground(color); - toggle.setHoverDecorationColor(computeActiveToggleColor()); - } - if (imageLabel != null) { - imageLabel.setBackground(color); - } - if (textLabel != null) { - textLabel.setBackground(color); - } - } - } - - protected Color computeActiveToggleColor() { - final Display display= getDisplay(); - final Color selection= display.getSystemColor(SWT.COLOR_LIST_SELECTION); - final Color background= getBackground(); - return new Color( - (63 + 3 * selection.getRed() + 2 * background.getRed()) / 6, - (63 + 3 * selection.getGreen() + 2 *background.getGreen()) / 6, - (63 + 3 * selection.getBlue() + 2 * background.getBlue()) / 6 ); - } - - /** - * Sets the foreground of all the custom controls in the expandable. - */ - @Override - public void setForeground(final @Nullable Color color) { - super.setForeground(color); - - final var toggle= this.toggle; - final var textLabel= this.textLabel; - - if (toggle != null) { - toggle.setForeground(color); - } - if (textLabel != null) { - textLabel.setForeground(color); - } - } - - /** - * Sets the color of the toggle control. - * - * @param color - * the color object - */ - public void setToggleColor(final @Nullable Color color) { - final var toggle= this.toggle; - if (toggle != null) { - toggle.setDecorationColor(color); - } - } - - /** - * Sets the active color of the toggle control (when the mouse enters the - * toggle area). - * - * @param color - * the active color object - */ - public void setActiveToggleColor(final @Nullable Color color) { - final var toggle= this.toggle; - if (toggle != null) { - toggle.setHoverDecorationColor(color); - } - } - - /** - * Sets the fonts of all the custom controls in the expandable. - */ - @Override - public void setFont(final @Nullable Font font) { - super.setFont(font); - - final var toggle= this.toggle; - final var textLabel= this.textLabel; - if (toggle != null) { - toggle.setFont(font); - } - if (textLabel != null) { - textLabel.setFont(font); - } - } - - @Override - public void setEnabled(final boolean enabled) { - final var toggle= this.toggle; - final var textLabel= this.textLabel; - if (toggle != null) { - toggle.setEnabled(enabled); - } - if (textLabel != null) { - textLabel.setEnabled(enabled); - } - - super.setEnabled(enabled); - } - - /** - * Sets the client of this expandable composite. The client must not be - * <samp>null </samp> and must be a direct child of this container. - * - * @param client - * the client that will be expanded or collapsed - */ - public void setClient(final Control client) { - Assert.isTrue(client != null && client.getParent() == this); - this.client= client; - } - - /** - * Returns the current expandable client. - * - * @return the client control - */ - public Control getClient() { - return this.client; - } - - public void setImage(final @Nullable Image image) { - final var imageLabel= this.imageLabel; - if (imageLabel != null) { - imageLabel.setImage(image); - } - } - - public @Nullable Image getImage() { - final var imageLabel= this.imageLabel; - if (imageLabel != null) { - return imageLabel.getImage(); - } - return null; - } - - /** - * Sets the title of the expandable composite. The title will act as a - * hyperlink and activating it will toggle the client between expanded and - * collapsed state. - * - * @param title - * the new title string - * @see #getText() - */ - public void setText(final String title) { - final var textLabel= this.textLabel; - if (textLabel instanceof Label) { - ((Label)textLabel).setText(title); - updateLabelTrim(); - } - else if (textLabel instanceof Hyperlink) { - ((Hyperlink)textLabel).setText(title); - } - else { - return; - } - layout(); - } - - /** - * Returns the title string. - * - * @return the title string - * @see #setText(String) - */ - public String getText() { - final var textLabel= this.textLabel; - if (textLabel instanceof Label) { - return ((Label)textLabel).getText(); - } - else if (textLabel instanceof Hyperlink) { - return ((Hyperlink)textLabel).getText(); - } - else { - return ""; //$NON-NLS-1$ - } - } - - @Override - public void setToolTipText(final @Nullable String string) { - super.setToolTipText(string); - - // Also set on label, otherwise it's just on the background without text. - final var toggle= this.toggle; - final var imageLabel= this.imageLabel; - final var textLabel= this.textLabel; - if (toggle != null) { - toggle.setToolTipText(string); - } - if (imageLabel != null) { - imageLabel.setToolTipText(string); - } - if (textLabel != null) { - textLabel.setToolTipText(string); - } - } - - /** - * Tests the expanded state of the composite. - * - * @return <samp>true </samp> if expanded, <samp>false </samp> if collapsed. - */ - public boolean isExpanded() { - return this.expanded; - } - - /** - * Returns the bitwise-ORed style bits for the expansion control. - * - * @return the bitwise-ORed style bits for the expansion control - */ - public int getExpansionStyle() { - return this.expansionStyle; - } - - /** - * Programmatically changes expanded state. - * - * @param expanded - * the new expanded state - */ - public void setExpanded(final boolean expanded) { - internalSetExpanded(expanded); - - final var toggle= this.toggle; - if (toggle != null) { - toggle.setExpanded(expanded); - } - } - - /** - * Performs the expansion state change for the expandable control. - * - * @param expanded - * the expansion state - */ - protected void internalSetExpanded(final boolean expanded) { - if (this.expanded != expanded) { - this.expanded= expanded; - - final var descriptionControl= getDescriptionControl(); - if (descriptionControl != null) { - descriptionControl.setVisible(expanded); - } - if (this.client != null) { - this.client.setVisible(expanded); - } - reflow(); - } - } - - /** - * Adds the listener that will be notified when the expansion state changes. - * - * @param listener - * the listener to add - */ - public void addExpansionListener(final IExpansionListener listener) { - this.listeners.add(listener); - } - - /** - * Removes the expansion listener. - * - * @param listener - * the listener to remove - */ - public void removeExpansionListener(final IExpansionListener listener) { - this.listeners.remove(listener); - } - - /** - * If TITLE_BAR or SHORT_TITLE_BAR style is used, title bar decoration will - * be painted behind the text in this method. The default implementation - * does nothing - subclasses are responsible for rendering the title area. - * - * @param e - * the paint event - */ - protected void onPaint(final PaintEvent e) { - } - - /** - * Returns description control that will be placed under the title if - * present. - * - * @return the description control or <samp>null </samp> if not used. - */ - protected @Nullable Control getDescriptionControl() { - return null; - } - - /** - * Returns the separator control that will be placed between the title and - * the description if present. - * - * @return the separator control or <samp>null </samp> if not used. - */ - protected @Nullable Control getSeparatorControl() { - return null; - } - - /** - * Computes the size of the expandable composite. - * - * @see org.eclipse.swt.widgets.Composite#computeSize - */ - @Override - public Point computeSize(final int wHint, final int hHint, final boolean changed) { - checkWidget(); - final Point size; - final var layout= (ExpandableLayout)getLayout(); - if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT) { - size= layout.computeSize(this, wHint, hHint, changed); - } else { - size= new Point(wHint, hHint); - } - final Rectangle trim= computeTrim(0, 0, size.x, size.y); - return new Point(trim.width, trim.height); - } - - /** - * Returns <samp>true </samp> if the composite is fixed i.e. cannot be - * expanded or collapsed. Fixed control will still contain the title, - * separator and description (if present) as well as the client, but will be - * in the permanent expanded state and the toggle affordance will not be - * shown. - * - * @return <samp>true </samp> if the control is fixed in the expanded state, - * <samp>false </samp> if it can be collapsed. - */ - protected boolean isFixedStyle() { - return ((this.expansionStyle & TWISTIE) == 0); - } - - /** - * Tests if this expandable composite renders a title bar around the text. - * - * @return <code>true</code> for <code>TITLE_BAR</code> or - * <code>SHORT_TITLE_BAR</code> styles, <code>false</code> - * otherwise. - */ - protected boolean hasTitleBar() { - return ((getExpansionStyle() & TITLE_BAR) != 0 - || (getExpansionStyle() & SHORT_TITLE_BAR) != 0 ); - } - - /** - * Sets the color of the title bar foreground when TITLE_BAR style is used. - * - * @param color - * the title bar foreground - */ - public void setTitleBarForeground(final @Nullable Color color) { - this.titleBarForeground= color; - - final var textLabel= this.textLabel; - if (textLabel != null) { - textLabel.setForeground(color); - } - } - - /** - * Returns the title bar foreground when TITLE_BAR style is used. - * - * @return the title bar foreground - */ - public @Nullable Color getTitleBarForeground() { - return this.titleBarForeground; - } - - // end of APIs - - private void toggleState() { - final boolean newState= !isExpanded(); - fireExpanding(newState, true); - internalSetExpanded(newState); - fireExpanding(newState, false); - if (newState) { - FormToolkit.ensureVisible(this); - } - } - - private void fireExpanding(final boolean state, final boolean before) { - final ImIdentityList<IExpansionListener> listenerList= this.listeners.toList(); - if (listenerList.isEmpty()) { - return; - } - final ExpansionEvent e= new ExpansionEvent(this, state); - for (final IExpansionListener listener : listenerList) { - if (before) { - listener.expansionStateChanging(e); - } - else { - listener.expansionStateChanged(e); - } - } - } - - private void verticalMove(final boolean down) { - final Composite parent= nonNullAssert(getParent()); - final Control[] children= parent.getChildren(); - for (int i= 0; i < children.length; i++) { - final Control child= children[i]; - if (child == this) { - final ExpandableRowComposite sibling= getSibling(children, i, down); - if (sibling != null && sibling.toggle != null) { - sibling.setFocus(); - } - break; - } - } - } - - private @Nullable ExpandableRowComposite getSibling(final Control[] children, final int index, - final boolean down) { - int loc= (down) ? index + 1 : index - 1; - while (loc >= 0 && loc < children.length) { - final Control c= children[loc]; - if (c instanceof ExpandableRowComposite && c.isVisible()) { - return (ExpandableRowComposite)c; - } - loc= (down) ? loc + 1 : loc - 1; - } - return null; - } - - private void programmaticToggleState() { - final var toggle= this.toggle; - if (toggle != null) { - toggle.setExpanded(!toggle.isExpanded()); - } - toggleState(); - } - - private void paintTitleFocus(final GC gc) { - final var toggle= this.toggle; - final var textLabel= this.textLabel; - if (textLabel != null) { - final Point size= textLabel.getSize(); - gc.setBackground(textLabel.getBackground()); - gc.setForeground(textLabel.getForeground()); - if (toggle != null && toggle.isFocusControl()) { - gc.drawFocus(0, 0, size.x, size.y); - } - } - } - - void reflow() { - Composite c= this; - while (c != null) { - c.setRedraw(false); - c= c.getParent(); - if (c instanceof SharedScrolledComposite || c instanceof Shell) { - break; - } - } - try { - c= this; - while (c != null) { - c.requestLayout(); - c= c.getParent(); - if (c instanceof SharedScrolledComposite) { - ((SharedScrolledComposite)c).reflow(true); - break; - } - if (c instanceof Shell) { - break; - } - } - } - finally { - c= this; - while (c != null) { - c.setRedraw(true); - c= c.getParent(); - if (c instanceof SharedScrolledComposite || c instanceof Shell) { - break; - } - } - } - } - - private void updateLabelTrim() { -// if (textLabel.computeSize(SWT.DEFAULT, SWT.DEFAULT).x > textLabel.getSize().x) { -// textLabel.setToolTipText(((Label)textLabel).getText()); -// } -// else { -// textLabel.setToolTipText(null); -// } - } - -} diff --git a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/datafilterview/RDataFilterPage.java b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/datafilterview/RDataFilterPage.java index e9d4d2ba..e37617f6 100644 --- a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/datafilterview/RDataFilterPage.java +++ b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/datafilterview/RDataFilterPage.java @@ -51,6 +51,7 @@ import org.eclipse.statet.jcommons.lang.Nullable; import org.eclipse.statet.ecommons.ui.SharedUIResources; import org.eclipse.statet.ecommons.ui.actions.HandlerContributionItem; import org.eclipse.statet.ecommons.ui.dialogs.DialogUtils; +import org.eclipse.statet.ecommons.ui.swt.expandable.ExpandableRowsList; import org.eclipse.statet.ecommons.ui.util.DNDUtils; import org.eclipse.statet.ecommons.ui.util.LayoutUtils; import org.eclipse.statet.ecommons.ui.util.UIAccess; @@ -167,7 +168,7 @@ public class RDataFilterPage extends Page implements FilterPage, IShowInTarget { private Composite composite; - private ScrolledPageComposite scrollComposite; + private ExpandableRowsList scrollComposite; private Text filterText; @@ -240,7 +241,7 @@ public class RDataFilterPage extends Page implements FilterPage, IShowInTarget { this.composite= new Composite(parent, SWT.NONE); this.composite.setLayout(LayoutUtils.newCompositeGrid(1)); - this.scrollComposite= new ScrolledPageComposite(this.composite, SWT.V_SCROLL); + this.scrollComposite= new ExpandableRowsList(this.composite, SWT.V_SCROLL); this.scrollComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); this.container= new VariableContainer(getSite(), this.scrollComposite); diff --git a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/datafilterview/ScrolledPageComposite.java b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/datafilterview/ScrolledPageComposite.java deleted file mode 100644 index fde1e916..00000000 --- a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/datafilterview/ScrolledPageComposite.java +++ /dev/null @@ -1,130 +0,0 @@ -/*=============================================================================# - # Copyright (c) 2012, 2021 Stephan Wahlbrink and others. - # - # This program and the accompanying materials are made available under the - # terms of the Eclipse Public License 2.0 which is available at - # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 - # which is available at https://www.apache.org/licenses/LICENSE-2.0. - # - # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 - # - # Contributors: - # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation - #=============================================================================*/ - -package org.eclipse.statet.internal.r.ui.datafilterview; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.forms.FormColors; -import org.eclipse.ui.forms.events.ExpansionAdapter; -import org.eclipse.ui.forms.events.ExpansionEvent; -import org.eclipse.ui.forms.events.IExpansionListener; -import org.eclipse.ui.forms.widgets.FormToolkit; -import org.eclipse.ui.forms.widgets.SharedScrolledComposite; - -import org.eclipse.statet.jcommons.lang.NonNullByDefault; -import org.eclipse.statet.jcommons.lang.Nullable; - - -@NonNullByDefault -public class ScrolledPageComposite extends SharedScrolledComposite { - - - private static @Nullable FormToolkit gDialogsFormToolkit; - - private static FormToolkit getViewFormToolkit() { - FormToolkit toolkit= gDialogsFormToolkit; - if (toolkit == null) { - final FormColors colors= new FormColors(Display.getCurrent()); - toolkit= new FormToolkit(colors); - gDialogsFormToolkit= toolkit; - } - return toolkit; - } - - - private final FormToolkit toolkit; - - private @Nullable IExpansionListener expansionListener; - - private int delayReflowCounter; - - - public ScrolledPageComposite(final Composite parent) { - this(parent, SWT.H_SCROLL | SWT.V_SCROLL); - } - - public ScrolledPageComposite(final Composite parent, final int style) { - super(parent, style); - - if ((style & SWT.H_SCROLL) == 0) { - setExpandHorizontal(true); - } - - setFont(parent.getFont()); - - this.toolkit= getViewFormToolkit(); - - setExpandHorizontal(true); - setExpandVertical(true); - - final Composite body= new Composite(this, SWT.NONE); - setContent(body); - - setFont(parent.getFont()); - setBackground(this.toolkit.getColors().getBackground()); - } - - - @Override - @SuppressWarnings("null") - public Composite getContent() { - return (Composite)super.getContent(); - } - - @Override - public void setDelayedReflow(final boolean delayedReflow) { - if (delayedReflow) { - this.delayReflowCounter++; - } - else { - this.delayReflowCounter--; - } - super.setDelayedReflow(this.delayReflowCounter > 0); - } - - public void adaptChild(final Control childControl) { - if (childControl instanceof ExpandableRowComposite) { - this.toolkit.adapt(childControl, true, false); - var expansionListener= this.expansionListener; - if (expansionListener == null) { - expansionListener= new ExpansionAdapter() { - @Override - public void expansionStateChanged(final ExpansionEvent e) { - expandedStateChanged(); - } - }; - this.expansionListener= expansionListener; - } - ((ExpandableRowComposite)childControl).addExpansionListener(expansionListener); - } - else if (childControl instanceof Composite) { - final var composite= (Composite)childControl; - this.toolkit.adapt(composite, false, false); - for (final Control child : composite.getChildren()) { - this.toolkit.adapt(child, true, false); - } - } - else { - this.toolkit.adapt(childControl, true, false); - } - } - - protected void expandedStateChanged() { - reflow(true); - } - -} diff --git a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/datafilterview/VariableComposite.java b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/datafilterview/VariableComposite.java index 2d0cc823..da59a27b 100644 --- a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/datafilterview/VariableComposite.java +++ b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/datafilterview/VariableComposite.java @@ -38,6 +38,7 @@ import org.eclipse.statet.jcommons.lang.ObjectUtils.ToStringBuilder; import org.eclipse.statet.ecommons.ui.SharedUIResources; import org.eclipse.statet.ecommons.ui.actions.SimpleContributionItem; +import org.eclipse.statet.ecommons.ui.swt.expandable.ExpandableComposite; import org.eclipse.statet.internal.r.ui.RUIPlugin; import org.eclipse.statet.internal.r.ui.datafilter.FilterSet; @@ -47,7 +48,7 @@ import org.eclipse.statet.r.ui.dataeditor.RDataTableColumn; @NonNullByDefault -public class VariableComposite extends ExpandableRowComposite { +public class VariableComposite extends ExpandableComposite { private final VariableContainer container; diff --git a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/datafilterview/VariableContainer.java b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/datafilterview/VariableContainer.java index b5e30413..f6a9adf3 100644 --- a/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/datafilterview/VariableContainer.java +++ b/r/org.eclipse.statet.r.ui/src/org/eclipse/statet/internal/r/ui/datafilterview/VariableContainer.java @@ -30,6 +30,7 @@ import org.eclipse.statet.jcommons.lang.NonNull; import org.eclipse.statet.jcommons.lang.NonNullByDefault; import org.eclipse.statet.jcommons.lang.Nullable; +import org.eclipse.statet.ecommons.ui.swt.expandable.ExpandableRowsList; import org.eclipse.statet.ecommons.ui.util.LayoutUtils; import org.eclipse.statet.internal.r.ui.dataeditor.RDataLabelProvider; @@ -52,7 +53,7 @@ public class VariableContainer { private final IServiceLocator serviceLocator; - private final ScrolledPageComposite composite; + private final ExpandableRowsList composite; private final List<VariableComposite> variables; @@ -63,7 +64,7 @@ public class VariableContainer { private @Nullable RDataTableContentDescription description; - public VariableContainer(final IServiceLocator serviceLocator, final ScrolledPageComposite composite) { + public VariableContainer(final IServiceLocator serviceLocator, final ExpandableRowsList composite) { this.serviceLocator= serviceLocator; this.composite= composite; this.variables= new ArrayList<>(); @@ -224,7 +225,7 @@ public class VariableContainer { return this.serviceLocator; } - public ScrolledPageComposite getComposite() { + public ExpandableRowsList getComposite() { return this.composite; } |
