Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 90227 Details for
Bug 195691
allow users to mark up screenshots
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
[patch]
Patch
clipboard.txt (text/plain), 50.90 KB, created by
Willian Mitsuda
on 2008-02-20 13:42:46 EST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Willian Mitsuda
Created:
2008-02-20 13:42:46 EST
Size:
50.90 KB
patch
obsolete
>### Eclipse Workspace Patch 1.0 >#P org.eclipse.mylyn.tasks.ui >Index: src/org/eclipse/mylyn/internal/tasks/ui/wizards/NewAttachmentPage.java >=================================================================== >RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/wizards/NewAttachmentPage.java,v >retrieving revision 1.17 >diff -u -r1.17 NewAttachmentPage.java >--- src/org/eclipse/mylyn/internal/tasks/ui/wizards/NewAttachmentPage.java 20 Feb 2008 00:01:57 -0000 1.17 >+++ src/org/eclipse/mylyn/internal/tasks/ui/wizards/NewAttachmentPage.java 20 Feb 2008 18:39:42 -0000 >@@ -239,7 +239,8 @@ > > @Override > public boolean isPageComplete() { >- return !"".equals(filePath.getText().trim()) && (attachmentDesc == null || !"".equals(attachmentDesc.getText().trim())); >+ return !"".equals(filePath.getText().trim()) >+ && (attachmentDesc == null || !"".equals(attachmentDesc.getText().trim())); > } > > public void populateAttachment() { >@@ -253,13 +254,6 @@ > return attachment; > } > >- @Override >- public boolean canFlipToNextPage() { >- if (filePath.getText().equals(InputAttachmentSourcePage.SCREENSHOT_LABEL)) >- return false; >- return isPageComplete(); >- } >- > public void setFilePath(String path) { > filePath.setText(path); > if (path.endsWith(".patch")) { >@@ -298,9 +292,9 @@ > public boolean supportsDescription() { > return supportsDescription; > } >- >+ > public void setSupportsDescription(boolean supportsDescription) { > this.supportsDescription = supportsDescription; > } >- >+ > } >Index: src/org/eclipse/mylyn/internal/tasks/ui/wizards/NewAttachmentWizard.java >=================================================================== >RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/wizards/NewAttachmentWizard.java,v >retrieving revision 1.38 >diff -u -r1.38 NewAttachmentWizard.java >--- src/org/eclipse/mylyn/internal/tasks/ui/wizards/NewAttachmentWizard.java 5 Feb 2008 04:23:10 -0000 1.38 >+++ src/org/eclipse/mylyn/internal/tasks/ui/wizards/NewAttachmentWizard.java 20 Feb 2008 18:39:42 -0000 >@@ -42,10 +42,6 @@ > import org.eclipse.mylyn.tasks.ui.editors.AbstractRepositoryTaskEditorInput; > import org.eclipse.mylyn.tasks.ui.editors.TaskEditor; > import org.eclipse.mylyn.tasks.ui.editors.TaskEditorInput; >-import org.eclipse.swt.SWT; >-import org.eclipse.swt.graphics.Image; >-import org.eclipse.swt.graphics.ImageData; >-import org.eclipse.swt.graphics.ImageLoader; > import org.eclipse.swt.widgets.Display; > import org.eclipse.ui.PlatformUI; > >@@ -81,7 +77,6 @@ > private boolean screenshotMode; > > public NewAttachmentWizard(TaskRepository repository, AbstractTask task, boolean screenshotMode) { >- super(); > this.task = task; > this.repository = repository; > this.screenshotMode = screenshotMode; >@@ -95,7 +90,12 @@ > } > > inputPage = new InputAttachmentSourcePage(this); >- attachment = new LocalAttachment(); >+ if (screenshotMode) { >+ shotPage = new ScreenshotAttachmentPage(); >+ attachment = new ImageAttachment(shotPage); >+ } else { >+ attachment = new LocalAttachment(); >+ } > attachment.setFilePath(""); > setNeedsProgressMonitor(true); > IDialogSettings workbenchSettings = TasksUiPlugin.getDefault().getDialogSettings(); >@@ -125,6 +125,15 @@ > } > > @Override >+ public void dispose() { >+ // Ensures the temporary screenshot image is deleted >+ if (attachment != null && attachment instanceof ImageAttachment) { >+ ((ImageAttachment) attachment).clearImageFile(); >+ } >+ super.dispose(); >+ } >+ >+ @Override > public boolean performFinish() { > /* TODO jpound - support non-text in clipboard */ > attachPage.populateAttachment(); >@@ -159,19 +168,7 @@ > task.setSynchronizationState(RepositoryTaskSyncState.OUTGOING); > > if (screenshotMode || InputAttachmentSourcePage.SCREENSHOT_LABEL.equals(path)) { >- Image image = shotPage.getScreenshotImage(); >- if (image == null) { >- throw new InvocationTargetException(new CoreException(new RepositoryStatus(IStatus.ERROR, >- TasksUiPlugin.ID_PLUGIN, RepositoryStatus.ERROR_INTERNAL, "Screenshot is empty", >- null))); >- } >- String path = TasksUiPlugin.getDefault().getDefaultDataDirectory(); >- ImageLoader loader = new ImageLoader(); >- loader.data = new ImageData[] { image.getImageData() }; >- String fileName = path + "/" + SCREENSHOT_FILENAME; >- loader.save(fileName, SWT.IMAGE_JPEG); >- attachment.setFile(new File(fileName)); >- attachment.setFilename(SCREENSHOT_FILENAME); >+ ((ImageAttachment) attachment).ensureImageFileWasCreated(); > } else if (InputAttachmentSourcePage.CLIPBOARD_LABEL.equals(path)) { > String contents = inputPage.getClipboardContents(); > if (contents == null) { >@@ -293,7 +290,7 @@ > @Override > public boolean canFinish() { > if (screenshotMode) { >- return shotPage.isPageComplete(); >+ return shotPage.isPageComplete() && attachPage.isPageComplete(); > } else { > return attachPage.isPageComplete(); > } >@@ -303,7 +300,7 @@ > public void addPages() { > super.addPages(); > if (screenshotMode) { >- addPage((shotPage = new ScreenshotAttachmentPage(attachment))); >+ addPage(shotPage); > addPage((attachPage = new NewAttachmentPage(attachment))); > } else { > if ("".equals(attachment.getFilePath())) { >Index: src/org/eclipse/mylyn/internal/tasks/ui/wizards/PreviewAttachmentPage.java >=================================================================== >RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/wizards/PreviewAttachmentPage.java,v >retrieving revision 1.9 >diff -u -r1.9 PreviewAttachmentPage.java >--- src/org/eclipse/mylyn/internal/tasks/ui/wizards/PreviewAttachmentPage.java 20 Sep 2007 15:21:47 -0000 1.9 >+++ src/org/eclipse/mylyn/internal/tasks/ui/wizards/PreviewAttachmentPage.java 20 Feb 2008 18:39:42 -0000 >@@ -13,10 +13,13 @@ > import java.io.FileNotFoundException; > import java.io.FileReader; > import java.io.IOException; >+import java.lang.reflect.InvocationTargetException; > import java.util.HashMap; > >+import org.eclipse.core.runtime.IProgressMonitor; > import org.eclipse.jface.layout.GridDataFactory; > import org.eclipse.jface.layout.GridLayoutFactory; >+import org.eclipse.jface.operation.IRunnableWithProgress; > import org.eclipse.jface.wizard.WizardPage; > import org.eclipse.mylyn.internal.tasks.core.LocalAttachment; > import org.eclipse.swt.SWT; >@@ -50,7 +53,7 @@ > private static final String TITLE = "Attachment Preview"; > > private static final String DESCRIPTION = "Review the attachment before submitting"; >- >+ > private LocalAttachment attachment; > > private static HashMap<String, String> textTypes; >@@ -93,6 +96,25 @@ > composite.setLayout(new GridLayout()); > setControl(composite); > >+ if (attachment instanceof ImageAttachment) { >+ try { >+ getContainer().run(true, false, new IRunnableWithProgress() { >+ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { >+ monitor.beginTask("Preparing image for preview...", 1); >+ ((ImageAttachment) attachment).ensureImageFileWasCreated(); >+ monitor.worked(1); >+ monitor.done(); >+ } >+ }); >+ } catch (InvocationTargetException e) { >+ createErrorPreview(composite, "Could not create image for preview"); >+ return; >+ } catch (InterruptedException e) { >+ createErrorPreview(composite, "Could not create image for preview"); >+ return; >+ } >+ } >+ > if (InputAttachmentSourcePage.CLIPBOARD_LABEL.equals(attachment.getFilePath())) { > createTextPreview(composite, ((NewAttachmentWizard) getWizard()).getClipboardContents()); > } else if (PreviewAttachmentPage.isTextAttachment(attachment.getContentType())) { >Index: src/org/eclipse/mylyn/internal/tasks/ui/wizards/ScreenshotAttachmentPage.java >=================================================================== >RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/wizards/ScreenshotAttachmentPage.java,v >retrieving revision 1.4 >diff -u -r1.4 ScreenshotAttachmentPage.java >--- src/org/eclipse/mylyn/internal/tasks/ui/wizards/ScreenshotAttachmentPage.java 16 Nov 2007 06:24:49 -0000 1.4 >+++ src/org/eclipse/mylyn/internal/tasks/ui/wizards/ScreenshotAttachmentPage.java 20 Feb 2008 18:39:42 -0000 >@@ -15,14 +15,20 @@ > import java.util.Map; > import java.util.Set; > >+import org.eclipse.jface.action.Action; >+import org.eclipse.jface.action.ActionContributionItem; >+import org.eclipse.jface.action.IAction; >+import org.eclipse.jface.action.Separator; >+import org.eclipse.jface.action.ToolBarManager; > import org.eclipse.jface.layout.GridDataFactory; >+import org.eclipse.jface.resource.ImageDescriptor; > import org.eclipse.jface.wizard.IWizardPage; > import org.eclipse.jface.wizard.WizardPage; >-import org.eclipse.mylyn.internal.tasks.core.LocalAttachment; > import org.eclipse.mylyn.internal.tasks.ui.TaskListColorsAndFonts; > import org.eclipse.mylyn.internal.tasks.ui.TasksUiImages; > import org.eclipse.swt.SWT; > import org.eclipse.swt.custom.ScrolledComposite; >+import org.eclipse.swt.custom.ViewForm; > import org.eclipse.swt.events.ControlAdapter; > import org.eclipse.swt.events.ControlEvent; > import org.eclipse.swt.events.MouseAdapter; >@@ -30,46 +36,60 @@ > import org.eclipse.swt.events.MouseMoveListener; > import org.eclipse.swt.events.PaintEvent; > import org.eclipse.swt.events.PaintListener; >-import org.eclipse.swt.events.SelectionAdapter; >-import org.eclipse.swt.events.SelectionEvent; >+import org.eclipse.swt.graphics.Color; > import org.eclipse.swt.graphics.Cursor; > import org.eclipse.swt.graphics.GC; > import org.eclipse.swt.graphics.Image; > import org.eclipse.swt.graphics.Point; >+import org.eclipse.swt.graphics.RGB; > import org.eclipse.swt.graphics.Rectangle; > import org.eclipse.swt.graphics.Region; >-import org.eclipse.swt.layout.GridLayout; >-import org.eclipse.swt.widgets.Button; > import org.eclipse.swt.widgets.Canvas; > import org.eclipse.swt.widgets.Composite; > import org.eclipse.swt.widgets.Display; >+import org.eclipse.swt.widgets.Event; > import org.eclipse.swt.widgets.Shell; >+import org.eclipse.swt.widgets.ToolItem; > > /** > * A wizard page to create a screenshot from the display. >- * <p> >- * Note: this class uses {@link GC#setXORMode(boolean)} which is deprecated because of lack of Mac implementation >- * (bug#50228). The strategy to make it work on platforms XOR is implemented and still have a good looking in platforms >- * where it is not implemented, is to draw each line 2 times: first using a WHITE foreground followed by the same draw >- * using a BLACK foreground. On platforms where XOR is implemented, the second draw will have no effect, since anything >- * XOR black results in noop. On platforms where XOR is NOT implemented, the {@link GC#setXORMode(boolean)} is a noop, >- * so the end result will be a black line. > * > * @author Balazs Brinkus (bug 160572) > * @author Mik Kersten > * @author Willian Mitsuda > */ >-public class ScreenshotAttachmentPage extends WizardPage { >+public class ScreenshotAttachmentPage extends WizardPage implements IImageCreator { > >- private ScreenshotAttachmentPage page; >+ private IAction captureAction; > >- private LocalAttachment attachment; >+ private IAction fitAction; > >- private Button captureButton; >+ private IAction cropAction; > >- private Button fitButton; >+ private IAction markAction; > >- private Image screenshotImage; >+ private IAction colorAction; >+ >+ private Image colorIcon; >+ >+ private Color markColor; >+ >+ private IAction clearAction; >+ >+ /** >+ * Original screenshot image; used for backup purposes >+ */ >+ private Image originalImage; >+ >+ /** >+ * Copy of {@link #originalImage original} image; all drawing operations are done here; base for the result image >+ */ >+ private Image workImage; >+ >+ /** >+ * Used to draw into {@link #workImage} >+ */ >+ private GC workImageGC; > > private Canvas canvas; > >@@ -87,13 +107,14 @@ > private Rectangle originalSelection; > > /** >- * Temporary storage for selection start point or selection resizing initial reference point; this value is >- * normalized to real image coordinates, no matter the zoom level (see {@link #scaleFactor}) >+ * Temporary storage for selection start point, selection resizing initial reference point or previous mark point >+ * (it depends on current tool); this value is normalized to real image coordinates, no matter the zoom level (see >+ * {@link #scaleFactor}) > */ > private Point startPoint; > > /** >- * What sides I'm resizing when doing an selection {@link Action#RESIZING_SELECTION resize} >+ * What sides I'm resizing when doing an selection {@link EditorAction#RESIZING_SELECTION resize} > */ > private Set<SelectionSide> resizableSides = EnumSet.noneOf(SelectionSide.class); > >@@ -110,48 +131,56 @@ > /** > * Available actions for the screenshot editor > */ >- private static enum Action { >+ private static enum EditorAction { > >- IDLE, SELECTING, RESIZING_SELECTION, MOVING_SELECTION; >+ CROPPING, SELECTING, RESIZING_SELECTION, MOVING_SELECTION, MARKING; > > }; > > /** > * What am I doing now? > */ >- private Action currentAction = Action.IDLE; >+ private EditorAction currentAction = EditorAction.CROPPING; > >- protected ScreenshotAttachmentPage(LocalAttachment attachment) { >+ protected ScreenshotAttachmentPage() { > super("ScreenShotAttachment"); > setTitle("Capture Screenshot"); >- setDescription("After capturing, drag the mouse to crop. This window will not be captured. " >+ setDescription("After capturing, you can crop the image and make drawings on it. This window will not be captured. " > + "Note that you can continue to interact with the workbench in order to set up the screenshot."); >- this.attachment = attachment; >- this.page = this; > } > > public void createControl(Composite parent) { >- >- Composite composite = new Composite(parent, SWT.NONE); >- composite.setLayout(new GridLayout()); >- setControl(composite); >+ ViewForm vf = new ViewForm(parent, SWT.BORDER | SWT.FLAT); >+ vf.horizontalSpacing = 0; >+ vf.verticalSpacing = 0; >+ setControl(vf); >+ vf.setLayoutData(GridDataFactory.fillDefaults().create()); > > allocateCursors(); > >- Composite buttonsComposite = new Composite(composite, SWT.NONE); >- buttonsComposite.setLayout(new GridLayout(3, false)); >- captureButton = new Button(buttonsComposite, SWT.PUSH); >- captureButton.setText("Capture Desktop"); >- captureButton.setImage(TasksUiImages.getImage(TasksUiImages.IMAGE_CAPTURE)); >- captureButton.addSelectionListener(new SelectionAdapter() { >+ // TODO: need disabled versions of all toolbar icons >+ ToolBarManager tbm = new ToolBarManager(SWT.FLAT | SWT.HORIZONTAL | SWT.RIGHT); >+ captureAction = new Action("&Capture Desktop", IAction.AS_PUSH_BUTTON) { >+ >+ private boolean isFirstCapture = true; > >- public void widgetSelected(SelectionEvent e) { >+ @Override >+ public void run() { > captureScreenshotContent(); >- page.setErrorMessage(null); >- fitButton.setEnabled(true); >+ setErrorMessage(null); >+ if (isFirstCapture) { >+ isFirstCapture = false; >+ fitAction.setEnabled(true); >+ cropAction.setEnabled(true); >+ cropAction.setChecked(true); >+ markAction.setEnabled(true); >+ clearAction.setEnabled(false); >+ } > } > >- }); >+ }; >+ captureAction.setToolTipText("Capture Desktop"); >+ captureAction.setImageDescriptor(ImageDescriptor.createFromImage(TasksUiImages.getImage(TasksUiImages.IMAGE_CAPTURE))); > > // captureDelayedButton = new Button(buttonsComposite, SWT.PUSH); > // final String captureIn = "Capture in "; >@@ -186,54 +215,118 @@ > // } > // }); > >- fitButton = new Button(buttonsComposite, SWT.TOGGLE); >- fitButton.setText("Fit Image"); >- fitButton.setImage(TasksUiImages.getImage(TasksUiImages.IMAGE_FIT)); >- fitButton.addSelectionListener(new SelectionAdapter() { >- >- public void widgetSelected(SelectionEvent e) { >+ fitAction = new Action("", IAction.AS_CHECK_BOX) { >+ @Override >+ public void run() { > refreshCanvasSize(); > } >+ }; >+ fitAction.setToolTipText("Fit Image"); >+ fitAction.setText("&Fit Image"); >+ fitAction.setImageDescriptor(ImageDescriptor.createFromImage(TasksUiImages.getImage(TasksUiImages.IMAGE_FIT))); >+ fitAction.setChecked(true); >+ fitAction.setEnabled(false); > >- }); >- fitButton.setSelection(true); >- fitButton.setEnabled(false); >+ cropAction = new Action("C&rop", IAction.AS_RADIO_BUTTON) { >+ @Override >+ public void run() { >+ currentAction = EditorAction.CROPPING; >+ cropAction.setChecked(true); >+ markAction.setChecked(false); >+ colorAction.setEnabled(false); >+ canvas.redraw(); >+ } >+ }; >+ cropAction.setToolTipText("Crop"); >+ cropAction.setImageDescriptor(ImageDescriptor.createFromFile(getClass(), "crop.png")); >+ cropAction.setEnabled(false); >+ >+ markAction = new Action("&Annotate", IAction.AS_RADIO_BUTTON) { >+ @Override >+ public void run() { >+ currentAction = EditorAction.MARKING; >+ cropAction.setChecked(false); >+ markAction.setChecked(true); >+ colorAction.setEnabled(true); >+ canvas.redraw(); >+ } >+ }; >+ markAction.setToolTipText("Draw annotations on screenshot image"); >+ markAction.setImageDescriptor(ImageDescriptor.createFromFile(getClass(), "mark.gif")); >+ markAction.setDisabledImageDescriptor(ImageDescriptor.createFromFile(getClass(), "mark_disabled.gif")); >+ markAction.setEnabled(false); >+ >+ colorAction = new Action("", IAction.AS_DROP_DOWN_MENU) { >+ @Override >+ public void runWithEvent(final Event e) { >+ final ColorSelectionWindow colorWindow = new ColorSelectionWindow(getControl().getShell()) { >+ >+ @Override >+ protected Point getInitialLocation(Point initialSize) { >+ ToolItem toolItem = (ToolItem) e.widget; >+ Rectangle itemBounds = toolItem.getBounds(); >+ Point location = toolItem.getParent().toDisplay(itemBounds.x + itemBounds.width, >+ itemBounds.y + itemBounds.height); >+ location.x -= initialSize.x; >+ return location; >+ } >+ >+ }; >+ colorWindow.setBlockOnOpen(true); >+ colorWindow.open(); >+ RGB color = colorWindow.getSelectedRGB(); >+ if (color != null) { >+ setMarkColor(color); >+ } >+ } >+ }; >+ colorAction.setToolTipText("Change pen color"); >+ colorIcon = new Image(getShell().getDisplay(), 16, 16); >+ setMarkColor(new RGB(255, 85, 85)); >+ colorAction.setEnabled(false); > >- scrolledComposite = new ScrolledComposite(composite, SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER); >- scrolledComposite.setLayoutData(GridDataFactory.fillDefaults() >- .align(SWT.FILL, SWT.FILL) >- .grab(true, true) >- .create()); >+ clearAction = new Action("C&lear Annotations", IAction.AS_PUSH_BUTTON) { >+ @Override >+ public void run() { >+ clearAction.setEnabled(false); >+ workImageGC.drawImage(originalImage, 0, 0); >+ canvas.redraw(); >+ markAttachmentDirty(); >+ } >+ }; >+ clearAction.setToolTipText("Clear all annotations made on screenshot image"); >+ clearAction.setImageDescriptor(ImageDescriptor.createFromFile(getClass(), "erase.png")); >+ clearAction.setEnabled(false); >+ >+ tbm.add(createAndConfigureCI(captureAction)); >+ tbm.add(createAndConfigureCI(fitAction)); >+ tbm.add(new Separator()); >+ tbm.add(createAndConfigureCI(cropAction)); >+ tbm.add(createAndConfigureCI(markAction)); >+ tbm.add(createAndConfigureCI(colorAction)); >+ tbm.add(new Separator()); >+ tbm.add(createAndConfigureCI(clearAction)); > >+ scrolledComposite = new ScrolledComposite(vf, SWT.V_SCROLL | SWT.H_SCROLL); > canvas = new Canvas(scrolledComposite, SWT.DOUBLE_BUFFERED); > scrolledComposite.setContent(canvas); > canvas.addPaintListener(new PaintListener() { > > public void paintControl(PaintEvent e) { >- if (screenshotImage != null) { >- Rectangle imageBounds = screenshotImage.getBounds(); >+ if (workImage != null) { >+ Rectangle imageBounds = workImage.getBounds(); > Rectangle canvasBounds = canvas.getClientArea(); > >- if (fitButton.getSelection()) { >- e.gc.drawImage(screenshotImage, 0, 0, imageBounds.width, imageBounds.height, 0, 0, >+ if (fitAction.isChecked()) { >+ e.gc.drawImage(workImage, 0, 0, imageBounds.width, imageBounds.height, 0, 0, > canvasBounds.width, canvasBounds.height); > } else { >- e.gc.drawImage(screenshotImage, 0, 0); >- } >- >- if (currentAction == Action.IDLE) { >- if (currentSelection != null) { >- drawSelection(e.gc); >- } >- } else if (currentAction == Action.SELECTING || currentAction == Action.RESIZING_SELECTION >- || currentAction == Action.MOVING_SELECTION) { >- if (currentSelection != null) { >- drawSelectionPreview(e.gc); >- } >+ e.gc.drawImage(workImage, 0, 0); > } >+ drawSelection(e.gc); > } else { > // page.setErrorMessage("Screenshot required"); >- fitButton.setEnabled(false); >+ fitAction.setEnabled(false); > } > } > }); >@@ -241,17 +334,51 @@ > scrolledComposite.addControlListener(new ControlAdapter() { > @Override > public void controlResized(ControlEvent e) { >- if (fitButton.getSelection()) { >+ if (fitAction.isChecked()) { > refreshCanvasSize(); > } > } > }); > >+ vf.setTopLeft(tbm.createControl(vf)); >+ vf.setContent(scrolledComposite); > registerMouseListeners(); > } > >+ private ActionContributionItem createAndConfigureCI(IAction action) { >+ ActionContributionItem ci = new ActionContributionItem(action); >+ ci.setMode(ActionContributionItem.MODE_FORCE_TEXT); >+ return ci; >+ } >+ >+ private void setMarkColor(RGB color) { >+ if (markColor != null) { >+ markColor.dispose(); >+ } >+ markColor = new Color(getShell().getDisplay(), color); >+ if (workImageGC != null) { >+ workImageGC.setForeground(markColor); >+ } >+ >+ GC colorGC = new GC(colorIcon); >+ colorGC.setBackground(markColor); >+ colorGC.fillRectangle(0, 0, 16, 16); >+ colorGC.drawRectangle(0, 0, 15, 15); >+ colorGC.dispose(); >+ >+ colorAction.setImageDescriptor(ImageDescriptor.createFromImage(colorIcon)); >+ } >+ > @Override > public void dispose() { >+ disposeImageResources(); >+ if (markColor != null) { >+ markColor.dispose(); >+ } >+ if (colorIcon != null) { >+ colorIcon.dispose(); >+ } >+ > canvas.setCursor(null); > for (Cursor cursor : cursors.values()) { > cursor.dispose(); >@@ -259,8 +386,22 @@ > super.dispose(); > } > >+ private void disposeImageResources() { >+ if (originalImage != null) { >+ originalImage.dispose(); >+ } >+ if (workImageGC != null) { >+ workImageGC.dispose(); >+ } >+ if (workImage != null) { >+ workImage.dispose(); >+ } >+ } >+ >+ private static final int CURSOR_MARK_TOOL = -1; >+ > private void allocateCursors() { >- Display display = Display.getCurrent(); >+ Display display = getShell().getDisplay(); > cursors.put(SWT.CURSOR_ARROW, new Cursor(display, SWT.CURSOR_ARROW)); > cursors.put(SWT.CURSOR_SIZEALL, new Cursor(display, SWT.CURSOR_SIZEALL)); > cursors.put(SWT.CURSOR_SIZENWSE, new Cursor(display, SWT.CURSOR_SIZENWSE)); >@@ -268,6 +409,9 @@ > cursors.put(SWT.CURSOR_SIZENS, new Cursor(display, SWT.CURSOR_SIZENS)); > cursors.put(SWT.CURSOR_SIZEWE, new Cursor(display, SWT.CURSOR_SIZEWE)); > cursors.put(SWT.CURSOR_CROSS, new Cursor(display, SWT.CURSOR_CROSS)); >+ >+ // TODO: allocate custom cursor for "mark" tool >+ cursors.put(CURSOR_MARK_TOOL, new Cursor(display, SWT.CURSOR_HAND)); > } > > private Rectangle getScaledSelection() { >@@ -278,25 +422,21 @@ > int y = (int) Math.round(currentSelection.y * scaleFactor); > int right = (int) Math.round((currentSelection.x + currentSelection.width) * scaleFactor); > int bottom = (int) Math.round((currentSelection.y + currentSelection.height) * scaleFactor); >- int width = Math.min(right, (int) Math.round((screenshotImage.getBounds().width - 1) * scaleFactor)) - x; >- int height = Math.min(bottom, (int) Math.round((screenshotImage.getBounds().height - 1) * scaleFactor)) - y; >+ int width = Math.min(right, (int) Math.round((workImage.getBounds().width - 1) * scaleFactor)) - x; >+ int height = Math.min(bottom, (int) Math.round((workImage.getBounds().height - 1) * scaleFactor)) - y; > return new Rectangle(x, y, width, height); > } > > @Override > public boolean isPageComplete() { >- if (screenshotImage == null) >- return false; >- return true; >+ return workImage != null; > } > > @Override > public IWizardPage getNextPage() { > NewAttachmentPage page = (NewAttachmentPage) getWizard().getPage("AttachmentDetails"); >- attachment.setContentType("image/jpeg"); > page.setFilePath(InputAttachmentSourcePage.SCREENSHOT_LABEL); > page.setContentType(); >- getCropScreenshot(); > return page; > } > >@@ -306,9 +446,8 @@ > } > > private void captureScreenshotContent() { >- >- final Display display = Display.getDefault(); >- final Shell wizardShell = getWizard().getContainer().getShell(); >+ Display display = getShell().getDisplay(); >+ Shell wizardShell = getWizard().getContainer().getShell(); > wizardShell.setVisible(false); > > // NOTE: need a wait since the shell can take time to disappear (e.g. fade on Vista) >@@ -318,24 +457,26 @@ > // ignore > } > >- display.asyncExec(new Runnable() { >- public void run() { >- Rectangle displayBounds = display.getBounds(); >- screenshotImage = new Image(display, displayBounds); >+ disposeImageResources(); >+ Rectangle displayBounds = display.getBounds(); >+ originalImage = new Image(display, displayBounds); >+ workImage = new Image(display, displayBounds); >+ >+ GC gc = new GC(display); >+ gc.copyArea(originalImage, 0, 0); >+ gc.copyArea(workImage, 0, 0); >+ gc.dispose(); > >- GC gc = new GC(display); >- gc.copyArea(screenshotImage, 0, 0); >- gc.dispose(); >+ workImageGC = new GC(workImage); >+ workImageGC.setForeground(markColor); >+ workImageGC.setLineWidth(4); >+ workImageGC.setLineCap(SWT.CAP_ROUND); > >- clearSelection(); >- refreshCanvasSize(); >+ clearSelection(); >+ refreshCanvasSize(); > >- wizardShell.setVisible(true); >- if (screenshotImage != null) { >- setPageComplete(true); >- } >- } >- }); >+ wizardShell.setVisible(true); >+ setPageComplete(true); > } > > /** >@@ -352,7 +493,7 @@ > currentSelection = new Rectangle(startX, startY, width, height); > > // Decreases 1 pixel size from original image because Rectangle.intersect() consider them as right-bottom limit >- Rectangle imageBounds = screenshotImage.getBounds(); >+ Rectangle imageBounds = workImage.getBounds(); > imageBounds.width--; > imageBounds.height--; > currentSelection.intersect(imageBounds); >@@ -363,12 +504,11 @@ > * level is changed > */ > private void setUpGrabPoints() { >+ grabPoints.clear(); > if (currentSelection == null) { > return; > } > >- canvas.setCursor(null); >- grabPoints.clear(); > Rectangle scaledSelection = getScaledSelection(); > grabPoints.add(GrabPoint.createGrabPoint(scaledSelection.x, scaledSelection.y, SWT.CURSOR_SIZENWSE, EnumSet.of( > SelectionSide.LEFT, SelectionSide.TOP))); >@@ -393,7 +533,7 @@ > originalSelection.height); > int deltaX = x - startPoint.x; > int deltaY = y - startPoint.y; >- Rectangle imageBounds = screenshotImage.getBounds(); >+ Rectangle imageBounds = workImage.getBounds(); > > // Check current selection limits > if (resizableSides.contains(SelectionSide.LEFT)) { >@@ -436,6 +576,8 @@ > if (resizableSides.contains(SelectionSide.BOTTOM)) { > currentSelection.height += deltaY; > } >+ >+ setUpGrabPoints(); > } > > private void refreshSelectionPosition(int x, int y) { >@@ -447,7 +589,7 @@ > if (newY < 0) { > newY = 0; > } >- Rectangle imageBounds = screenshotImage.getBounds(); >+ Rectangle imageBounds = workImage.getBounds(); > if (newX + originalSelection.width - 1 > imageBounds.width) { > newX = imageBounds.width - originalSelection.width; > } >@@ -455,6 +597,8 @@ > newY = imageBounds.height - originalSelection.height; > } > currentSelection = new Rectangle(newX, newY, originalSelection.width, originalSelection.height); >+ >+ setUpGrabPoints(); > } > > private void registerMouseListeners() { >@@ -464,17 +608,19 @@ > * If a selection is in course, moving the mouse around refreshes the selection rectangle > */ > public void mouseMove(MouseEvent e) { >- if (currentAction == Action.SELECTING) { >- // Selection in course >- refreshCurrentSelection((int) Math.round(e.x / scaleFactor), (int) Math.round(e.y / scaleFactor)); >+ int scaledX = (int) Math.round(e.x / scaleFactor); >+ int scaledY = (int) Math.round(e.y / scaleFactor); >+ >+ if (currentAction == EditorAction.SELECTING) { >+ refreshCurrentSelection(scaledX, scaledY); > canvas.redraw(); >- } else if (currentAction == Action.RESIZING_SELECTION) { >- refreshSelectionResize((int) Math.round(e.x / scaleFactor), (int) Math.round(e.y / scaleFactor)); >+ } else if (currentAction == EditorAction.RESIZING_SELECTION) { >+ refreshSelectionResize(scaledX, scaledY); > canvas.redraw(); >- } else if (currentAction == Action.MOVING_SELECTION) { >- refreshSelectionPosition((int) Math.round(e.x / scaleFactor), (int) Math.round(e.y / scaleFactor)); >+ } else if (currentAction == EditorAction.MOVING_SELECTION) { >+ refreshSelectionPosition(scaledX, scaledY); > canvas.redraw(); >- } else if (currentAction == Action.IDLE && currentSelection != null) { >+ } else if (currentAction == EditorAction.CROPPING && currentSelection != null) { > boolean cursorSet = false; > > // No selection in course, but have something selected; first test if I'm hovering some grab point >@@ -491,8 +637,18 @@ > canvas.setCursor(cursors.get(SWT.CURSOR_SIZEALL)); > cursorSet = true; > } >- if (!cursorSet && canvas.getCursor() != null) { >- canvas.setCursor(null); >+ >+ // If I'm out, the default cursor for cropping mode is cross >+ Cursor crossCursor = cursors.get(SWT.CURSOR_CROSS); >+ if (!cursorSet && canvas.getCursor() != crossCursor) { >+ canvas.setCursor(crossCursor); >+ } >+ } else if (currentAction == EditorAction.MARKING) { >+ drawMarkLine(scaledX, scaledY); >+ >+ Cursor markCursor = cursors.get(CURSOR_MARK_TOOL); >+ if (canvas.getCursor() != markCursor) { >+ canvas.setCursor(markCursor); > } > } > } >@@ -502,21 +658,19 @@ > canvas.addMouseListener(new MouseAdapter() { > > /** >- * Releasing the mouse button ends the selection; compute the selection rectangle and redraw the cropped >- * image >+ * Releasing the mouse button ends the selection or a drawing; compute the selection rectangle and redraw >+ * the cropped image > */ > public void mouseUp(MouseEvent e) { >- if (currentAction == Action.SELECTING || currentAction == Action.RESIZING_SELECTION >- || currentAction == Action.MOVING_SELECTION) { >- canvas.setCursor(cursors.get(SWT.CURSOR_ARROW)); >- >+ if (currentAction == EditorAction.SELECTING || currentAction == EditorAction.RESIZING_SELECTION >+ || currentAction == EditorAction.MOVING_SELECTION) { > int scaledX = (int) Math.round(e.x / scaleFactor); > int scaledY = (int) Math.round(e.y / scaleFactor); >- if (currentAction == Action.SELECTING) { >+ if (currentAction == EditorAction.SELECTING) { > refreshCurrentSelection(scaledX, scaledY); >- } else if (currentAction == Action.RESIZING_SELECTION) { >+ } else if (currentAction == EditorAction.RESIZING_SELECTION) { > refreshSelectionResize(scaledX, scaledY); >- } else if (currentAction == Action.MOVING_SELECTION) { >+ } else if (currentAction == EditorAction.MOVING_SELECTION) { > refreshSelectionPosition(scaledX, scaledY); > } > if (currentSelection.width == 0 && currentSelection.height == 0) { >@@ -524,17 +678,29 @@ > } > setUpGrabPoints(); > startPoint = null; >- currentAction = Action.IDLE; >+ currentAction = EditorAction.CROPPING; > > canvas.redraw(); >+ markAttachmentDirty(); >+ } else if (currentAction == EditorAction.MARKING) { >+ startPoint = null; >+ markAttachmentDirty(); > } > } > > /** >- * Pressing mouse button starts a selection; normalizes and marks the start point >+ * Pressing mouse button starts a selection or a drawing; normalizes and marks the start point > */ > public void mouseDown(MouseEvent e) { >- if (currentAction != Action.IDLE) { >+ int scaledX = (int) (e.x / scaleFactor); >+ int scaledY = (int) (e.y / scaleFactor); >+ >+ if (currentAction == EditorAction.MARKING) { >+ startPoint = new Point(scaledX, scaledY); >+ drawMarkLine(scaledX, scaledY); >+ canvas.setCursor(cursors.get(CURSOR_MARK_TOOL)); >+ return; >+ } else if (currentAction != EditorAction.CROPPING) { > return; > } > >@@ -543,9 +709,9 @@ > for (GrabPoint point : grabPoints) { > if (point.grabArea.contains(e.x, e.y)) { > originalSelection = currentSelection; >- currentAction = Action.RESIZING_SELECTION; >+ currentAction = EditorAction.RESIZING_SELECTION; > resizableSides = point.resizableSides; >- startPoint = new Point((int) (e.x / scaleFactor), (int) (e.y / scaleFactor)); >+ startPoint = new Point(scaledX, scaledY); > canvas.redraw(); > return; > } >@@ -553,20 +719,20 @@ > } > > // Check if I could move the selection >- if (currentSelection != null >- && currentSelection.contains((int) (e.x / scaleFactor), (int) (e.y / scaleFactor))) { >+ if (currentSelection != null && currentSelection.contains(scaledX, scaledY)) { > originalSelection = currentSelection; >- currentAction = Action.MOVING_SELECTION; >- startPoint = new Point((int) (e.x / scaleFactor), (int) (e.y / scaleFactor)); >+ currentAction = EditorAction.MOVING_SELECTION; >+ startPoint = new Point(scaledX, scaledY); > canvas.redraw(); > return; > } > > // Do a simple selection > canvas.setCursor(cursors.get(SWT.CURSOR_CROSS)); >- currentAction = Action.SELECTING; >+ currentAction = EditorAction.SELECTING; > currentSelection = null; >- startPoint = new Point((int) (e.x / scaleFactor), (int) (e.y / scaleFactor)); >+ startPoint = new Point(scaledX, scaledY); >+ setUpGrabPoints(); > canvas.redraw(); > } > >@@ -577,13 +743,14 @@ > private void clearSelection() { > currentSelection = null; > startPoint = null; >+ markAttachmentDirty(); > } > > /** > * Recalculates image canvas size based on "fit on canvas" setting, set up the grab points, and redraws > * <p> >- * This method should be called whenever the {@link #screenshotImage image} <strong>visible</strong> size is >- * changed, which can happen when: >+ * This method should be called whenever the {@link #workImage image} <strong>visible</strong> size is changed, >+ * which can happen when: > * <p> > * <ul> > * <li>The "Fit Image" setting is changed, so the image zoom level changes >@@ -595,15 +762,15 @@ > * Calling this method under other circumstances may lead to strange behavior in the scrolled composite > */ > private void refreshCanvasSize() { >- if (fitButton.getSelection()) { >+ if (fitAction.isChecked()) { > // This little hack is necessary to get the client area without scrollbars; > // they'll be automatically restored if necessary after Canvas.setBounds() > scrolledComposite.getHorizontalBar().setVisible(false); > scrolledComposite.getVerticalBar().setVisible(false); > > Rectangle bounds = scrolledComposite.getClientArea(); >- if (screenshotImage != null) { >- Rectangle imageBounds = screenshotImage.getBounds(); >+ if (workImage != null) { >+ Rectangle imageBounds = workImage.getBounds(); > if (imageBounds.width > bounds.width || imageBounds.height > bounds.height) { > double xRatio = (double) bounds.width / imageBounds.width; > double yRatio = (double) bounds.height / imageBounds.height; >@@ -616,8 +783,8 @@ > } else { > scaleFactor = 1.0; > Rectangle bounds = scrolledComposite.getClientArea(); >- if (screenshotImage != null) { >- Rectangle imageBounds = screenshotImage.getBounds(); >+ if (workImage != null) { >+ Rectangle imageBounds = workImage.getBounds(); > bounds.width = imageBounds.width; > bounds.height = imageBounds.height; > } >@@ -628,25 +795,12 @@ > } > > /** >- * Decorates the screenshot canvas with the selection rectangle; this is done while still selecting, so it does not >- * have all adornments of a {@link #drawSelection(GC) finished} selection >- */ >- @SuppressWarnings("deprecation") >- private void drawSelectionPreview(GC gc) { >- gc.setLineDash(new int[] { 4 }); >- gc.setXORMode(true); >- gc.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_WHITE)); >- gc.drawRectangle(getScaledSelection()); >- gc.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK)); >- gc.drawRectangle(getScaledSelection()); >- gc.setXORMode(false); >- gc.setLineStyle(SWT.LINE_SOLID); >- } >- >- /** > * Decorates the screenshot canvas with the selection rectangle, resize grab points and other adornments > */ > private void drawSelection(GC gc) { >+ if (currentSelection == null) { >+ return; >+ } > Rectangle scaledSelection = getScaledSelection(); > > // Draw shadow >@@ -666,18 +820,31 @@ > > // Draw selection rectangle > gc.setLineStyle(SWT.LINE_SOLID); >- gc.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_DARK_GRAY)); >+ gc.setForeground(getShell().getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY)); > gc.drawRectangle(scaledSelection); > > // Draw grab points >- gc.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE)); >- gc.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_BLACK)); >+ gc.setBackground(getShell().getDisplay().getSystemColor(SWT.COLOR_WHITE)); >+ gc.setForeground(getShell().getDisplay().getSystemColor(SWT.COLOR_BLACK)); > for (GrabPoint point : grabPoints) { > gc.fillRectangle(point.grabArea); > gc.drawRectangle(point.grabArea); > } > } > >+ /** >+ * Connects the previous mark point to the new reference point, by drawing a new line >+ */ >+ private void drawMarkLine(int x, int y) { >+ if (startPoint != null) { >+ clearAction.setEnabled(true); >+ workImageGC.drawLine(startPoint.x, startPoint.y, x, y); >+ startPoint.x = x; >+ startPoint.y = y; >+ canvas.redraw(); >+ } >+ } >+ > private static enum SelectionSide { > > LEFT, RIGHT, TOP, BOTTOM; >@@ -706,22 +873,31 @@ > > private List<GrabPoint> grabPoints = new ArrayList<GrabPoint>(8); > >- private Image getCropScreenshot() { >- if (currentSelection == null) { >- return screenshotImage; >+ /** >+ * Creates the final screenshot >+ * >+ * @return The final screenshot, with all markings, and cropped according to user settings; <strong>The caller is >+ * responsible for disposing the returned image</strong> >+ */ >+ public Image createImage() { >+ Image screenshot = new Image(getShell().getDisplay(), currentSelection != null ? currentSelection >+ : workImage.getBounds()); >+ >+ GC gc = new GC(screenshot); >+ if (currentSelection != null) { >+ gc.drawImage(workImage, currentSelection.x, currentSelection.y, currentSelection.width, >+ currentSelection.height, 0, 0, currentSelection.width, currentSelection.height); >+ } else { >+ gc.drawImage(workImage, 0, 0); > } >- >- Image image = new Image(Display.getDefault(), currentSelection); >- GC gc = new GC(image); >- gc.drawImage(screenshotImage, currentSelection.x, currentSelection.y, currentSelection.width, >- currentSelection.height, 0, 0, currentSelection.width, currentSelection.height); > gc.dispose(); > >- return image; >+ return screenshot; > } > >- public Image getScreenshotImage() { >- return getCropScreenshot(); >+ private void markAttachmentDirty() { >+ NewAttachmentWizard wizard = (NewAttachmentWizard) getWizard(); >+ ((ImageAttachment) wizard.getAttachment()).markDirty(); > } > > } >Index: src/org/eclipse/mylyn/internal/tasks/ui/wizards/ColorSelectionWindow.java >=================================================================== >RCS file: src/org/eclipse/mylyn/internal/tasks/ui/wizards/ColorSelectionWindow.java >diff -N src/org/eclipse/mylyn/internal/tasks/ui/wizards/ColorSelectionWindow.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/mylyn/internal/tasks/ui/wizards/ColorSelectionWindow.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,116 @@ >+/******************************************************************************* >+ * Copyright (c) 2004, 2007 Mylyn project committers and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ *******************************************************************************/ >+ >+package org.eclipse.mylyn.internal.tasks.ui.wizards; >+ >+import org.eclipse.jface.layout.GridDataFactory; >+import org.eclipse.jface.layout.GridLayoutFactory; >+import org.eclipse.jface.window.Window; >+import org.eclipse.swt.SWT; >+import org.eclipse.swt.events.MouseAdapter; >+import org.eclipse.swt.events.MouseEvent; >+import org.eclipse.swt.events.SelectionAdapter; >+import org.eclipse.swt.events.SelectionEvent; >+import org.eclipse.swt.events.ShellAdapter; >+import org.eclipse.swt.events.ShellEvent; >+import org.eclipse.swt.graphics.RGB; >+import org.eclipse.swt.widgets.Button; >+import org.eclipse.swt.widgets.Composite; >+import org.eclipse.swt.widgets.Control; >+import org.eclipse.swt.widgets.Shell; >+ >+/** >+ * Popup window for color selection >+ * >+ * @author Willian Mitsuda >+ */ >+public class ColorSelectionWindow extends Window { >+ >+ private ColorCanvas[] colors; >+ >+ public ColorSelectionWindow(Shell shell) { >+ super(shell); >+ setShellStyle(SWT.BORDER); >+ } >+ >+ @Override >+ protected void configureShell(Shell newShell) { >+ super.configureShell(newShell); >+ newShell.addShellListener(new ShellAdapter() { >+ >+ @Override >+ public void shellDeactivated(ShellEvent e) { >+ close(); >+ } >+ >+ }); >+ } >+ >+ @Override >+ protected Control createContents(Composite parent) { >+ Composite colorComposite = new Composite(parent, SWT.NONE); >+ colorComposite.setBackground(getShell().getDisplay().getSystemColor(SWT.COLOR_BLACK)); >+ colorComposite.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create()); >+ colorComposite.setLayout(GridLayoutFactory.fillDefaults().numColumns(8).spacing(1, 1).margins(1, 1).equalWidth( >+ true).create()); >+ >+ // EGA classic palette >+ colors = new ColorCanvas[16]; >+ colors[0] = createColorCanvas(colorComposite, new RGB(0, 0, 0)); >+ colors[1] = createColorCanvas(colorComposite, new RGB(0, 0, 170)); >+ colors[2] = createColorCanvas(colorComposite, new RGB(0, 170, 0)); >+ colors[3] = createColorCanvas(colorComposite, new RGB(0, 170, 170)); >+ colors[4] = createColorCanvas(colorComposite, new RGB(170, 0, 0)); >+ colors[5] = createColorCanvas(colorComposite, new RGB(170, 0, 170)); >+ colors[6] = createColorCanvas(colorComposite, new RGB(170, 85, 0)); >+ colors[7] = createColorCanvas(colorComposite, new RGB(170, 170, 170)); >+ colors[8] = createColorCanvas(colorComposite, new RGB(85, 85, 85)); >+ colors[9] = createColorCanvas(colorComposite, new RGB(85, 85, 255)); >+ colors[10] = createColorCanvas(colorComposite, new RGB(85, 255, 85)); >+ colors[11] = createColorCanvas(colorComposite, new RGB(85, 255, 255)); >+ colors[12] = createColorCanvas(colorComposite, new RGB(255, 85, 85)); >+ colors[13] = createColorCanvas(colorComposite, new RGB(255, 85, 255)); >+ colors[14] = createColorCanvas(colorComposite, new RGB(255, 255, 85)); >+ colors[15] = createColorCanvas(colorComposite, new RGB(255, 255, 255)); >+ >+ Button closeButton = new Button(parent, SWT.PUSH); >+ closeButton.setText("&Close"); >+ closeButton.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create()); >+ closeButton.addSelectionListener(new SelectionAdapter() { >+ >+ @Override >+ public void widgetSelected(SelectionEvent e) { >+ close(); >+ } >+ >+ }); >+ return parent; >+ } >+ >+ private ColorCanvas createColorCanvas(Composite parent, RGB rgb) { >+ final ColorCanvas canvas = new ColorCanvas(parent, SWT.NONE, rgb); >+ canvas.setLayoutData(GridDataFactory.fillDefaults().hint(16, 16).create()); >+ canvas.addMouseListener(new MouseAdapter() { >+ >+ @Override >+ public void mouseDown(MouseEvent e) { >+ selectedRGB = canvas.getRGB(); >+ close(); >+ } >+ >+ }); >+ return canvas; >+ } >+ >+ private RGB selectedRGB; >+ >+ public RGB getSelectedRGB() { >+ return selectedRGB; >+ } >+ >+} >Index: src/org/eclipse/mylyn/internal/tasks/ui/wizards/ImageAttachment.java >=================================================================== >RCS file: src/org/eclipse/mylyn/internal/tasks/ui/wizards/ImageAttachment.java >diff -N src/org/eclipse/mylyn/internal/tasks/ui/wizards/ImageAttachment.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/mylyn/internal/tasks/ui/wizards/ImageAttachment.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,90 @@ >+/******************************************************************************* >+ * Copyright (c) 2004, 2007 Mylyn project committers and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ *******************************************************************************/ >+ >+package org.eclipse.mylyn.internal.tasks.ui.wizards; >+ >+import java.io.File; >+ >+import org.eclipse.mylyn.internal.tasks.core.LocalAttachment; >+import org.eclipse.mylyn.tasks.ui.TasksUiPlugin; >+import org.eclipse.swt.SWT; >+import org.eclipse.swt.graphics.Image; >+import org.eclipse.swt.graphics.ImageData; >+import org.eclipse.swt.graphics.ImageLoader; >+ >+/** >+ * Represents a attachment created from a {@link Image}; handles lazy persistence into a {@link File} and image data >+ * change >+ * >+ * @author Willian Mitsuda >+ */ >+public class ImageAttachment extends LocalAttachment { >+ >+ private static final long serialVersionUID = 28264291629999181L; >+ >+ /** >+ * Provides the {@link Image} object that will be converted to desired file format, and then attached >+ */ >+ private IImageCreator imageCreator; >+ >+ public ImageAttachment(IImageCreator imageCreator) { >+ this.imageCreator = imageCreator; >+ } >+ >+ @Override >+ public void setContentType(String contentType) { >+ // Does not apply; actually always save as JPEG >+ // Will be implemented on bug#210179 >+ } >+ >+ @Override >+ public String getContentType() { >+ return "image/jpeg"; >+ } >+ >+ @Override >+ public String getFilename() { >+ return "screenshot.jpg"; >+ } >+ >+ private boolean dirty = true; >+ >+ public void markDirty() { >+ dirty = true; >+ } >+ >+ public void ensureImageFileWasCreated() { >+ if (!dirty) { >+ return; >+ } >+ >+ dirty = false; >+ createContents(); >+ } >+ >+ private void createContents() { >+ Image image = imageCreator.createImage(); >+ try { >+ String path = TasksUiPlugin.getDefault().getDefaultDataDirectory(); >+ ImageLoader loader = new ImageLoader(); >+ loader.data = new ImageData[] { image.getImageData() }; >+ String fileName = path + "/" + getFilename(); >+ loader.save(fileName, SWT.IMAGE_JPEG); >+ setFile(new File(fileName)); >+ setFilePath(fileName); >+ } finally { >+ image.dispose(); >+ } >+ } >+ >+ public void clearImageFile() { >+ String path = TasksUiPlugin.getDefault().getDefaultDataDirectory(); >+ new File(path + "/" + getFilename()).delete(); >+ } >+ >+} >Index: src/org/eclipse/mylyn/internal/tasks/ui/wizards/ColorCanvas.java >=================================================================== >RCS file: src/org/eclipse/mylyn/internal/tasks/ui/wizards/ColorCanvas.java >diff -N src/org/eclipse/mylyn/internal/tasks/ui/wizards/ColorCanvas.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/mylyn/internal/tasks/ui/wizards/ColorCanvas.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,49 @@ >+/******************************************************************************* >+ * Copyright (c) 2004, 2007 Mylyn project committers and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ *******************************************************************************/ >+ >+package org.eclipse.mylyn.internal.tasks.ui.wizards; >+ >+import org.eclipse.swt.events.DisposeEvent; >+import org.eclipse.swt.events.DisposeListener; >+import org.eclipse.swt.events.PaintEvent; >+import org.eclipse.swt.events.PaintListener; >+import org.eclipse.swt.graphics.Color; >+import org.eclipse.swt.graphics.RGB; >+import org.eclipse.swt.widgets.Canvas; >+import org.eclipse.swt.widgets.Composite; >+ >+/** >+ * A tiny control just for color display >+ * >+ * @author Willian Mitsuda >+ */ >+public class ColorCanvas extends Canvas { >+ >+ private Color color; >+ >+ public ColorCanvas(Composite parent, int style, RGB rgb) { >+ super(parent, style); >+ color = new Color(parent.getDisplay(), rgb); >+ addPaintListener(new PaintListener() { >+ public void paintControl(PaintEvent e) { >+ e.gc.setBackground(color); >+ e.gc.fillRectangle(getClientArea()); >+ } >+ }); >+ addDisposeListener(new DisposeListener() { >+ public void widgetDisposed(DisposeEvent e) { >+ color.dispose(); >+ } >+ }); >+ } >+ >+ public RGB getRGB() { >+ return color.getRGB(); >+ } >+ >+} >Index: src/org/eclipse/mylyn/internal/tasks/ui/wizards/IImageCreator.java >=================================================================== >RCS file: src/org/eclipse/mylyn/internal/tasks/ui/wizards/IImageCreator.java >diff -N src/org/eclipse/mylyn/internal/tasks/ui/wizards/IImageCreator.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/mylyn/internal/tasks/ui/wizards/IImageCreator.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,25 @@ >+/******************************************************************************* >+ * Copyright (c) 2004, 2007 Mylyn project committers and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ *******************************************************************************/ >+ >+package org.eclipse.mylyn.internal.tasks.ui.wizards; >+ >+import org.eclipse.swt.graphics.Image; >+ >+/** >+ * Something capable of creating {@link Image images} >+ * >+ * @author Willian Mitsuda >+ */ >+public interface IImageCreator { >+ >+ /** >+ * Creates a {@link Image} object it represents; the caller is responsible for disposing the returned {@link Image} >+ */ >+ public Image createImage(); >+ >+}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 195691
:
83155
|
83156
|
83160
|
83175
|
83176
|
88850
|
88853
|
88854
|
90227
|
90228
|
90286
|
90287
|
90454