1 /*******************************************************************************
2  * Copyright (c) 2000, 2014 IBM Corporation 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  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.jdt.internal.ui.refactoring;
15 
16 import java.util.HashMap;
17 import java.util.Map;
18 
19 import org.eclipse.swt.SWT;
20 import org.eclipse.swt.custom.StyledText;
21 import org.eclipse.swt.events.DisposeEvent;
22 import org.eclipse.swt.events.DisposeListener;
23 import org.eclipse.swt.graphics.Color;
24 import org.eclipse.swt.graphics.Image;
25 import org.eclipse.swt.graphics.RGB;
26 import org.eclipse.swt.widgets.Composite;
27 import org.eclipse.swt.widgets.Control;
28 import org.eclipse.swt.widgets.Display;
29 
30 import org.eclipse.core.runtime.IAdaptable;
31 
32 import org.eclipse.jface.dialogs.Dialog;
33 import org.eclipse.jface.preference.IPreferenceStore;
34 import org.eclipse.jface.preference.PreferenceConverter;
35 import org.eclipse.jface.resource.ImageDescriptor;
36 import org.eclipse.jface.resource.JFaceResources;
37 
38 import org.eclipse.jface.text.Document;
39 import org.eclipse.jface.text.IDocument;
40 import org.eclipse.jface.text.source.IVerticalRuler;
41 import org.eclipse.jface.text.source.SourceViewer;
42 import org.eclipse.jface.text.source.SourceViewerConfiguration;
43 
44 import org.eclipse.ui.model.IWorkbenchAdapter;
45 
46 import org.eclipse.ui.texteditor.AbstractTextEditor;
47 
48 import org.eclipse.ui.editors.text.EditorsUI;
49 
50 import org.eclipse.ltk.core.refactoring.Change;
51 import org.eclipse.ltk.ui.refactoring.ChangePreviewViewerInput;
52 import org.eclipse.ltk.ui.refactoring.IChangePreviewViewer;
53 
54 import org.eclipse.jdt.internal.corext.refactoring.nls.changes.CreateTextFileChange;
55 
56 import org.eclipse.jdt.ui.PreferenceConstants;
57 import org.eclipse.jdt.ui.text.JavaSourceViewerConfiguration;
58 import org.eclipse.jdt.ui.text.JavaTextTools;
59 
60 import org.eclipse.jdt.internal.ui.JavaPlugin;
61 import org.eclipse.jdt.internal.ui.propertiesfileeditor.IPropertiesFilePartitions;
62 import org.eclipse.jdt.internal.ui.propertiesfileeditor.PropertiesFileDocumentSetupParticipant;
63 import org.eclipse.jdt.internal.ui.propertiesfileeditor.PropertiesFileSourceViewerConfiguration;
64 import org.eclipse.jdt.internal.ui.util.ViewerPane;
65 
66 /**
67  * Change preview viewer for <code>CreateTextFileChange</code> objects.
68  */
69 public final class CreateTextFileChangePreviewViewer implements IChangePreviewViewer {
70 
71 	private static class CreateTextFilePreviewer extends ViewerPane {
72 
73 		private ImageDescriptor fDescriptor;
74 
75 		private Image fImage;
76 
CreateTextFilePreviewer(Composite parent, int style)77 		public CreateTextFilePreviewer(Composite parent, int style) {
78 			super(parent, style);
79 			addDisposeListener(new DisposeListener() {
80 				@Override
81 				public void widgetDisposed(DisposeEvent e) {
82 					disposeImage();
83 				}
84 			});
85 		}
86 
disposeImage()87 		/*package*/ void disposeImage() {
88 			if (fImage != null) {
89 				fImage.dispose();
90 			}
91 		}
92 
setImageDescriptor(ImageDescriptor imageDescriptor)93 		public void setImageDescriptor(ImageDescriptor imageDescriptor) {
94 			fDescriptor= imageDescriptor;
95 		}
96 
97 		@Override
setText(String text)98 		public void setText(String text) {
99 			super.setText(text);
100 			Image current= null;
101 			if (fDescriptor != null) {
102 				current= fImage;
103 				fImage= fDescriptor.createImage();
104 			} else {
105 				current= fImage;
106 				fImage= null;
107 			}
108 			setImage(fImage);
109 			if (current != null) {
110 				current.dispose();
111 			}
112 		}
113 
114 	}
115 
116 	private static class FileChangeSourceViewer extends SourceViewer {
117 
118 		private final Map<String, Color> customColors= new HashMap<>();
119 
FileChangeSourceViewer(Composite parent, IVerticalRuler ruler, int styles)120 		public FileChangeSourceViewer(Composite parent, IVerticalRuler ruler, int styles) {
121 			super(parent, ruler, styles);
122 			setColors();
123 			StyledText textWidget= getTextWidget();
124 			textWidget.setEditable(false);
125 			textWidget.setFont(JFaceResources.getFont(PreferenceConstants.EDITOR_TEXT_FONT));
126 		}
127 
128 		@Override
handleDispose()129 		protected void handleDispose() {
130 			for (Color color : customColors.values()) {
131 				if (color != null) {
132 					color.dispose();
133 				}
134 			}
135 			customColors.clear();
136 			super.handleDispose();
137 		}
138 
setColors()139 		private void setColors() {
140 			IPreferenceStore store= EditorsUI.getPreferenceStore();
141 			StyledText styledText= getTextWidget();
142 			setColor(styledText, store,
143 					AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND,
144 					store.getBoolean(
145 							AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND_SYSTEM_DEFAULT));
146 			setColor(styledText, store,
147 					AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND,
148 					store.getBoolean(
149 							AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT));
150 			setColor(styledText, store,
151 					AbstractTextEditor.PREFERENCE_COLOR_SELECTION_FOREGROUND,
152 					store.getBoolean(
153 							AbstractTextEditor.PREFERENCE_COLOR_SELECTION_FOREGROUND_SYSTEM_DEFAULT));
154 			setColor(styledText, store,
155 					AbstractTextEditor.PREFERENCE_COLOR_SELECTION_BACKGROUND,
156 					store.getBoolean(
157 							AbstractTextEditor.PREFERENCE_COLOR_SELECTION_BACKGROUND_SYSTEM_DEFAULT));
158 		}
159 
setColor(StyledText styledText, IPreferenceStore store, String key, boolean useDefault)160 		private void setColor(StyledText styledText, IPreferenceStore store,
161 				String key, boolean useDefault) {
162 			Color newColor= useDefault
163 					? null
164 					: createColor(styledText.getDisplay(), store, key);
165 			switch (key) {
166 				case AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND:
167 					styledText.setForeground(newColor);
168 					break;
169 				case AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND:
170 					styledText.setBackground(newColor);
171 					break;
172 				case AbstractTextEditor.PREFERENCE_COLOR_SELECTION_FOREGROUND:
173 					styledText.setSelectionForeground(newColor);
174 					break;
175 				case AbstractTextEditor.PREFERENCE_COLOR_SELECTION_BACKGROUND:
176 					styledText.setSelectionBackground(newColor);
177 					break;
178 				default:
179 					return;
180 			}
181 			Color oldColor= customColors.remove(key);
182 			if (oldColor != null) {
183 				oldColor.dispose();
184 			}
185 			customColors.put(key, newColor);
186 		}
187 
createColor(Display display, IPreferenceStore store, String key)188 		private static Color createColor(Display display, IPreferenceStore store,
189 				String key) {
190 			RGB rgb= null;
191 			if (store.contains(key)) {
192 				if (store.isDefault(key)) {
193 					rgb= PreferenceConverter.getDefaultColor(store, key);
194 				} else {
195 					rgb= PreferenceConverter.getColor(store, key);
196 				}
197 				if (rgb != null) {
198 					return new Color(display, rgb);
199 				}
200 			}
201 			return null;
202 		}
203 	}
204 
205 	private CreateTextFilePreviewer fPane;
206 
207 	private SourceViewer fSourceViewer;
208 
209 	@Override
createControl(Composite parent)210 	public void createControl(Composite parent) {
211 		fPane= new CreateTextFilePreviewer(parent, SWT.BORDER | SWT.FLAT);
212 		Dialog.applyDialogFont(fPane);
213 
214 		fSourceViewer= new FileChangeSourceViewer(fPane, null, SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI | SWT.FULL_SELECTION);
215 		fPane.setContent(fSourceViewer.getControl());
216 	}
217 
218 	@Override
getControl()219 	public Control getControl() {
220 		return fPane;
221 	}
222 
refresh()223 	public void refresh() {
224 		fSourceViewer.refresh();
225 	}
226 
227 
228 	@Override
setInput(ChangePreviewViewerInput input)229 	public void setInput(ChangePreviewViewerInput input) {
230 		Change change= input.getChange();
231 		if (change != null) {
232 			Object element= change.getModifiedElement();
233 			if (element instanceof IAdaptable) {
234 				IAdaptable adaptable= (IAdaptable) element;
235 				IWorkbenchAdapter workbenchAdapter= adaptable.getAdapter(IWorkbenchAdapter.class);
236 				if (workbenchAdapter != null) {
237 					fPane.setImageDescriptor(workbenchAdapter.getImageDescriptor(element));
238 				} else {
239 					fPane.setImageDescriptor(null);
240 				}
241 			} else {
242 				fPane.setImageDescriptor(null);
243 			}
244 		}
245 		if (!(change instanceof CreateTextFileChange)) {
246 			fSourceViewer.setInput(null);
247 			fPane.setText(""); //$NON-NLS-1$
248 			return;
249 		}
250 		CreateTextFileChange textFileChange= (CreateTextFileChange) change;
251 		fPane.setText(textFileChange.getName());
252 		IDocument document= new Document(textFileChange.getPreview());
253 		// This is a temporary work around until we get the
254 		// source viewer registry.
255 		fSourceViewer.unconfigure();
256 		String textType= textFileChange.getTextType();
257 		JavaTextTools textTools= JavaPlugin.getDefault().getJavaTextTools();
258 		IPreferenceStore store= JavaPlugin.getDefault().getCombinedPreferenceStore();
259 		boolean nomatch= false;
260 		if (textType != null) switch (textType) {
261 		case "java": //$NON-NLS-1$
262 			textTools.setupJavaDocumentPartitioner(document);
263 			fSourceViewer.configure(new JavaSourceViewerConfiguration(textTools.getColorManager(), store, null, null));
264 			fSourceViewer.getTextWidget().setOrientation(SWT.LEFT_TO_RIGHT);
265 			break;
266 		case "properties": //$NON-NLS-1$
267 			PropertiesFileDocumentSetupParticipant.setupDocument(document);
268 			fSourceViewer.configure(new PropertiesFileSourceViewerConfiguration(textTools.getColorManager(), store, null, IPropertiesFilePartitions.PROPERTIES_FILE_PARTITIONING));
269 			fSourceViewer.getTextWidget().setOrientation(SWT.LEFT_TO_RIGHT);
270 			break;
271 		default:
272 			nomatch= true;
273 			break;
274 		}
275 		if (nomatch) {
276 			fSourceViewer.configure(new SourceViewerConfiguration());
277 			fSourceViewer.getTextWidget().setOrientation(fSourceViewer.getTextWidget().getParent().getOrientation());
278 		}
279 		fSourceViewer.setInput(document);
280 	}
281 }
282