Skip to content

Commit ecf4ffb

Browse files
committed
Enable searchable tree for the e4 model editor
Setting is relatively hidden for new users (or existing ones) and it is really useful. The readonly tab is not a big functionality loss as this text is rarely modified directly.
1 parent 9474c95 commit ecf4ffb

File tree

1 file changed

+211
-0
lines changed
  • tools/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/tabs

1 file changed

+211
-0
lines changed
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2014, 2017 TwelveTone LLC and others.
3+
* Copyright (c) 2010-2014 BestSolution.at and others.
4+
*
5+
* This program and the accompanying materials
6+
* are made available under the terms of the Eclipse Public License 2.0
7+
* which accompanies this distribution, and is available at
8+
* https://www.eclipse.org/legal/epl-2.0/
9+
*
10+
* SPDX-License-Identifier: EPL-2.0
11+
*
12+
* Contributors:
13+
* Steven Spungin <[email protected]> - initial API and implementation, Bug 391089, Bug 437543, Ongoing Maintenance
14+
*******************************************************************************/
15+
16+
package org.eclipse.e4.tools.emf.ui.internal.common.component.tabs;
17+
18+
import javax.annotation.PostConstruct;
19+
import javax.inject.Inject;
20+
21+
import org.eclipse.core.resources.IProject;
22+
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
23+
import org.eclipse.e4.core.contexts.IEclipseContext;
24+
import org.eclipse.e4.core.di.annotations.Optional;
25+
import org.eclipse.e4.core.services.nls.Translation;
26+
import org.eclipse.e4.tools.emf.ui.internal.Messages;
27+
import org.eclipse.e4.tools.emf.ui.internal.common.xml.AnnotationAccess;
28+
import org.eclipse.e4.tools.emf.ui.internal.common.xml.EMFDocumentResourceMediator;
29+
import org.eclipse.e4.tools.emf.ui.internal.common.xml.XMLConfiguration;
30+
import org.eclipse.e4.tools.emf.ui.internal.common.xml.XMLPartitionScanner;
31+
import org.eclipse.e4.tools.services.IResourcePool;
32+
import org.eclipse.emf.ecore.EObject;
33+
import org.eclipse.emf.ecore.resource.Resource.Diagnostic;
34+
import org.eclipse.jface.resource.JFaceResources;
35+
import org.eclipse.jface.text.BadLocationException;
36+
import org.eclipse.jface.text.IDocument;
37+
import org.eclipse.jface.text.IDocumentPartitioner;
38+
import org.eclipse.jface.text.IRegion;
39+
import org.eclipse.jface.text.Position;
40+
import org.eclipse.jface.text.TextSelection;
41+
import org.eclipse.jface.text.rules.FastPartitioner;
42+
import org.eclipse.jface.text.source.Annotation;
43+
import org.eclipse.jface.text.source.AnnotationModel;
44+
import org.eclipse.jface.text.source.SourceViewer;
45+
import org.eclipse.jface.text.source.VerticalRuler;
46+
import org.eclipse.swt.SWT;
47+
import org.eclipse.swt.events.KeyAdapter;
48+
import org.eclipse.swt.events.KeyEvent;
49+
import org.eclipse.swt.layout.GridData;
50+
import org.eclipse.swt.layout.GridLayout;
51+
import org.eclipse.swt.widgets.Composite;
52+
import org.eclipse.swt.widgets.Text;
53+
54+
public class XmiTab extends Composite {
55+
56+
private static final String ORG_ECLIPSE_E4_TOOLS_MODELEDITOR_FILTEREDTREE_ENABLED_XMITAB_DISABLED = "org.eclipse.e4.tools.modeleditor.filteredtree.enabled.xmitab.disabled";//$NON-NLS-1$
57+
private static final int VERTICAL_RULER_WIDTH = 20;
58+
59+
@Inject
60+
private IEclipseContext context;
61+
62+
@Optional
63+
@Inject
64+
private IProject project;
65+
@Inject
66+
private EMFDocumentResourceMediator emfDocumentProvider;
67+
@Inject
68+
private IResourcePool resourcePool;
69+
@Inject
70+
private IEclipsePreferences preferences;
71+
72+
@Inject
73+
@Translation
74+
protected Messages Messages;
75+
76+
private Text text;
77+
protected int offsetStart;
78+
private SourceViewer sourceViewer;
79+
80+
@Inject
81+
public XmiTab(Composite parent) {
82+
super(parent, SWT.NONE);
83+
setLayout(new GridLayout(1, false));
84+
}
85+
86+
@PostConstruct
87+
protected void postConstruct() {
88+
text = new Text(this, SWT.SINGLE | SWT.LEAD | SWT.BORDER);
89+
text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
90+
text.setMessage(Messages.XmiTab_TypeTextToSearch);
91+
text.addKeyListener(new KeyAdapter() {
92+
@Override
93+
public void keyPressed(KeyEvent e) {
94+
if (e.keyCode != SWT.CR) {
95+
offsetStart = 0;
96+
}
97+
offsetStart = searchAndHighlight(text.getText(), offsetStart);
98+
}
99+
});
100+
101+
final AnnotationModel model = new AnnotationModel();
102+
final VerticalRuler verticalRuler = new VerticalRuler(VERTICAL_RULER_WIDTH, new AnnotationAccess(resourcePool));
103+
final int styles = SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION;
104+
sourceViewer = new SourceViewer(this, verticalRuler, styles);
105+
sourceViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
106+
107+
sourceViewer.configure(new XMLConfiguration(resourcePool));
108+
sourceViewer.setEditable(project != null);
109+
sourceViewer.getTextWidget().setFont(JFaceResources.getTextFont());
110+
111+
final IDocument document = emfDocumentProvider.getDocument();
112+
final IDocumentPartitioner partitioner = new FastPartitioner(new XMLPartitionScanner(), new String[] {
113+
XMLPartitionScanner.XML_TAG, XMLPartitionScanner.XML_COMMENT });
114+
partitioner.connect(document);
115+
document.setDocumentPartitioner(partitioner);
116+
sourceViewer.setDocument(document);
117+
verticalRuler.setModel(model);
118+
119+
emfDocumentProvider.setValidationChangedCallback(() -> {
120+
model.removeAllAnnotations();
121+
122+
for (final Diagnostic d : emfDocumentProvider.getErrorList()) {
123+
final Annotation a = new Annotation("e4xmi.error", false, d.getMessage()); //$NON-NLS-1$
124+
int l;
125+
try {
126+
l = document.getLineOffset(d.getLine() - 1);
127+
model.addAnnotation(a, new Position(l));
128+
} catch (final BadLocationException e) {
129+
// TODO Auto-generated catch block
130+
e.printStackTrace();
131+
}
132+
}
133+
});
134+
135+
final String property = System
136+
.getProperty(ORG_ECLIPSE_E4_TOOLS_MODELEDITOR_FILTEREDTREE_ENABLED_XMITAB_DISABLED);
137+
if (property != null || preferences.getBoolean("tab-form-search-show", true)) { //$NON-NLS-1$
138+
sourceViewer.setEditable(false);
139+
sourceViewer.getTextWidget().setEnabled(false);
140+
}
141+
}
142+
143+
/**
144+
*
145+
* @param text
146+
* @param startOffset
147+
* @return The endOFfset, or -1 if not found
148+
*/
149+
protected int searchAndHighlight(String text, int startOffset) {
150+
try {
151+
// select the entire start tag
152+
IRegion region;
153+
region = emfDocumentProvider.findText(text, startOffset);
154+
if (region == null && startOffset > 0) {
155+
region = emfDocumentProvider.findText(text, 0);
156+
}
157+
if (region != null) {
158+
sourceViewer.setSelection(new TextSelection(region.getOffset(), region.getLength()), true);
159+
return region.getOffset() + region.getLength();
160+
}
161+
sourceViewer.setSelection(new TextSelection(0, 0), true);
162+
return -1;
163+
} catch (final Exception e) {
164+
e.printStackTrace();
165+
return -1;
166+
}
167+
}
168+
169+
public IEclipseContext getContext() {
170+
return context;
171+
}
172+
173+
public void gotoEObject(EObject object) {
174+
// select the entire start tag
175+
final IRegion region = emfDocumentProvider.findStartTag(object);
176+
if (region != null) {
177+
sourceViewer.setSelection(new TextSelection(region.getOffset(), region.getLength()), true);
178+
} else {
179+
sourceViewer.setSelection(new TextSelection(0, 0), true);
180+
}
181+
}
182+
183+
public void paste() {
184+
if (isFilterTextFocused()) {
185+
text.paste();
186+
} else {
187+
sourceViewer.getTextWidget().paste();
188+
}
189+
}
190+
191+
public void copy() {
192+
if (isFilterTextFocused()) {
193+
text.copy();
194+
} else {
195+
sourceViewer.getTextWidget().copy();
196+
}
197+
}
198+
199+
public void cut() {
200+
if (isFilterTextFocused()) {
201+
text.cut();
202+
} else {
203+
sourceViewer.getTextWidget().cut();
204+
}
205+
}
206+
207+
private boolean isFilterTextFocused() {
208+
return text.isFocusControl();
209+
}
210+
211+
}

0 commit comments

Comments
 (0)