Skip to content

Commit 8dcdeab

Browse files
committed
Add a new snippet to demonstrate drawing to different devices
1 parent 9112e41 commit 8dcdeab

File tree

1 file changed

+262
-0
lines changed
  • examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets

1 file changed

+262
-0
lines changed
Lines changed: 262 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2026 Eclipse Platform Contributors and others.
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* Eclipse Platform Contributors - initial API and implementation
13+
*******************************************************************************/
14+
package org.eclipse.swt.snippets;
15+
16+
/*
17+
* Drawing operations test snippet: compare drawing on Display, Printer and PDF
18+
*
19+
* This snippet demonstrates drawing operations across different devices (Display, Printer, PDF)
20+
* to verify that drawing is consistent. It draws a test pattern with borders, crosses, and
21+
* a reference box of a specific physical size (in centimeters).
22+
*
23+
* For a list of all SWT example snippets see
24+
* http://www.eclipse.org/swt/snippets/
25+
*/
26+
27+
import org.eclipse.swt.*;
28+
import org.eclipse.swt.graphics.*;
29+
import org.eclipse.swt.layout.*;
30+
import org.eclipse.swt.printing.*;
31+
import org.eclipse.swt.program.*;
32+
import org.eclipse.swt.widgets.*;
33+
34+
public class Snippet391 {
35+
36+
private static int boxSizeCm = 10;
37+
private static boolean considerMonitorZoom = false;
38+
39+
public static void main(String[] args) {
40+
Display display = new Display();
41+
Shell shell = new Shell(display);
42+
shell.setText("Drawing Operations Test - Snippet 391");
43+
shell.setLayout(new GridLayout(2, false));
44+
45+
// Canvas on the left
46+
Canvas canvas = new Canvas(shell, SWT.BORDER | SWT.DOUBLE_BUFFERED);
47+
GridData canvasData = new GridData(SWT.FILL, SWT.FILL, true, true);
48+
canvasData.minimumWidth = 400;
49+
canvasData.minimumHeight = 400;
50+
canvas.setLayoutData(canvasData);
51+
canvas.setBackground(display.getSystemColor(SWT.COLOR_WHITE));
52+
53+
canvas.addListener(SWT.Paint, e -> {
54+
Monitor monitor = canvas.getMonitor();
55+
Rectangle clientArea = canvas.getClientArea();
56+
drawTestPattern(e.gc, display, clientArea, monitor);
57+
});
58+
59+
// Controls on the right
60+
Composite controlPanel = new Composite(shell, SWT.NONE);
61+
controlPanel.setLayout(new GridLayout(2, false));
62+
controlPanel.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
63+
64+
// Box size spinner
65+
Label sizeLabel = new Label(controlPanel, SWT.NONE);
66+
sizeLabel.setText("Box size (cm):");
67+
68+
Spinner sizeSpinner = new Spinner(controlPanel, SWT.BORDER);
69+
sizeSpinner.setMinimum(1);
70+
sizeSpinner.setMaximum(50);
71+
sizeSpinner.setSelection(boxSizeCm);
72+
sizeSpinner.addListener(SWT.Selection, e -> {
73+
boxSizeCm = sizeSpinner.getSelection();
74+
canvas.redraw();
75+
});
76+
77+
// Monitor zoom checkbox
78+
Button zoomCheckbox = new Button(controlPanel, SWT.CHECK);
79+
zoomCheckbox.setText("Consider Monitor zoom");
80+
GridData checkboxData = new GridData();
81+
checkboxData.horizontalSpan = 2;
82+
zoomCheckbox.setLayoutData(checkboxData);
83+
zoomCheckbox.addListener(SWT.Selection, e -> {
84+
considerMonitorZoom = zoomCheckbox.getSelection();
85+
canvas.redraw();
86+
});
87+
88+
// Separator
89+
Label separator = new Label(controlPanel, SWT.SEPARATOR | SWT.HORIZONTAL);
90+
GridData sepData = new GridData(SWT.FILL, SWT.CENTER, true, false);
91+
sepData.horizontalSpan = 2;
92+
separator.setLayoutData(sepData);
93+
94+
// Print button
95+
Button printButton = new Button(controlPanel, SWT.PUSH);
96+
printButton.setText("Print");
97+
GridData printData = new GridData(SWT.FILL, SWT.CENTER, true, false);
98+
printData.horizontalSpan = 2;
99+
printButton.setLayoutData(printData);
100+
printButton.addListener(SWT.Selection, e -> printToPrinter(shell));
101+
102+
// Create PDF button
103+
Button pdfButton = new Button(controlPanel, SWT.PUSH);
104+
pdfButton.setText("Create PDF");
105+
GridData pdfData = new GridData(SWT.FILL, SWT.CENTER, true, false);
106+
pdfData.horizontalSpan = 2;
107+
pdfButton.setLayoutData(pdfData);
108+
pdfButton.addListener(SWT.Selection, e -> createPdf(shell, canvas));
109+
110+
shell.setSize(800, 600);
111+
shell.open();
112+
113+
while (!shell.isDisposed()) {
114+
if (!display.readAndDispatch()) {
115+
display.sleep();
116+
}
117+
}
118+
display.dispose();
119+
}
120+
121+
/**
122+
* Draws a test pattern on the given GC.
123+
*
124+
* @param gc the graphics context to draw on
125+
* @param device the device (Display, Printer, or PDFDocument)
126+
* @param rect the rectangle defining the drawing area
127+
* @param monitor optional monitor for zoom information (can be null)
128+
*/
129+
public static void drawTestPattern(GC gc, Device device, Rectangle rect, Monitor monitor) {
130+
Point deviceDpi = device.getDPI();
131+
int dpi = deviceDpi.x;
132+
// Calculate effective DPI considering monitor zoom if enabled
133+
int effectiveDpi = dpi;
134+
if (monitor != null && considerMonitorZoom) {
135+
int zoom = monitor.getZoom();
136+
effectiveDpi = (dpi * zoom) / 100;
137+
}
138+
139+
// Save original settings
140+
int originalLineWidth = gc.getLineWidth();
141+
Color originalFg = gc.getForeground();
142+
143+
// Draw red border at 1px distance from edges
144+
gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_RED));
145+
gc.setLineWidth(1);
146+
gc.drawRectangle(rect.x + 1, rect.y + 1, rect.width - 3, rect.height - 3);
147+
148+
// Draw blue border at 5px distance from edges
149+
gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_BLUE));
150+
gc.drawRectangle(rect.x + 5, rect.y + 5, rect.width - 11, rect.height - 11);
151+
152+
// Draw DPI info in upper left if drawable is a Device
153+
gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_BLACK));
154+
gc.drawString("DPI: " + dpi, rect.x + 10, rect.y + 10, true);
155+
156+
// Draw monitor zoom in upper right if monitor is given
157+
if (monitor != null) {
158+
String zoomText = "Zoom: " + monitor.getZoom() + "%";
159+
Point textExtent = gc.stringExtent(zoomText);
160+
gc.drawString(zoomText, rect.x + rect.width - textExtent.x - 10, rect.y + 10, true);
161+
}
162+
163+
// Draw black cross with 2px line width over full rectangle
164+
gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_BLACK));
165+
gc.setLineWidth(2);
166+
gc.drawLine(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height);
167+
gc.drawLine(rect.x + rect.width, rect.y, rect.x, rect.y + rect.height);
168+
169+
// Calculate box size in pixels from centimeters
170+
// 1 inch = 2.54 cm, so pixels = (cm / 2.54) * DPI
171+
int boxWidthPx = (int) Math.round((boxSizeCm / 2.54) * effectiveDpi);
172+
int boxHeightPx = boxWidthPx;
173+
174+
// Center the box in the rectangle
175+
int boxX = rect.x + (rect.width - boxWidthPx) / 2;
176+
int boxY = rect.y + (rect.height - boxHeightPx) / 2;
177+
178+
// Fill the box with light gray
179+
gc.setBackground(gc.getDevice().getSystemColor(SWT.COLOR_GRAY));
180+
gc.fillRectangle(boxX, boxY, boxWidthPx, boxHeightPx);
181+
182+
// Draw 1px black border around the box
183+
gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_BLACK));
184+
gc.setLineWidth(1);
185+
gc.drawRectangle(boxX, boxY, boxWidthPx, boxHeightPx);
186+
187+
// Show the actual computed pixel dimensions on top/right of the box
188+
String pixelInfo = boxWidthPx + " x " + boxHeightPx + " px";
189+
Point infoExtent = gc.stringExtent(pixelInfo);
190+
int infoX = boxX + boxWidthPx - infoExtent.x;
191+
int infoY = boxY - infoExtent.y - 2;
192+
if (infoY < rect.y + 30) {
193+
infoY = rect.y + 30;
194+
}
195+
gc.drawString(pixelInfo, infoX, infoY, true);
196+
197+
// Show the box size in cm below the pixel info
198+
String cmInfo = boxSizeCm + " cm (effective DPI: " + effectiveDpi + ")";
199+
gc.drawString(cmInfo, boxX, boxY + boxHeightPx + 5, true);
200+
201+
// Restore original settings
202+
gc.setLineWidth(originalLineWidth);
203+
gc.setForeground(originalFg);
204+
}
205+
206+
private static void printToPrinter(Shell shell) {
207+
PrintDialog printDialog = new PrintDialog(shell);
208+
PrinterData data = printDialog.open();
209+
if (data == null) {
210+
return; // User cancelled
211+
}
212+
213+
Printer printer = new Printer(data);
214+
if (printer.startJob("Drawing Test - Snippet 391")) {
215+
GC gc = new GC(printer);
216+
if (printer.startPage()) {
217+
Rectangle printArea = printer.getClientArea();
218+
drawTestPattern(gc, printer, printArea, null);
219+
printer.endPage();
220+
}
221+
gc.dispose();
222+
printer.endJob();
223+
}
224+
printer.dispose();
225+
226+
MessageBox msgBox = new MessageBox(shell, SWT.ICON_INFORMATION | SWT.OK);
227+
msgBox.setText("Print Complete");
228+
msgBox.setMessage("Document sent to printer.");
229+
msgBox.open();
230+
}
231+
232+
private static void createPdf(Shell shell, Canvas canvas) {
233+
try {
234+
String tempDir = System.getProperty("java.io.tmpdir");
235+
String pdfPath = tempDir + "/drawing_test_snippet391.pdf";
236+
237+
// Use exact canvas size in points (1 point = 1 pixel at 72 DPI)
238+
Point canvasSize = canvas.getSize();
239+
double widthPoints = canvasSize.x;
240+
double heightPoints = canvasSize.y;
241+
242+
PDFDocument pdf = new PDFDocument(pdfPath, widthPoints, heightPoints);
243+
GC gc = new GC(pdf);
244+
245+
Rectangle pdfRect = new Rectangle(0, 0, canvasSize.x, canvasSize.y);
246+
drawTestPattern(gc, pdf, pdfRect, null);
247+
248+
gc.dispose();
249+
pdf.dispose();
250+
251+
System.out.println("PDF exported to: " + pdfPath);
252+
Program.launch(pdfPath);
253+
254+
} catch (Throwable ex) {
255+
MessageBox errorBox = new MessageBox(shell, SWT.ICON_ERROR | SWT.OK);
256+
errorBox.setText("Error");
257+
errorBox.setMessage("Failed to create PDF: " + ex.getMessage());
258+
errorBox.open();
259+
ex.printStackTrace();
260+
}
261+
}
262+
}

0 commit comments

Comments
 (0)