Lines 32-46
Link Here
|
32 |
import org.eclipse.swt.events.PaintListener; |
32 |
import org.eclipse.swt.events.PaintListener; |
33 |
import org.eclipse.swt.events.SelectionAdapter; |
33 |
import org.eclipse.swt.events.SelectionAdapter; |
34 |
import org.eclipse.swt.events.SelectionEvent; |
34 |
import org.eclipse.swt.events.SelectionEvent; |
|
|
35 |
import org.eclipse.swt.graphics.Color; |
35 |
import org.eclipse.swt.graphics.Cursor; |
36 |
import org.eclipse.swt.graphics.Cursor; |
36 |
import org.eclipse.swt.graphics.GC; |
37 |
import org.eclipse.swt.graphics.GC; |
37 |
import org.eclipse.swt.graphics.Image; |
38 |
import org.eclipse.swt.graphics.Image; |
38 |
import org.eclipse.swt.graphics.Point; |
39 |
import org.eclipse.swt.graphics.Point; |
|
|
40 |
import org.eclipse.swt.graphics.RGB; |
39 |
import org.eclipse.swt.graphics.Rectangle; |
41 |
import org.eclipse.swt.graphics.Rectangle; |
40 |
import org.eclipse.swt.graphics.Region; |
42 |
import org.eclipse.swt.graphics.Region; |
41 |
import org.eclipse.swt.layout.GridLayout; |
43 |
import org.eclipse.swt.layout.GridLayout; |
42 |
import org.eclipse.swt.widgets.Button; |
44 |
import org.eclipse.swt.widgets.Button; |
43 |
import org.eclipse.swt.widgets.Canvas; |
45 |
import org.eclipse.swt.widgets.Canvas; |
|
|
46 |
import org.eclipse.swt.widgets.ColorDialog; |
44 |
import org.eclipse.swt.widgets.Composite; |
47 |
import org.eclipse.swt.widgets.Composite; |
45 |
import org.eclipse.swt.widgets.Display; |
48 |
import org.eclipse.swt.widgets.Display; |
46 |
import org.eclipse.swt.widgets.Shell; |
49 |
import org.eclipse.swt.widgets.Shell; |
Lines 69-75
Link Here
|
69 |
|
72 |
|
70 |
private Button fitButton; |
73 |
private Button fitButton; |
71 |
|
74 |
|
72 |
private Image screenshotImage; |
75 |
private Button cropButton; |
|
|
76 |
|
77 |
private Button markButton; |
78 |
|
79 |
private Button colorButton; |
80 |
|
81 |
private Image colorIcon; |
82 |
|
83 |
private Color markColor; |
84 |
|
85 |
private Button resetButton; |
86 |
|
87 |
/** |
88 |
* Original screenshot image; used for backup purposes |
89 |
*/ |
90 |
private Image originalImage; |
91 |
|
92 |
/** |
93 |
* Copy of {@link #originalImage original} image; all drawing operations are done here; base for the result image |
94 |
*/ |
95 |
private Image workImage; |
96 |
|
97 |
/** |
98 |
* Used to draw into {@link #workImage} |
99 |
*/ |
100 |
private GC workImageGC; |
73 |
|
101 |
|
74 |
private Canvas canvas; |
102 |
private Canvas canvas; |
75 |
|
103 |
|
Lines 87-94
Link Here
|
87 |
private Rectangle originalSelection; |
115 |
private Rectangle originalSelection; |
88 |
|
116 |
|
89 |
/** |
117 |
/** |
90 |
* Temporary storage for selection start point or selection resizing initial reference point; this value is |
118 |
* Temporary storage for selection start point, selection resizing initial reference point or previous mark point |
91 |
* normalized to real image coordinates, no matter the zoom level (see {@link #scaleFactor}) |
119 |
* (it depends on current tool); this value is normalized to real image coordinates, no matter the zoom level (see |
|
|
120 |
* {@link #scaleFactor}) |
92 |
*/ |
121 |
*/ |
93 |
private Point startPoint; |
122 |
private Point startPoint; |
94 |
|
123 |
|
Lines 112-118
Link Here
|
112 |
*/ |
141 |
*/ |
113 |
private static enum Action { |
142 |
private static enum Action { |
114 |
|
143 |
|
115 |
IDLE, SELECTING, RESIZING_SELECTION, MOVING_SELECTION; |
144 |
IDLE, SELECTING, RESIZING_SELECTION, MOVING_SELECTION, MARKING; |
116 |
|
145 |
|
117 |
}; |
146 |
}; |
118 |
|
147 |
|
Lines 131-137
Link Here
|
131 |
} |
160 |
} |
132 |
|
161 |
|
133 |
public void createControl(Composite parent) { |
162 |
public void createControl(Composite parent) { |
134 |
|
|
|
135 |
Composite composite = new Composite(parent, SWT.NONE); |
163 |
Composite composite = new Composite(parent, SWT.NONE); |
136 |
composite.setLayout(new GridLayout()); |
164 |
composite.setLayout(new GridLayout()); |
137 |
setControl(composite); |
165 |
setControl(composite); |
Lines 139-154
Link Here
|
139 |
allocateCursors(); |
167 |
allocateCursors(); |
140 |
|
168 |
|
141 |
Composite buttonsComposite = new Composite(composite, SWT.NONE); |
169 |
Composite buttonsComposite = new Composite(composite, SWT.NONE); |
142 |
buttonsComposite.setLayout(new GridLayout(3, false)); |
170 |
buttonsComposite.setLayout(new GridLayout(6, false)); |
143 |
captureButton = new Button(buttonsComposite, SWT.PUSH); |
171 |
captureButton = new Button(buttonsComposite, SWT.PUSH); |
144 |
captureButton.setText("Capture Desktop"); |
172 |
captureButton.setText("&Capture Desktop"); |
145 |
captureButton.setImage(TasksUiImages.getImage(TasksUiImages.IMAGE_CAPTURE)); |
173 |
captureButton.setImage(TasksUiImages.getImage(TasksUiImages.IMAGE_CAPTURE)); |
146 |
captureButton.addSelectionListener(new SelectionAdapter() { |
174 |
captureButton.addSelectionListener(new SelectionAdapter() { |
147 |
|
175 |
|
|
|
176 |
private boolean isFirstCapture = true; |
177 |
|
148 |
public void widgetSelected(SelectionEvent e) { |
178 |
public void widgetSelected(SelectionEvent e) { |
149 |
captureScreenshotContent(); |
179 |
captureScreenshotContent(); |
150 |
page.setErrorMessage(null); |
180 |
page.setErrorMessage(null); |
151 |
fitButton.setEnabled(true); |
181 |
if (isFirstCapture) { |
|
|
182 |
isFirstCapture = false; |
183 |
fitButton.setEnabled(true); |
184 |
cropButton.setEnabled(true); |
185 |
cropButton.setSelection(true); |
186 |
markButton.setEnabled(true); |
187 |
resetButton.setEnabled(true); |
188 |
} |
152 |
} |
189 |
} |
153 |
|
190 |
|
154 |
}); |
191 |
}); |
Lines 187-193
Link Here
|
187 |
// }); |
224 |
// }); |
188 |
|
225 |
|
189 |
fitButton = new Button(buttonsComposite, SWT.TOGGLE); |
226 |
fitButton = new Button(buttonsComposite, SWT.TOGGLE); |
190 |
fitButton.setText("Fit Image"); |
227 |
fitButton.setText("&Fit Image"); |
191 |
fitButton.setImage(TasksUiImages.getImage(TasksUiImages.IMAGE_FIT)); |
228 |
fitButton.setImage(TasksUiImages.getImage(TasksUiImages.IMAGE_FIT)); |
192 |
fitButton.addSelectionListener(new SelectionAdapter() { |
229 |
fitButton.addSelectionListener(new SelectionAdapter() { |
193 |
|
230 |
|
Lines 199-204
Link Here
|
199 |
fitButton.setSelection(true); |
236 |
fitButton.setSelection(true); |
200 |
fitButton.setEnabled(false); |
237 |
fitButton.setEnabled(false); |
201 |
|
238 |
|
|
|
239 |
cropButton = new Button(buttonsComposite, SWT.TOGGLE); |
240 |
cropButton.setText("Cro&p"); |
241 |
cropButton.addSelectionListener(new SelectionAdapter() { |
242 |
|
243 |
@Override |
244 |
public void widgetSelected(SelectionEvent e) { |
245 |
currentAction = Action.IDLE; |
246 |
cropButton.setSelection(true); |
247 |
markButton.setSelection(false); |
248 |
colorButton.setEnabled(false); |
249 |
canvas.redraw(); |
250 |
} |
251 |
|
252 |
}); |
253 |
cropButton.setEnabled(false); |
254 |
|
255 |
markButton = new Button(buttonsComposite, SWT.TOGGLE); |
256 |
markButton.setText("&Mark"); |
257 |
markButton.addSelectionListener(new SelectionAdapter() { |
258 |
|
259 |
@Override |
260 |
public void widgetSelected(SelectionEvent e) { |
261 |
currentAction = Action.MARKING; |
262 |
cropButton.setSelection(false); |
263 |
markButton.setSelection(true); |
264 |
colorButton.setEnabled(true); |
265 |
canvas.redraw(); |
266 |
} |
267 |
|
268 |
}); |
269 |
markButton.setEnabled(false); |
270 |
|
271 |
colorButton = new Button(buttonsComposite, SWT.PUSH); |
272 |
colorButton.setText("Change Co&lor..."); |
273 |
colorIcon = new Image(Display.getCurrent(), 16, 16); |
274 |
setMarkColor(new RGB(255, 0, 0)); |
275 |
colorButton.setEnabled(false); |
276 |
colorButton.addSelectionListener(new SelectionAdapter() { |
277 |
|
278 |
@Override |
279 |
public void widgetSelected(SelectionEvent e) { |
280 |
ColorDialog dialog = new ColorDialog(getControl().getShell()); |
281 |
RGB color = dialog.open(); |
282 |
if (color != null) { |
283 |
setMarkColor(color); |
284 |
} |
285 |
} |
286 |
|
287 |
}); |
288 |
|
289 |
resetButton = new Button(buttonsComposite, SWT.PUSH); |
290 |
resetButton.setText("&Reset Image"); |
291 |
resetButton.addSelectionListener(new SelectionAdapter() { |
292 |
|
293 |
@Override |
294 |
public void widgetSelected(SelectionEvent e) { |
295 |
workImageGC.drawImage(originalImage, 0, 0); |
296 |
canvas.redraw(); |
297 |
} |
298 |
|
299 |
}); |
300 |
resetButton.setEnabled(false); |
301 |
|
202 |
scrolledComposite = new ScrolledComposite(composite, SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER); |
302 |
scrolledComposite = new ScrolledComposite(composite, SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER); |
203 |
scrolledComposite.setLayoutData(GridDataFactory.fillDefaults() |
303 |
scrolledComposite.setLayoutData(GridDataFactory.fillDefaults() |
204 |
.align(SWT.FILL, SWT.FILL) |
304 |
.align(SWT.FILL, SWT.FILL) |
Lines 210-224
Link Here
|
210 |
canvas.addPaintListener(new PaintListener() { |
310 |
canvas.addPaintListener(new PaintListener() { |
211 |
|
311 |
|
212 |
public void paintControl(PaintEvent e) { |
312 |
public void paintControl(PaintEvent e) { |
213 |
if (screenshotImage != null) { |
313 |
if (workImage != null) { |
214 |
Rectangle imageBounds = screenshotImage.getBounds(); |
314 |
Rectangle imageBounds = workImage.getBounds(); |
215 |
Rectangle canvasBounds = canvas.getClientArea(); |
315 |
Rectangle canvasBounds = canvas.getClientArea(); |
216 |
|
316 |
|
217 |
if (fitButton.getSelection()) { |
317 |
if (fitButton.getSelection()) { |
218 |
e.gc.drawImage(screenshotImage, 0, 0, imageBounds.width, imageBounds.height, 0, 0, |
318 |
e.gc.drawImage(workImage, 0, 0, imageBounds.width, imageBounds.height, 0, 0, |
219 |
canvasBounds.width, canvasBounds.height); |
319 |
canvasBounds.width, canvasBounds.height); |
220 |
} else { |
320 |
} else { |
221 |
e.gc.drawImage(screenshotImage, 0, 0); |
321 |
e.gc.drawImage(workImage, 0, 0); |
222 |
} |
322 |
} |
223 |
|
323 |
|
224 |
if (currentAction == Action.IDLE) { |
324 |
if (currentAction == Action.IDLE) { |
Lines 226-232
Link Here
|
226 |
drawSelection(e.gc); |
326 |
drawSelection(e.gc); |
227 |
} |
327 |
} |
228 |
} else if (currentAction == Action.SELECTING || currentAction == Action.RESIZING_SELECTION |
328 |
} else if (currentAction == Action.SELECTING || currentAction == Action.RESIZING_SELECTION |
229 |
|| currentAction == Action.MOVING_SELECTION) { |
329 |
|| currentAction == Action.MOVING_SELECTION || currentAction == Action.MARKING) { |
230 |
if (currentSelection != null) { |
330 |
if (currentSelection != null) { |
231 |
drawSelectionPreview(e.gc); |
331 |
drawSelectionPreview(e.gc); |
232 |
} |
332 |
} |
Lines 250-257
Link Here
|
250 |
registerMouseListeners(); |
350 |
registerMouseListeners(); |
251 |
} |
351 |
} |
252 |
|
352 |
|
|
|
353 |
private void setMarkColor(RGB color) { |
354 |
if (markColor != null) { |
355 |
markColor.dispose(); |
356 |
} |
357 |
markColor = new Color(Display.getCurrent(), color); |
358 |
if (workImageGC != null) { |
359 |
workImageGC.setForeground(markColor); |
360 |
} |
361 |
|
362 |
GC colorGC = new GC(colorIcon); |
363 |
colorGC.setBackground(markColor); |
364 |
colorGC.fillRectangle(0, 0, 15, 15); |
365 |
colorGC.drawRectangle(0, 0, 15, 15); |
366 |
colorGC.dispose(); |
367 |
|
368 |
colorButton.setImage(colorIcon); |
369 |
} |
370 |
|
253 |
@Override |
371 |
@Override |
254 |
public void dispose() { |
372 |
public void dispose() { |
|
|
373 |
disposeImageResources(); |
374 |
if (markColor != null) { |
375 |
markColor.dispose(); |
376 |
} |
377 |
if (colorIcon != null) { |
378 |
colorIcon.dispose(); |
379 |
} |
380 |
|
255 |
canvas.setCursor(null); |
381 |
canvas.setCursor(null); |
256 |
for (Cursor cursor : cursors.values()) { |
382 |
for (Cursor cursor : cursors.values()) { |
257 |
cursor.dispose(); |
383 |
cursor.dispose(); |
Lines 259-264
Link Here
|
259 |
super.dispose(); |
385 |
super.dispose(); |
260 |
} |
386 |
} |
261 |
|
387 |
|
|
|
388 |
private void disposeImageResources() { |
389 |
if (originalImage != null) { |
390 |
originalImage.dispose(); |
391 |
} |
392 |
if (workImageGC != null) { |
393 |
workImageGC.dispose(); |
394 |
} |
395 |
if (workImage != null) { |
396 |
workImage.dispose(); |
397 |
} |
398 |
} |
399 |
|
400 |
private static final int CURSOR_MARK_TOOL = -1; |
401 |
|
262 |
private void allocateCursors() { |
402 |
private void allocateCursors() { |
263 |
Display display = Display.getCurrent(); |
403 |
Display display = Display.getCurrent(); |
264 |
cursors.put(SWT.CURSOR_ARROW, new Cursor(display, SWT.CURSOR_ARROW)); |
404 |
cursors.put(SWT.CURSOR_ARROW, new Cursor(display, SWT.CURSOR_ARROW)); |
Lines 268-273
Link Here
|
268 |
cursors.put(SWT.CURSOR_SIZENS, new Cursor(display, SWT.CURSOR_SIZENS)); |
408 |
cursors.put(SWT.CURSOR_SIZENS, new Cursor(display, SWT.CURSOR_SIZENS)); |
269 |
cursors.put(SWT.CURSOR_SIZEWE, new Cursor(display, SWT.CURSOR_SIZEWE)); |
409 |
cursors.put(SWT.CURSOR_SIZEWE, new Cursor(display, SWT.CURSOR_SIZEWE)); |
270 |
cursors.put(SWT.CURSOR_CROSS, new Cursor(display, SWT.CURSOR_CROSS)); |
410 |
cursors.put(SWT.CURSOR_CROSS, new Cursor(display, SWT.CURSOR_CROSS)); |
|
|
411 |
|
412 |
// TODO: allocate custom cursor for "mark" tool |
413 |
cursors.put(CURSOR_MARK_TOOL, new Cursor(display, SWT.CURSOR_HAND)); |
271 |
} |
414 |
} |
272 |
|
415 |
|
273 |
private Rectangle getScaledSelection() { |
416 |
private Rectangle getScaledSelection() { |
Lines 278-293
Link Here
|
278 |
int y = (int) Math.round(currentSelection.y * scaleFactor); |
421 |
int y = (int) Math.round(currentSelection.y * scaleFactor); |
279 |
int right = (int) Math.round((currentSelection.x + currentSelection.width) * scaleFactor); |
422 |
int right = (int) Math.round((currentSelection.x + currentSelection.width) * scaleFactor); |
280 |
int bottom = (int) Math.round((currentSelection.y + currentSelection.height) * scaleFactor); |
423 |
int bottom = (int) Math.round((currentSelection.y + currentSelection.height) * scaleFactor); |
281 |
int width = Math.min(right, (int) Math.round((screenshotImage.getBounds().width - 1) * scaleFactor)) - x; |
424 |
int width = Math.min(right, (int) Math.round((workImage.getBounds().width - 1) * scaleFactor)) - x; |
282 |
int height = Math.min(bottom, (int) Math.round((screenshotImage.getBounds().height - 1) * scaleFactor)) - y; |
425 |
int height = Math.min(bottom, (int) Math.round((workImage.getBounds().height - 1) * scaleFactor)) - y; |
283 |
return new Rectangle(x, y, width, height); |
426 |
return new Rectangle(x, y, width, height); |
284 |
} |
427 |
} |
285 |
|
428 |
|
286 |
@Override |
429 |
@Override |
287 |
public boolean isPageComplete() { |
430 |
public boolean isPageComplete() { |
288 |
if (screenshotImage == null) |
431 |
return workImage != null; |
289 |
return false; |
|
|
290 |
return true; |
291 |
} |
432 |
} |
292 |
|
433 |
|
293 |
@Override |
434 |
@Override |
Lines 296-302
Link Here
|
296 |
attachment.setContentType("image/jpeg"); |
437 |
attachment.setContentType("image/jpeg"); |
297 |
page.setFilePath(InputAttachmentSourcePage.SCREENSHOT_LABEL); |
438 |
page.setFilePath(InputAttachmentSourcePage.SCREENSHOT_LABEL); |
298 |
page.setContentType(); |
439 |
page.setContentType(); |
299 |
getCropScreenshot(); |
|
|
300 |
return page; |
440 |
return page; |
301 |
} |
441 |
} |
302 |
|
442 |
|
Lines 306-314
Link Here
|
306 |
} |
446 |
} |
307 |
|
447 |
|
308 |
private void captureScreenshotContent() { |
448 |
private void captureScreenshotContent() { |
309 |
|
449 |
Display display = Display.getDefault(); |
310 |
final Display display = Display.getDefault(); |
450 |
Shell wizardShell = getWizard().getContainer().getShell(); |
311 |
final Shell wizardShell = getWizard().getContainer().getShell(); |
|
|
312 |
wizardShell.setVisible(false); |
451 |
wizardShell.setVisible(false); |
313 |
|
452 |
|
314 |
// NOTE: need a wait since the shell can take time to disappear (e.g. fade on Vista) |
453 |
// NOTE: need a wait since the shell can take time to disappear (e.g. fade on Vista) |
Lines 318-341
Link Here
|
318 |
// ignore |
457 |
// ignore |
319 |
} |
458 |
} |
320 |
|
459 |
|
321 |
display.asyncExec(new Runnable() { |
460 |
disposeImageResources(); |
322 |
public void run() { |
461 |
Rectangle displayBounds = display.getBounds(); |
323 |
Rectangle displayBounds = display.getBounds(); |
462 |
originalImage = new Image(display, displayBounds); |
324 |
screenshotImage = new Image(display, displayBounds); |
463 |
workImage = new Image(display, displayBounds); |
325 |
|
464 |
|
326 |
GC gc = new GC(display); |
465 |
GC gc = new GC(display); |
327 |
gc.copyArea(screenshotImage, 0, 0); |
466 |
gc.copyArea(originalImage, 0, 0); |
328 |
gc.dispose(); |
467 |
gc.copyArea(workImage, 0, 0); |
|
|
468 |
gc.dispose(); |
329 |
|
469 |
|
330 |
clearSelection(); |
470 |
workImageGC = new GC(workImage); |
331 |
refreshCanvasSize(); |
471 |
workImageGC.setForeground(markColor); |
|
|
472 |
workImageGC.setLineWidth(4); |
473 |
workImageGC.setLineCap(SWT.CAP_ROUND); |
332 |
|
474 |
|
333 |
wizardShell.setVisible(true); |
475 |
clearSelection(); |
334 |
if (screenshotImage != null) { |
476 |
refreshCanvasSize(); |
335 |
setPageComplete(true); |
477 |
|
336 |
} |
478 |
wizardShell.setVisible(true); |
337 |
} |
479 |
setPageComplete(true); |
338 |
}); |
|
|
339 |
} |
480 |
} |
340 |
|
481 |
|
341 |
/** |
482 |
/** |
Lines 352-358
Link Here
|
352 |
currentSelection = new Rectangle(startX, startY, width, height); |
493 |
currentSelection = new Rectangle(startX, startY, width, height); |
353 |
|
494 |
|
354 |
// Decreases 1 pixel size from original image because Rectangle.intersect() consider them as right-bottom limit |
495 |
// Decreases 1 pixel size from original image because Rectangle.intersect() consider them as right-bottom limit |
355 |
Rectangle imageBounds = screenshotImage.getBounds(); |
496 |
Rectangle imageBounds = workImage.getBounds(); |
356 |
imageBounds.width--; |
497 |
imageBounds.width--; |
357 |
imageBounds.height--; |
498 |
imageBounds.height--; |
358 |
currentSelection.intersect(imageBounds); |
499 |
currentSelection.intersect(imageBounds); |
Lines 367-373
Link Here
|
367 |
return; |
508 |
return; |
368 |
} |
509 |
} |
369 |
|
510 |
|
370 |
canvas.setCursor(null); |
|
|
371 |
grabPoints.clear(); |
511 |
grabPoints.clear(); |
372 |
Rectangle scaledSelection = getScaledSelection(); |
512 |
Rectangle scaledSelection = getScaledSelection(); |
373 |
grabPoints.add(GrabPoint.createGrabPoint(scaledSelection.x, scaledSelection.y, SWT.CURSOR_SIZENWSE, EnumSet.of( |
513 |
grabPoints.add(GrabPoint.createGrabPoint(scaledSelection.x, scaledSelection.y, SWT.CURSOR_SIZENWSE, EnumSet.of( |
Lines 393-399
Link Here
|
393 |
originalSelection.height); |
533 |
originalSelection.height); |
394 |
int deltaX = x - startPoint.x; |
534 |
int deltaX = x - startPoint.x; |
395 |
int deltaY = y - startPoint.y; |
535 |
int deltaY = y - startPoint.y; |
396 |
Rectangle imageBounds = screenshotImage.getBounds(); |
536 |
Rectangle imageBounds = workImage.getBounds(); |
397 |
|
537 |
|
398 |
// Check current selection limits |
538 |
// Check current selection limits |
399 |
if (resizableSides.contains(SelectionSide.LEFT)) { |
539 |
if (resizableSides.contains(SelectionSide.LEFT)) { |
Lines 447-453
Link Here
|
447 |
if (newY < 0) { |
587 |
if (newY < 0) { |
448 |
newY = 0; |
588 |
newY = 0; |
449 |
} |
589 |
} |
450 |
Rectangle imageBounds = screenshotImage.getBounds(); |
590 |
Rectangle imageBounds = workImage.getBounds(); |
451 |
if (newX + originalSelection.width - 1 > imageBounds.width) { |
591 |
if (newX + originalSelection.width - 1 > imageBounds.width) { |
452 |
newX = imageBounds.width - originalSelection.width; |
592 |
newX = imageBounds.width - originalSelection.width; |
453 |
} |
593 |
} |
Lines 464-478
Link Here
|
464 |
* If a selection is in course, moving the mouse around refreshes the selection rectangle |
604 |
* If a selection is in course, moving the mouse around refreshes the selection rectangle |
465 |
*/ |
605 |
*/ |
466 |
public void mouseMove(MouseEvent e) { |
606 |
public void mouseMove(MouseEvent e) { |
|
|
607 |
int scaledX = (int) Math.round(e.x / scaleFactor); |
608 |
int scaledY = (int) Math.round(e.y / scaleFactor); |
609 |
|
467 |
if (currentAction == Action.SELECTING) { |
610 |
if (currentAction == Action.SELECTING) { |
468 |
// Selection in course |
611 |
refreshCurrentSelection(scaledX, scaledY); |
469 |
refreshCurrentSelection((int) Math.round(e.x / scaleFactor), (int) Math.round(e.y / scaleFactor)); |
|
|
470 |
canvas.redraw(); |
612 |
canvas.redraw(); |
471 |
} else if (currentAction == Action.RESIZING_SELECTION) { |
613 |
} else if (currentAction == Action.RESIZING_SELECTION) { |
472 |
refreshSelectionResize((int) Math.round(e.x / scaleFactor), (int) Math.round(e.y / scaleFactor)); |
614 |
refreshSelectionResize(scaledX, scaledY); |
473 |
canvas.redraw(); |
615 |
canvas.redraw(); |
474 |
} else if (currentAction == Action.MOVING_SELECTION) { |
616 |
} else if (currentAction == Action.MOVING_SELECTION) { |
475 |
refreshSelectionPosition((int) Math.round(e.x / scaleFactor), (int) Math.round(e.y / scaleFactor)); |
617 |
refreshSelectionPosition(scaledX, scaledY); |
476 |
canvas.redraw(); |
618 |
canvas.redraw(); |
477 |
} else if (currentAction == Action.IDLE && currentSelection != null) { |
619 |
} else if (currentAction == Action.IDLE && currentSelection != null) { |
478 |
boolean cursorSet = false; |
620 |
boolean cursorSet = false; |
Lines 491-498
Link Here
|
491 |
canvas.setCursor(cursors.get(SWT.CURSOR_SIZEALL)); |
633 |
canvas.setCursor(cursors.get(SWT.CURSOR_SIZEALL)); |
492 |
cursorSet = true; |
634 |
cursorSet = true; |
493 |
} |
635 |
} |
494 |
if (!cursorSet && canvas.getCursor() != null) { |
636 |
|
495 |
canvas.setCursor(null); |
637 |
// If I'm out, the default cursor for cropping mode is cross |
|
|
638 |
Cursor crossCursor = cursors.get(SWT.CURSOR_CROSS); |
639 |
if (!cursorSet && canvas.getCursor() != crossCursor) { |
640 |
canvas.setCursor(crossCursor); |
641 |
} |
642 |
} else if (currentAction == Action.MARKING) { |
643 |
drawMarkLine(scaledX, scaledY); |
644 |
|
645 |
Cursor markCursor = cursors.get(CURSOR_MARK_TOOL); |
646 |
if (canvas.getCursor() != markCursor) { |
647 |
canvas.setCursor(markCursor); |
496 |
} |
648 |
} |
497 |
} |
649 |
} |
498 |
} |
650 |
} |
Lines 508-515
Link Here
|
508 |
public void mouseUp(MouseEvent e) { |
660 |
public void mouseUp(MouseEvent e) { |
509 |
if (currentAction == Action.SELECTING || currentAction == Action.RESIZING_SELECTION |
661 |
if (currentAction == Action.SELECTING || currentAction == Action.RESIZING_SELECTION |
510 |
|| currentAction == Action.MOVING_SELECTION) { |
662 |
|| currentAction == Action.MOVING_SELECTION) { |
511 |
canvas.setCursor(cursors.get(SWT.CURSOR_ARROW)); |
|
|
512 |
|
513 |
int scaledX = (int) Math.round(e.x / scaleFactor); |
663 |
int scaledX = (int) Math.round(e.x / scaleFactor); |
514 |
int scaledY = (int) Math.round(e.y / scaleFactor); |
664 |
int scaledY = (int) Math.round(e.y / scaleFactor); |
515 |
if (currentAction == Action.SELECTING) { |
665 |
if (currentAction == Action.SELECTING) { |
Lines 527-532
Link Here
|
527 |
currentAction = Action.IDLE; |
677 |
currentAction = Action.IDLE; |
528 |
|
678 |
|
529 |
canvas.redraw(); |
679 |
canvas.redraw(); |
|
|
680 |
} else if (currentAction == Action.MARKING) { |
681 |
startPoint = null; |
530 |
} |
682 |
} |
531 |
} |
683 |
} |
532 |
|
684 |
|
Lines 534-540
Link Here
|
534 |
* Pressing mouse button starts a selection; normalizes and marks the start point |
686 |
* Pressing mouse button starts a selection; normalizes and marks the start point |
535 |
*/ |
687 |
*/ |
536 |
public void mouseDown(MouseEvent e) { |
688 |
public void mouseDown(MouseEvent e) { |
537 |
if (currentAction != Action.IDLE) { |
689 |
int scaledX = (int) (e.x / scaleFactor); |
|
|
690 |
int scaledY = (int) (e.y / scaleFactor); |
691 |
|
692 |
if (currentAction == Action.MARKING) { |
693 |
startPoint = new Point(scaledX, scaledY); |
694 |
drawMarkLine(scaledX, scaledY); |
695 |
canvas.setCursor(cursors.get(CURSOR_MARK_TOOL)); |
696 |
return; |
697 |
} else if (currentAction != Action.IDLE) { |
538 |
return; |
698 |
return; |
539 |
} |
699 |
} |
540 |
|
700 |
|
Lines 545-551
Link Here
|
545 |
originalSelection = currentSelection; |
705 |
originalSelection = currentSelection; |
546 |
currentAction = Action.RESIZING_SELECTION; |
706 |
currentAction = Action.RESIZING_SELECTION; |
547 |
resizableSides = point.resizableSides; |
707 |
resizableSides = point.resizableSides; |
548 |
startPoint = new Point((int) (e.x / scaleFactor), (int) (e.y / scaleFactor)); |
708 |
startPoint = new Point(scaledX, scaledY); |
549 |
canvas.redraw(); |
709 |
canvas.redraw(); |
550 |
return; |
710 |
return; |
551 |
} |
711 |
} |
Lines 553-563
Link Here
|
553 |
} |
713 |
} |
554 |
|
714 |
|
555 |
// Check if I could move the selection |
715 |
// Check if I could move the selection |
556 |
if (currentSelection != null |
716 |
if (currentSelection != null && currentSelection.contains(scaledX, scaledY)) { |
557 |
&& currentSelection.contains((int) (e.x / scaleFactor), (int) (e.y / scaleFactor))) { |
|
|
558 |
originalSelection = currentSelection; |
717 |
originalSelection = currentSelection; |
559 |
currentAction = Action.MOVING_SELECTION; |
718 |
currentAction = Action.MOVING_SELECTION; |
560 |
startPoint = new Point((int) (e.x / scaleFactor), (int) (e.y / scaleFactor)); |
719 |
startPoint = new Point(scaledX, scaledY); |
561 |
canvas.redraw(); |
720 |
canvas.redraw(); |
562 |
return; |
721 |
return; |
563 |
} |
722 |
} |
Lines 566-572
Link Here
|
566 |
canvas.setCursor(cursors.get(SWT.CURSOR_CROSS)); |
725 |
canvas.setCursor(cursors.get(SWT.CURSOR_CROSS)); |
567 |
currentAction = Action.SELECTING; |
726 |
currentAction = Action.SELECTING; |
568 |
currentSelection = null; |
727 |
currentSelection = null; |
569 |
startPoint = new Point((int) (e.x / scaleFactor), (int) (e.y / scaleFactor)); |
728 |
startPoint = new Point(scaledX, scaledY); |
570 |
canvas.redraw(); |
729 |
canvas.redraw(); |
571 |
} |
730 |
} |
572 |
|
731 |
|
Lines 582-589
Link Here
|
582 |
/** |
741 |
/** |
583 |
* Recalculates image canvas size based on "fit on canvas" setting, set up the grab points, and redraws |
742 |
* Recalculates image canvas size based on "fit on canvas" setting, set up the grab points, and redraws |
584 |
* <p> |
743 |
* <p> |
585 |
* This method should be called whenever the {@link #screenshotImage image} <strong>visible</strong> size is |
744 |
* This method should be called whenever the {@link #workImage image} <strong>visible</strong> size is changed, |
586 |
* changed, which can happen when: |
745 |
* which can happen when: |
587 |
* <p> |
746 |
* <p> |
588 |
* <ul> |
747 |
* <ul> |
589 |
* <li>The "Fit Image" setting is changed, so the image zoom level changes |
748 |
* <li>The "Fit Image" setting is changed, so the image zoom level changes |
Lines 602-609
Link Here
|
602 |
scrolledComposite.getVerticalBar().setVisible(false); |
761 |
scrolledComposite.getVerticalBar().setVisible(false); |
603 |
|
762 |
|
604 |
Rectangle bounds = scrolledComposite.getClientArea(); |
763 |
Rectangle bounds = scrolledComposite.getClientArea(); |
605 |
if (screenshotImage != null) { |
764 |
if (workImage != null) { |
606 |
Rectangle imageBounds = screenshotImage.getBounds(); |
765 |
Rectangle imageBounds = workImage.getBounds(); |
607 |
if (imageBounds.width > bounds.width || imageBounds.height > bounds.height) { |
766 |
if (imageBounds.width > bounds.width || imageBounds.height > bounds.height) { |
608 |
double xRatio = (double) bounds.width / imageBounds.width; |
767 |
double xRatio = (double) bounds.width / imageBounds.width; |
609 |
double yRatio = (double) bounds.height / imageBounds.height; |
768 |
double yRatio = (double) bounds.height / imageBounds.height; |
Lines 616-623
Link Here
|
616 |
} else { |
775 |
} else { |
617 |
scaleFactor = 1.0; |
776 |
scaleFactor = 1.0; |
618 |
Rectangle bounds = scrolledComposite.getClientArea(); |
777 |
Rectangle bounds = scrolledComposite.getClientArea(); |
619 |
if (screenshotImage != null) { |
778 |
if (workImage != null) { |
620 |
Rectangle imageBounds = screenshotImage.getBounds(); |
779 |
Rectangle imageBounds = workImage.getBounds(); |
621 |
bounds.width = imageBounds.width; |
780 |
bounds.width = imageBounds.width; |
622 |
bounds.height = imageBounds.height; |
781 |
bounds.height = imageBounds.height; |
623 |
} |
782 |
} |
Lines 678-683
Link Here
|
678 |
} |
837 |
} |
679 |
} |
838 |
} |
680 |
|
839 |
|
|
|
840 |
/** |
841 |
* Connects the previous mark point to the new reference point, by drawing a new line |
842 |
*/ |
843 |
private void drawMarkLine(int x, int y) { |
844 |
if (startPoint != null) { |
845 |
workImageGC.drawLine(startPoint.x, startPoint.y, x, y); |
846 |
startPoint.x = x; |
847 |
startPoint.y = y; |
848 |
canvas.redraw(); |
849 |
} |
850 |
} |
851 |
|
681 |
private static enum SelectionSide { |
852 |
private static enum SelectionSide { |
682 |
|
853 |
|
683 |
LEFT, RIGHT, TOP, BOTTOM; |
854 |
LEFT, RIGHT, TOP, BOTTOM; |
Lines 706-727
Link Here
|
706 |
|
877 |
|
707 |
private List<GrabPoint> grabPoints = new ArrayList<GrabPoint>(8); |
878 |
private List<GrabPoint> grabPoints = new ArrayList<GrabPoint>(8); |
708 |
|
879 |
|
709 |
private Image getCropScreenshot() { |
880 |
/** |
710 |
if (currentSelection == null) { |
881 |
* Creates the final screenshot |
711 |
return screenshotImage; |
882 |
* |
|
|
883 |
* @return The final screenshot, with all markings, and cropped according to user settings; <strong>The caller is |
884 |
* responsible for disposing the returned image</strong> |
885 |
*/ |
886 |
public Image createScreenshotImage() { |
887 |
Image screenshot = new Image(Display.getDefault(), currentSelection != null ? currentSelection |
888 |
: workImage.getBounds()); |
889 |
|
890 |
GC gc = new GC(screenshot); |
891 |
if (currentSelection != null) { |
892 |
gc.drawImage(workImage, currentSelection.x, currentSelection.y, currentSelection.width, |
893 |
currentSelection.height, 0, 0, currentSelection.width, currentSelection.height); |
894 |
} else { |
895 |
gc.drawImage(workImage, 0, 0); |
712 |
} |
896 |
} |
713 |
|
|
|
714 |
Image image = new Image(Display.getDefault(), currentSelection); |
715 |
GC gc = new GC(image); |
716 |
gc.drawImage(screenshotImage, currentSelection.x, currentSelection.y, currentSelection.width, |
717 |
currentSelection.height, 0, 0, currentSelection.width, currentSelection.height); |
718 |
gc.dispose(); |
897 |
gc.dispose(); |
719 |
|
898 |
|
720 |
return image; |
899 |
return screenshot; |
721 |
} |
|
|
722 |
|
723 |
public Image getScreenshotImage() { |
724 |
return getCropScreenshot(); |
725 |
} |
900 |
} |
726 |
|
901 |
|
727 |
} |
902 |
} |