1 package sourceforge.org.qmc2.options.editor.ui;
2 
3 import java.io.File;
4 import java.util.Set;
5 
6 import org.eclipse.core.commands.ExecutionException;
7 import org.eclipse.core.commands.operations.DefaultOperationHistory;
8 import org.eclipse.core.commands.operations.IOperationHistory;
9 import org.eclipse.core.commands.operations.IUndoContext;
10 import org.eclipse.core.commands.operations.IUndoableOperation;
11 import org.eclipse.core.commands.operations.UndoContext;
12 import org.eclipse.core.runtime.NullProgressMonitor;
13 import org.eclipse.jface.action.IAction;
14 import org.eclipse.jface.action.IMenuListener;
15 import org.eclipse.jface.action.IMenuManager;
16 import org.eclipse.jface.action.MenuManager;
17 import org.eclipse.jface.dialogs.MessageDialog;
18 import org.eclipse.jface.viewers.ColumnViewerEditor;
19 import org.eclipse.jface.viewers.FocusCellOwnerDrawHighlighter;
20 import org.eclipse.jface.viewers.ISelectionChangedListener;
21 import org.eclipse.jface.viewers.SelectionChangedEvent;
22 import org.eclipse.jface.viewers.TreeViewer;
23 import org.eclipse.jface.viewers.TreeViewerColumn;
24 import org.eclipse.jface.viewers.TreeViewerEditor;
25 import org.eclipse.jface.viewers.TreeViewerFocusCellManager;
26 import org.eclipse.jface.window.ApplicationWindow;
27 import org.eclipse.swt.SWT;
28 import org.eclipse.swt.events.ModifyEvent;
29 import org.eclipse.swt.events.ModifyListener;
30 import org.eclipse.swt.events.SelectionAdapter;
31 import org.eclipse.swt.events.SelectionEvent;
32 import org.eclipse.swt.layout.GridData;
33 import org.eclipse.swt.layout.GridLayout;
34 import org.eclipse.swt.widgets.Button;
35 import org.eclipse.swt.widgets.Composite;
36 import org.eclipse.swt.widgets.FileDialog;
37 import org.eclipse.swt.widgets.Label;
38 import org.eclipse.swt.widgets.Menu;
39 import org.eclipse.swt.widgets.Text;
40 import org.eclipse.swt.widgets.TreeColumn;
41 
42 import sourceforge.org.qmc2.options.editor.model.QMC2TemplateFile;
43 import sourceforge.org.qmc2.options.editor.ui.actions.AddLanguageAction;
44 import sourceforge.org.qmc2.options.editor.ui.actions.AddOptionAction;
45 import sourceforge.org.qmc2.options.editor.ui.actions.AddSectionAction;
46 import sourceforge.org.qmc2.options.editor.ui.actions.RedoAction;
47 import sourceforge.org.qmc2.options.editor.ui.actions.RemoveSelectedItemsAction;
48 import sourceforge.org.qmc2.options.editor.ui.actions.UndoAction;
49 
50 public class QMC2Editor extends Composite {
51 
52 	private final TreeViewer viewer;
53 
54 	public static final String EDITOR_ID = "sourceforge.org.qmc2.options.editor";
55 
56 	private String selectedFile = null;
57 
58 	private QMC2TemplateFile templateFile = null;
59 
60 	private String filter = null;
61 
62 	private IOperationHistory operationHistory = new DefaultOperationHistory();
63 
64 	private IUndoContext undoContext = new UndoContext();
65 
66 	private final ApplicationWindow application;
67 
QMC2Editor(Composite parent, ApplicationWindow app)68 	public QMC2Editor(Composite parent, ApplicationWindow app) {
69 		super(parent, SWT.NONE);
70 		this.application = app;
71 		setLayout(new GridLayout(3, false));
72 
73 		createFileChooser();
74 		createFilterAndSearch();
75 
76 		viewer = new TreeViewer(this, SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL
77 				| SWT.BORDER | SWT.FULL_SELECTION);
78 		viewer.setContentProvider(new QMC2ContentProvider());
79 		viewer.getTree().setHeaderVisible(true);
80 		viewer.getTree().setLinesVisible(true);
81 		viewer.getTree().setLayoutData(
82 				new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1));
83 
84 		TreeViewerEditor.create(viewer, new TreeViewerFocusCellManager(viewer,
85 				new FocusCellOwnerDrawHighlighter(viewer)),
86 				new QMC2EditorActivationStrategy(viewer),
87 				ColumnViewerEditor.TABBING_HORIZONTAL
88 						| ColumnViewerEditor.TABBING_MOVE_TO_ROW_NEIGHBOR
89 						| ColumnViewerEditor.TABBING_VERTICAL
90 						| ColumnViewerEditor.KEYBOARD_ACTIVATION);
91 
92 		viewer.addFilter(new QMC2ViewFilter(this));
93 
94 		MenuManager manager = new MenuManager();
95 		manager.setRemoveAllWhenShown(true);
96 		manager.addMenuListener(new IMenuListener() {
97 			@Override
98 			public void menuAboutToShow(IMenuManager manager) {
99 				populateContextMenu(manager);
100 			}
101 		});
102 		Menu m = manager.createContextMenu(viewer.getControl());
103 		viewer.getTree().setMenu(m);
104 		viewer.addSelectionChangedListener(new ISelectionChangedListener() {
105 
106 			@Override
107 			public void selectionChanged(SelectionChangedEvent event) {
108 				updateApplicationMenuBar();
109 			}
110 		});
111 
112 	}
113 
populateContextMenu(IMenuManager manager)114 	private void populateContextMenu(IMenuManager manager) {
115 		manager.add(new UndoAction(QMC2Editor.this));
116 		manager.add(new RedoAction(QMC2Editor.this));
117 		manager.add(new AddLanguageAction(QMC2Editor.this));
118 		manager.add(new AddSectionAction(QMC2Editor.this));
119 		manager.add(new AddOptionAction(QMC2Editor.this));
120 		manager.add(new RemoveSelectedItemsAction(QMC2Editor.this));
121 	}
122 
createFilterAndSearch()123 	private void createFilterAndSearch() {
124 		GridData layoutData = new GridData(SWT.LEAD, SWT.TOP, false, false, 1,
125 				1);
126 		Label filterLabel = new Label(this, SWT.NONE);
127 		filterLabel.setText("Filter: ");
128 		filterLabel.setLayoutData(layoutData);
129 
130 		layoutData = new GridData(SWT.FILL, SWT.TOP, true, false, 2, 1);
131 		final Text filterText = new Text(this, SWT.SEARCH);
132 		filterText.setMessage("Filter...");
133 		filterText.setLayoutData(layoutData);
134 		filterText.addModifyListener(new ModifyListener() {
135 
136 			@Override
137 			public void modifyText(ModifyEvent arg0) {
138 				setFilter(filterText.getText() == null ? null : filterText
139 						.getText().trim().length() == 0 ? null : filterText
140 						.getText().toLowerCase());
141 
142 				viewer.refresh();
143 
144 			}
145 		});
146 
147 	}
148 
createFileChooser()149 	private void createFileChooser() {
150 
151 		GridData layoutData = new GridData(SWT.LEAD, SWT.TOP, false, false, 1,
152 				1);
153 		Label fileSelectionLabel = new Label(this, SWT.NONE);
154 		fileSelectionLabel.setText("Template File: ");
155 		fileSelectionLabel.setLayoutData(layoutData);
156 
157 		final Text fileSelection = new Text(this, SWT.BORDER | SWT.SINGLE);
158 		layoutData = new GridData(SWT.FILL, SWT.TOP, true, false, 1, 1);
159 		fileSelection.setLayoutData(layoutData);
160 		fileSelection.addModifyListener(new ModifyListener() {
161 
162 			@Override
163 			public void modifyText(ModifyEvent e) {
164 				selectedFile = fileSelection.getText();
165 				File f = new File(selectedFile);
166 				if (f.exists() && f.isFile() && f.canRead()) {
167 					try {
168 						templateFile = QMC2TemplateFile.parse(new File(
169 								selectedFile));
170 						createColumns(templateFile.getLanguages());
171 						operationHistory = new DefaultOperationHistory();
172 						viewer.setInput(templateFile);
173 						updateApplicationMenuBar();
174 					} catch (Exception e1) {
175 						MessageDialog.openError(
176 								getShell(),
177 								"Error",
178 								"Unable to open template file: "
179 										+ e1.getMessage());
180 					}
181 				}
182 
183 			}
184 		});
185 
186 		Button browse = new Button(this, SWT.PUSH);
187 		browse.setText("Browse...");
188 		layoutData = new GridData(SWT.TRAIL, SWT.TOP, false, false, 1, 1);
189 		browse.setLayoutData(layoutData);
190 
191 		browse.addSelectionListener(new SelectionAdapter() {
192 			@Override
193 			public void widgetSelected(SelectionEvent e) {
194 				FileDialog dialog = new FileDialog(getShell(), SWT.OPEN);
195 				dialog.setFileName(selectedFile);
196 				String filename = dialog.open();
197 				if (filename != null) {
198 					selectedFile = filename;
199 					fileSelection.setText(filename);
200 				}
201 			}
202 		});
203 
204 	}
205 
createColumns(Set<String> languages)206 	private void createColumns(Set<String> languages) {
207 
208 		int KEYS_COLUMN_SIZE = 150;
209 
210 		viewer.getTree().setRedraw(false);
211 		for (TreeColumn c : viewer.getTree().getColumns()) {
212 			c.dispose();
213 		}
214 
215 		TreeViewerColumn c = new TreeViewerColumn(viewer, SWT.NONE);
216 
217 		c.getColumn().setMoveable(false);
218 		c.getColumn().setText("Item");
219 		c.setLabelProvider(new QMC2LabelProvider(null));
220 		c.getColumn().setWidth(KEYS_COLUMN_SIZE);
221 
222 		for (String lang : languages) {
223 			c = createColumn(viewer, lang, "us".equals(lang) ? 1 : -1);
224 		}
225 
226 		viewer.getTree().setRedraw(true);
227 		int columnSize = (viewer.getTree().getSize().x - KEYS_COLUMN_SIZE)
228 				/ (viewer.getTree().getColumnCount() - 1);
229 
230 		for (int i = 1; i < viewer.getTree().getColumnCount(); i++) {
231 			viewer.getTree().getColumn(i).setWidth(columnSize);
232 		}
233 
234 	}
235 
createColumn(TreeViewer viewer, String lang, int columnIndex)236 	public TreeViewerColumn createColumn(TreeViewer viewer, String lang,
237 			int columnIndex) {
238 		TreeViewerColumn c = new TreeViewerColumn(viewer, SWT.NONE, columnIndex);
239 		c.getColumn().setMoveable(false);
240 		c.getColumn().setText(lang);
241 		c.setLabelProvider(new QMC2LabelProvider(lang));
242 		c.setEditingSupport(new QMC2EditingSupport(this, lang));
243 		return c;
244 	}
245 
getViewer()246 	public TreeViewer getViewer() {
247 		return viewer;
248 	}
249 
getOperationHistory()250 	public IOperationHistory getOperationHistory() {
251 		return operationHistory;
252 	}
253 
getCurrentFile()254 	public String getCurrentFile() {
255 		return selectedFile;
256 	}
257 
getTemplateFile()258 	public QMC2TemplateFile getTemplateFile() {
259 		return templateFile;
260 	}
261 
getUndoContext()262 	public IUndoContext getUndoContext() {
263 		return undoContext;
264 	}
265 
getFilter()266 	public String getFilter() {
267 		return filter;
268 	}
269 
setFilter(String filter)270 	public void setFilter(String filter) {
271 		this.filter = filter;
272 	}
273 
updateApplicationMenuBar()274 	public void updateApplicationMenuBar() {
275 		application.getMenuBarManager().update(IAction.TEXT);
276 		application.getMenuBarManager().update(IAction.ENABLED);
277 	}
278 
executeOperation(IUndoableOperation operation)279 	public void executeOperation(IUndoableOperation operation) {
280 		operation.addContext(undoContext);
281 		try {
282 			operationHistory
283 					.execute(operation, new NullProgressMonitor(), null);
284 		} catch (ExecutionException e) {
285 			// TODO Auto-generated catch block
286 			e.printStackTrace();
287 		}
288 	}
289 }
290