| /******************************************************************************* |
| * Copyright (c) 2018 Red Hat and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Red Hat - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.swt.tests.gtk.snippets; |
| |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.graphics.GC; |
| import org.eclipse.swt.graphics.Path; |
| import org.eclipse.swt.graphics.PathData; |
| import org.eclipse.swt.graphics.Rectangle; |
| import org.eclipse.swt.graphics.Region; |
| import org.eclipse.swt.layout.FillLayout; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.Shell; |
| |
| public class Bug475784_TransparentComposite extends Shell |
| { |
| public static int RADIUS_OF_ROUND_EDGES = 30; |
| |
| /** |
| * Launch the application. |
| * @param args |
| */ |
| public static void main(String args[]) |
| { |
| try |
| { |
| Display display = Display.getDefault(); |
| Bug475784_TransparentComposite shell = new Bug475784_TransparentComposite(display); |
| shell.open(); |
| shell.layout(); |
| while (!shell.isDisposed()) |
| { |
| if (!display.readAndDispatch()) |
| { |
| display.sleep(); |
| } |
| } |
| } |
| catch (Exception e) |
| { |
| e.printStackTrace(); |
| } |
| } |
| |
| /** |
| * Create the shell. |
| * @param display |
| */ |
| public Bug475784_TransparentComposite(final Display display) |
| { |
| super(display, SWT.SHELL_TRIM); |
| setLayout(new GridLayout(1, false)); |
| final Composite composite = new Composite(this, SWT.NONE); |
| composite.setBackground(display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND)); |
| composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); |
| composite.setLayout(new GridLayout(1, false)); |
| //overlay composite |
| final Composite overlay = new Composite(composite, SWT.NO_BACKGROUND | SWT.NO_FOCUS); |
| overlay.setLayout(new FillLayout()); |
| overlay.setVisible(false); |
| //label |
| Label textLabel = new Label(composite, SWT.NONE); |
| textLabel.setText("Hello World!\nHello World!"); |
| Button btnCheckButton = new Button(composite, SWT.CHECK); |
| btnCheckButton.setText("Check Button"); |
| Button btnRadioButton = new Button(composite, SWT.RADIO); |
| btnRadioButton.setText("Radio Button"); |
| //Composite for drawings |
| Composite compDraws = new Composite(composite, SWT.NONE); |
| compDraws.addPaintListener(e -> { |
| e.gc.setBackground(display.getSystemColor(SWT.COLOR_RED)); |
| e.gc.fillArc(0, 0, 50, 50, 0, 360); |
| }); |
| //exclude overlay composite |
| GridData gData = new GridData(); |
| gData.exclude = true; |
| overlay.setLayoutData(gData); |
| //set region |
| Region reg = new Region(); |
| getRegionForRoundRectangle(reg, 0, 0, 200, 200, RADIUS_OF_ROUND_EDGES); |
| overlay.setRegion(reg); |
| reg.dispose(); |
| //toggle overlay button |
| final Button btnNewButton = new Button(composite, SWT.NONE); |
| btnNewButton.setLayoutData(new GridData(SWT.LEFT, SWT.BOTTOM, false, true, 1, 1)); |
| btnNewButton.setText("Toggle overlay"); |
| GridData gdDataButton = new GridData(GridData.VERTICAL_ALIGN_END); |
| gdDataButton.horizontalAlignment = SWT.LEFT; |
| gdDataButton.verticalAlignment = SWT.BOTTOM; |
| gdDataButton.grabExcessVerticalSpace = true; |
| btnNewButton.setLayoutData(gdDataButton); |
| btnNewButton.addSelectionListener(new SelectionAdapter() |
| { |
| @Override |
| public void widgetSelected(SelectionEvent e) |
| { |
| int width = composite.getSize().x; |
| int height = composite.getSize().y - btnNewButton.getSize().y - 10; |
| overlay.setSize(width, height); |
| overlay.setVisible(!overlay.isVisible()); |
| } |
| }); |
| overlay.moveAbove(null); |
| overlay.addPaintListener(e -> { |
| e.gc.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_YELLOW)); |
| e.gc.setAlpha(150); |
| e.gc.fillRectangle(new Rectangle(0, 0, overlay.getSize().x, overlay.getSize().y)); |
| }); |
| createContents(); |
| } |
| |
| /** |
| * Create contents of the shell. |
| */ |
| protected void createContents() |
| { |
| setText("SWT Application"); |
| setSize(450, 300); |
| } |
| |
| @Override |
| protected void checkSubclass() |
| { |
| // Disable the check that prevents subclassing of SWT components |
| } |
| |
| public static void getCircleRegion(Region region, int r, int offsetX, int offsetY) |
| { |
| int[] polygon = new int[8 * r + 4]; |
| // x^2 + y^2 = r^2 |
| for (int i = 0; i < 2 * r + 1; i++) |
| { |
| int x = i - r; |
| int y = (int) Math.sqrt(r * r - x * x); |
| polygon[2 * i] = offsetX + x; |
| polygon[2 * i + 1] = offsetY + y; |
| polygon[8 * r - 2 * i - 2] = offsetX + x; |
| polygon[8 * r - 2 * i - 1] = offsetY - y; |
| } |
| region.add(polygon); |
| } |
| |
| public static void drawRoundFrame(GC gc, int width, int height) |
| { |
| Rectangle tmpClippingRect = gc.getClipping(); |
| Region reg = new Region(); |
| gc.getClipping(reg); |
| Region roundReg = new Region(); |
| getRegionForRoundRectangle(roundReg, 1, 1, width, height, RADIUS_OF_ROUND_EDGES - 1); |
| reg.subtract(roundReg); |
| gc.setClipping(reg); |
| gc.fillRectangle(0, 0, width + 1, height + 1); |
| reg.dispose(); |
| roundReg.dispose(); |
| gc.setClipping(tmpClippingRect); |
| } |
| |
| public static void loadPath(Region region, float[] points, byte[] types) |
| { |
| int start = 0, end = 0; |
| for (int i = 0; i < types.length; i++) |
| { |
| switch (types[i]) |
| { |
| case SWT.PATH_MOVE_TO: |
| { |
| if (start != end) |
| { |
| int n = 0; |
| int[] temp = new int[end - start]; |
| for (int k = start; k < end; k++) |
| { |
| temp[n++] = Math.round(points[k]); |
| } |
| region.add(temp); |
| } |
| start = end; |
| end += 2; |
| break; |
| } |
| case SWT.PATH_LINE_TO: |
| { |
| end += 2; |
| break; |
| } |
| case SWT.PATH_CLOSE: |
| { |
| if (start != end) |
| { |
| int n = 0; |
| int[] temp = new int[end - start]; |
| for (int k = start; k < end; k++) |
| { |
| temp[n++] = Math.round(points[k]); |
| } |
| region.add(temp); |
| } |
| start = end; |
| break; |
| } |
| } |
| } |
| } |
| |
| public static Path getPathForRoundRectangle(int x, int y, int width, int height, int r) |
| { |
| Path path = new Path(Display.getDefault()); |
| path.addArc(x, y, 2 * r, 2 * r, 0, 360); |
| path.addArc(width - 2 * r, y, 2 * r, 2 * r, 0, 360); |
| path.addArc(x, height - 2 * r, 2 * r, 2 * r, 0, 360); |
| path.addArc(width - 2 * r, height - 2 * r, 2 * r, 2 * r, 0, 360); |
| path.addRectangle(x, r - y, width - x, height - 2 * r); |
| path.addRectangle(r - x, y, width - 2 * r, height - y); |
| Path path2 = new Path(Display.getDefault(), path, 0.0001f); |
| path.dispose(); |
| return path2; |
| } |
| |
| public static void drawRoundRectangleByPath(GC gc, int x, int y, int width, int height) |
| { |
| Path path = getPathForRoundRectangle(x, y, width, height, RADIUS_OF_ROUND_EDGES - 1); |
| gc.drawPath(path); |
| path.dispose(); |
| } |
| |
| public static void getRegionForRoundRectangle(Region reg, int x, int y, int width, int height, int r) |
| { |
| Path tmpPath = getPathForRoundRectangle(x, y, width, height, r); |
| PathData data = tmpPath.getPathData(); |
| tmpPath.dispose(); |
| loadPath(reg, data.points, data.types); |
| } |
| } |