2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
10 package eu
.etaxonomy
.taxeditor
.editor
.name
.e4
.container
;
12 import java
.util
.Iterator
;
13 import java
.util
.List
;
16 import org
.apache
.commons
.lang3
.StringUtils
;
17 import org
.eclipse
.core
.runtime
.Assert
;
18 import org
.eclipse
.e4
.ui
.di
.UISynchronize
;
19 import org
.eclipse
.jface
.dialogs
.Dialog
;
20 import org
.eclipse
.jface
.text
.IDocument
;
21 import org
.eclipse
.jface
.text
.Position
;
22 import org
.eclipse
.jface
.window
.DefaultToolTip
;
23 import org
.eclipse
.swt
.custom
.StyledText
;
24 import org
.eclipse
.swt
.dnd
.DND
;
25 import org
.eclipse
.swt
.dnd
.DragSource
;
26 import org
.eclipse
.swt
.dnd
.Transfer
;
27 import org
.eclipse
.swt
.events
.ControlAdapter
;
28 import org
.eclipse
.swt
.events
.ControlEvent
;
29 import org
.eclipse
.swt
.events
.ControlListener
;
30 import org
.eclipse
.swt
.events
.FocusAdapter
;
31 import org
.eclipse
.swt
.events
.FocusEvent
;
32 import org
.eclipse
.swt
.events
.FocusListener
;
33 import org
.eclipse
.swt
.events
.ModifyEvent
;
34 import org
.eclipse
.swt
.events
.ModifyListener
;
35 import org
.eclipse
.swt
.events
.MouseAdapter
;
36 import org
.eclipse
.swt
.events
.MouseEvent
;
37 import org
.eclipse
.swt
.graphics
.Color
;
38 import org
.eclipse
.swt
.graphics
.Font
;
39 import org
.eclipse
.swt
.graphics
.Image
;
40 import org
.eclipse
.swt
.widgets
.Composite
;
41 import org
.eclipse
.swt
.widgets
.Control
;
42 import org
.eclipse
.swt
.widgets
.Display
;
43 import org
.eclipse
.swt
.widgets
.Label
;
44 import org
.eclipse
.ui
.forms
.IFormPart
;
45 import org
.eclipse
.ui
.forms
.IManagedForm
;
46 import org
.eclipse
.ui
.forms
.widgets
.TableWrapData
;
47 import org
.eclipse
.ui
.forms
.widgets
.TableWrapLayout
;
49 import eu
.etaxonomy
.cdm
.hibernate
.HibernateProxyHelper
;
50 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
51 import eu
.etaxonomy
.cdm
.model
.name
.TaxonName
;
52 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
53 import eu
.etaxonomy
.cdm
.strategy
.parser
.ParserProblem
;
54 import eu
.etaxonomy
.taxeditor
.editor
.CdmDataTransfer
;
55 import eu
.etaxonomy
.taxeditor
.editor
.l10n
.Messages
;
56 import eu
.etaxonomy
.taxeditor
.editor
.name
.container
.EditorAnnotation
;
57 import eu
.etaxonomy
.taxeditor
.editor
.name
.container
.EditorAnnotation
.EditorAnnotationType
;
58 import eu
.etaxonomy
.taxeditor
.editor
.name
.container
.IContainerConstants
;
59 import eu
.etaxonomy
.taxeditor
.editor
.name
.container
.LineBreakListener
;
60 import eu
.etaxonomy
.taxeditor
.editor
.name
.container
.LineWrapSupport
;
61 import eu
.etaxonomy
.taxeditor
.editor
.name
.e4
.TaxonNameEditorE4
;
62 import eu
.etaxonomy
.taxeditor
.editor
.name
.e4
.dnd
.NameEditorDragListenerE4
;
63 import eu
.etaxonomy
.taxeditor
.editor
.name
.e4
.dnd
.NameEditorDragSourceEffect
;
64 import eu
.etaxonomy
.taxeditor
.editor
.name
.operation
.CreateSynonymInNewGroupOperation
;
65 import eu
.etaxonomy
.taxeditor
.model
.AbstractUtility
;
66 import eu
.etaxonomy
.taxeditor
.model
.IElementHasDetails
;
67 import eu
.etaxonomy
.taxeditor
.model
.NameHelper
;
68 import eu
.etaxonomy
.taxeditor
.model
.TextHelper
;
69 import eu
.etaxonomy
.taxeditor
.parser
.ParseHandler
;
70 import eu
.etaxonomy
.taxeditor
.preference
.Resources
;
73 * Formats <code>GroupedComposite</code> with cosmetic and layout properties
74 * specific to the Editor. This should be used to maintain a consistent look and
75 * feel for all Editor freetext area components, such as
76 * DescriptionElementComposite.
78 * Requires an <code>IManagedForm</code>, whose <code>input</code> is set to the
79 * contents of {@link #getData()} when the <code>GroupedComposite</code> gets
80 * focus, i.e. to populate the property sheet with the data.
83 * The <code>IManagedForm</code> is also required to have a <code>Taxon</code>
84 * in its own <code>getData()</code>.
87 * The <code>IManagedForm</code> can also used for drawing borders by calling
88 * the method <code>createBorderSupport()</code>.
95 abstract public class AbstractGroupedContainerE4
<T
extends TaxonBase
> implements
96 IFormPart
, IContainerConstants
, IElementHasDetails
{
98 protected ParseHandler parseHandler
;
100 private FocusListener nameCompositeFocusListener
;
101 private ModifyListener nameCompositeModifyListener
;
103 protected NameViewerE4 nameViewer
;
105 private AbstractGroupE4 group
;
107 private Label nonEditableInfoLabel
;
108 private DefaultToolTip nonEditableInfoHover
;
110 private static AbstractGroupedContainerE4
<?
> selection
;
112 private FocusListener focusListener
;
113 private LineBreakListener lineBreakListener
;
115 private int cursorPosition
;
117 protected Composite control
;
119 private Color backgroundColor
;
120 private boolean isDirty
;
122 public AbstractGroupedContainerE4(AbstractGroupE4 group
, T taxonBase
) {
125 parseHandler
= ParseHandler
.NewInstance(taxonBase
.getName());
128 public void createContent() {
132 createLineWrapSupport();
133 createLineBreakListener();
137 setDraggableControl(new Control
[] { getControl(),
138 getNameViewer().getRulerControl() });
140 createEmptyViewerPrompt(EMPTY_NAME_PROMPT
);
142 initializeComposite();
149 protected void createListener() {
150 nameCompositeModifyListener
= (ModifyEvent e
)->{
151 // mark the composite dirty
154 String text
= nameViewer
.getTextWidget().getText();
156 TaxonName name
= (TaxonName
)parseHandler
.parse(text
);
157 getTaxonBase().setName(name
);
158 getTaxonBase().setTitleCache((getTaxonBase().generateTitle()));
160 // show errors resulting from parsing
161 calculateAnnotations();
162 // store the position of the cursor
164 // notify selection listener
165 setDelayedSelection();
168 nameCompositeFocusListener
= new FocusAdapter() {
171 public void focusLost(FocusEvent e
) {
180 protected void addListener() {
181 getNameViewer().getTextWidget().addModifyListener(
182 nameCompositeModifyListener
);
183 getNameViewer().getTextWidget().addFocusListener(
184 nameCompositeFocusListener
);
187 protected void removeListener() {
188 getNameViewer().getTextWidget().removeModifyListener(
189 nameCompositeModifyListener
);
190 getNameViewer().getTextWidget().removeFocusListener(
191 nameCompositeFocusListener
);
195 * Initialize the composite specific code
197 protected abstract void initializeComposite();
199 protected String
getEmptyTextPrompt() {
200 return EMPTY_NAME_PROMPT
;
203 protected void initTextViewer() {
209 String text
= NameHelper
.getDisplayNameWithRef(getData());
211 if (text
.length() == 0) {
214 getNameViewer().setText(text
);
217 calculateAnnotations();
220 synchronized protected void calculateAnnotations() {
221 getNameViewer().clearAnnotations();
225 public void showAnnotations() {
227 if (getName() != null && getName().hasProblem()) {
228 showParsingProblems();
231 if (!isNameParsable()) {
234 new EditorAnnotation(EditorAnnotationType
.WARNING
,
236 Messages
.AbstractGroupedContainer_EDIT_IN_DETAILS_VIEW
));
239 if (isNameUsedMultipleTimes()) {
240 getNameViewer().addAnnotation(
241 new EditorAnnotation(EditorAnnotationType
.WARNING
, 0,
242 Messages
.AbstractGroupedContainer_MULTIPLE_USE
));
247 private void showParsingProblems() {
248 TaxonName name
= getName();
253 List
<ParserProblem
> parsingProblems
= name
.getParsingProblems();
255 for (ParserProblem problem
: parsingProblems
) {
256 getNameViewer().addAnnotation(new EditorAnnotation(problem
),
257 getParsingProblemPosition());
261 private Position
getParsingProblemPosition() {
262 String text
= getNameViewer().getTextWidget().getText();
264 if (getName() != null && getName().hasProblem() && text
.length() > 0) {
265 int start
= getName().getProblemStarts();
266 int length
= getName().getProblemEnds() - start
;
268 if (start
== -1 || getName().getProblemEnds() == -1) {
272 // Don't let squigglies try to draw beyond the end of the text
273 if (text
.length() < start
+ length
) {
274 length
= text
.length() - start
;
279 return new Position(start
, length
);
284 protected void handleSplitText(String text
) {
285 // Create a synonym in a new homotypic group using text as name
286 TaxonName synonymName
= TaxonName
.castAndDeproxy(
287 ParseHandler
.parseReferencedName(text
, null));
289 AbstractUtility
.executeOperation(new CreateSynonymInNewGroupOperation(
290 Messages
.AbstractGroupedContainer_NEW_HETERO_SYNONYM
, getEditor().getUndoContext(),
291 getEditor().getTaxon(), synonymName
, getEditor()), group
.getContext().get(UISynchronize
.class));
295 * Refreshes the display with latest data from the model.
297 * Note: Will not parse the text and not calculate errors!
300 public void refresh() {
301 // showNameRelations();
303 String text
= NameHelper
.getDisplayNameWithRef(getTaxonBase());
305 if (getNameViewer().getTextWidget() == null) {
306 // we might get here via dnd. Look slike it can be ignored
310 if (text
.length() == 0) {
312 } else if (!getNameViewer().getTextWidget().getText().equals(text
)) {
314 getNameViewer().getTextWidget().setText(text
);
318 updateNonEditableInfo();
323 setDelayedSelection();
327 protected abstract void updateIcon();
329 protected abstract void updateIndent();
331 protected abstract void updateNonEditableInfo();
333 protected void enableFreeText() {
334 setEnabled(isFreetextEditingAllowed());
338 * Checks whether the freetext should be editable based on specific empty
343 private boolean isFreetextEditingAllowed() {
344 boolean enableFreetext
= true;
346 enableFreetext
|= isNameUsedMultipleTimes();
347 enableFreetext
&= isNameParsable();
349 return enableFreetext
;
353 * Checks whether there are more than one, non-orphaned taxon bases
354 * attached to the taxon name
358 private boolean isNameUsedMultipleTimes() {
360 TaxonName name
= getName();
362 Set
<TaxonBase
> taxonBases
= name
.getTaxonBases();
363 Iterator
<TaxonBase
> tbItr
= taxonBases
.iterator();
364 int nonOrphanedTaxonBaseCount
= taxonBases
.size();
366 while(tbItr
.hasNext()) {
367 TaxonBase
<?
> tb
= tbItr
.next();
368 if(tb
.isOrphaned()) {
369 nonOrphanedTaxonBaseCount
--;
372 if(nonOrphanedTaxonBaseCount
> 1) {
379 private boolean isNameParsable() {
380 TaxonName name
= getName();
385 boolean isParsable
= true;
386 isParsable
&= StringUtils
.isBlank(name
.getAppendedPhrase()); // taxonFieldsEmpty();
387 if (name
.isProtectedAuthorshipCache()){
388 isParsable
&= nameAuthorsSet(name
);
390 if (name
.isProtectedNameCache()){
391 isParsable
&= nameEpithetsNotSet(name
) && nameAuthorsSet(name
);
397 private boolean nameAuthorsSet(TaxonName name
) {
398 boolean result
= true;
399 result
&= name
.getBasionymAuthorship() == null && name
.getCombinationAuthorship() == null && name
.getExBasionymAuthorship() == null && name
.getExCombinationAuthorship() == null;
403 private boolean nameEpithetsNotSet(TaxonName name
) {
404 boolean result
= true;
405 result
&= name
.getGenusOrUninomial() == null && name
.getInfraGenericEpithet() == null && name
.getSpecificEpithet() == null && name
.getInfraSpecificEpithet() == null;
411 * Parse the text and calculate errors
413 public void parseAndCalculateAnnotations() {
415 String unparsedNameString
= getNameViewer().getTextWidget().getText();
416 parseHandler
.parse(unparsedNameString
);
418 calculateAnnotations();
421 public T
getTaxonBase() {
425 public TaxonName
getName() {
426 return CdmBase
.deproxy(getTaxonBase().getName());
429 public void persistName() {
431 getNameViewer().getTextWidget().setEnabled(false);
432 final String unparsedNameString
= getNameViewer().getTextWidget()
434 final TaxonName name
= (TaxonName
)parseHandler
435 .parseAndResolveDuplicates(unparsedNameString
);
436 getTaxonBase().setName(name
);
437 getTaxonBase().setTitleCache((getTaxonBase().generateTitle()));
439 getNameViewer().getTextWidget().setEnabled(true);
443 public AbstractGroupE4
getGroup() {
445 throw new IllegalStateException("Group shall not be null."); //$NON-NLS-1$
450 public void remove() {
451 getGroup().remove(this);
454 protected void createControl() {
455 control
= getEditor().getToolkit().createComposite(
456 getGroup().getControl());
458 control
.setLayoutData(new TableWrapData(TableWrapData
.FILL_GRAB
));
459 TableWrapLayout layout
= new TableWrapLayout();
460 layout
.leftMargin
= 0;
461 layout
.rightMargin
= 0;
462 layout
.topMargin
= 5;
463 layout
.bottomMargin
= 5;
465 layout
.verticalSpacing
= 0;
466 layout
.horizontalSpacing
= 0;
468 control
.setLayout(layout
);
472 protected TaxonNameEditorE4
getEditor() {
473 return getGroup().getEditor();
476 public Composite
getControl() {
480 protected void createLineWrapSupport() {
481 new LineWrapSupport(getNameViewer(), getEditor().getManagedForm());
484 protected void createTextViewer() {
485 nameViewer
= new NameViewerE4(control
);
487 focusListener
= new FocusAdapter() {
489 public void focusGained(FocusEvent e
) {
491 .getGroupedContainers().isEmpty()){
495 for (AbstractGroupedContainerE4
<?
> container
: getEditor()
496 .getGroupedContainers()) {
497 container
.colorSelected(NOT_SELECTED
);
499 getEditor().getManagedForm().setInput(
500 AbstractGroupedContainerE4
.this);
502 colorSelected(SELECTED_FOCUS
);
505 nameViewer
.getTextWidget().addFocusListener(focusListener
);
507 MouseAdapter mouseListener
= new MouseAdapter() {
509 public void mouseDown(MouseEvent e
) {
513 control
.addMouseListener(mouseListener
);
514 nameViewer
.getRulerControl().addMouseListener(mouseListener
);
515 nameViewer
.getTextWidget().addMouseListener(mouseListener
);
518 public void setIcon(Image icon
) {
519 getNameViewer().setIcon(icon
);
522 public void setIndent(int indent
) {
523 if (control
.getLayout() instanceof TableWrapLayout
) {
524 TableWrapLayout layout
= ((TableWrapLayout
) control
.getLayout());
525 layout
.leftMargin
= indent
;
526 layout
.rightMargin
= ACCEPTED_INDENT
;
527 control
.setLayout(layout
);
530 throw new RuntimeException(
531 "Couldn't indent - composite's layout must be TableWrapLayout."); //$NON-NLS-1$
535 public void setSelected() {
536 getNameViewer().getTextWidget().setFocus();
539 public boolean isSelected() {
540 return getEditor().getSelectedContainer() == this;
543 public void colorSelected(int mode
) {
544 if (control
!=null && !control
.isDisposed()) {
545 String colorString
= null;
549 colorString
= Resources
.COLOR_CONTROL_SELECTED_FOCUS
;
551 case SELECTED_NO_FOCUS
:
552 colorString
= Resources
.COLOR_CONTROL_SELECTED
;
555 colorString
= Resources
.COLOR_COMPOSITE_BACKGROUND
;
558 backgroundColor
= AbstractUtility
.getColor(colorString
);
560 setBackground(backgroundColor
);
564 private Delay delay
= new Delay(Display
.getCurrent());
566 private class Delay
extends Thread
{
568 private volatile boolean stop
= false;
569 private Display display
;
571 public Delay(Display display
) {
572 this.display
= display
;
582 display
.syncExec(() -> {
583 getEditor().getManagedForm().setInput(selection
);
587 } catch (InterruptedException ex
) {
592 public void requestStop() {
597 protected void setDelayedSelection() {
600 Display display
= Display
.getCurrent();
603 delay
= new Delay(display
);
608 public void setBackground(Color color
) {
609 control
.setBackground(color
);
611 for (Control child
: control
.getChildren()) {
612 child
.setBackground(color
);
615 getNameViewer().setBackground(color
);
618 public void setFont(Font font
) {
619 getNameViewer().getTextWidget().setFont(font
);
622 public NameViewerE4
getNameViewer() {
623 if (nameViewer
== null) {
624 throw new RuntimeException(
625 "The Name Viewer is corrupt for Name Container: " //$NON-NLS-1$
626 + getTaxonBase().getName().getTitleCache());
631 public void createEmptyViewerPrompt(final String prompt
) {
633 Assert
.isNotNull(getNameViewer());
635 final StyledText textControl
= getNameViewer().getTextWidget();
636 final IDocument document
= getNameViewer().getDocument();
638 setFocusListener(new FocusListener() {
641 public void focusGained(FocusEvent e
) {
642 if (document
.get().equals(prompt
)) {
643 textControl
.setFont(getViewerFont());
644 document
.set(""); //$NON-NLS-1$
649 public void focusLost(FocusEvent e
) {
650 if (document
.getLength() == 0) {
656 textControl
.addFocusListener(getFocusListener());
658 if (document
.getLength() == 0) {
659 textControl
.setFont(AbstractUtility
660 .getFont(Resources
.FONT_DEFAULT_PROMPT
));
661 document
.set(prompt
);
665 abstract protected Font
getViewerFont();
667 protected void initEmptyText() {
668 Font defaultFont
= AbstractUtility
.getFont(Resources
.FONT_DEFAULT_PROMPT
);
669 getNameViewer().getTextWidget().setFont(defaultFont
);
671 getNameViewer().getDocument().set(getEmptyTextPrompt());
674 protected void setFocusListener(FocusListener focusListener
) {
675 this.focusListener
= focusListener
;
678 private FocusListener
getFocusListener() {
679 return focusListener
;
682 public void setDirty(boolean isDirty
) {
684 getEditor().getManagedForm().dirtyStateChanged();
686 this.isDirty
= isDirty
;
690 public boolean isDirty() {
694 public void setMenu() {
695 getEditor().getMenuService().registerContextMenu(getNameViewer().getTextWidget(), "eu.etaxonomy.taxeditor.editor.popupmenu.nameeditor");
698 private Control
[] draggableControls
;
700 protected void setDraggableControl(Control
[] controls
) {
701 draggableControls
= controls
;
704 public void setIsDraggable(boolean draggable
) {
708 if (draggableControls
== null) {
709 throw new NullPointerException(
710 "Draggable controls must be set to add draggability"); //$NON-NLS-1$
713 Transfer
[] types
= new Transfer
[] { CdmDataTransfer
.getInstance() };
714 int operations
= DND
.DROP_MOVE
;
716 for (Control draggableControl
: draggableControls
) {
717 DragSource dragSource
= new DragSource(draggableControl
,
719 dragSource
.setTransfer(types
);
721 dragSource
.addDragListener(new NameEditorDragListenerE4(this));
722 dragSource
.setDragSourceEffect(new NameEditorDragSourceEffect(
728 private String nonEditableText
;
730 ControlListener nonEditableResizeListener
= new ControlAdapter() {
735 public void controlResized(ControlEvent e
) {
736 if (nonEditableInfoLabel
.getBounds().width
== width
) {
739 width
= nonEditableInfoLabel
.getBounds().width
;
740 if (nonEditableInfoLabel
.getBounds().width
> 0) {
741 nonEditableInfoLabel
.setText(Dialog
.shortenText(
742 nonEditableText
.toUpperCase(), nonEditableInfoLabel
));
747 private String nonEditableHoverText
;
749 private LabelEllipsisListener nonEditableLabelEllipsisListener
;
754 * nonEditableInfo is a label displayed underneath a GroupedComposite's
755 * input field. For instance, NameComposites display things like name
756 * relations, sec. references, etc. here.
759 * the text to display in the label
761 * whether the string should be appended to text that is already
764 public void setNonEditableInfo(String info
, boolean append
) {
765 // TODO non editable info should only be drawn once, when everything
767 info
= info
.toUpperCase();
770 nonEditableText
+= ", " + info
; //$NON-NLS-1$
771 nonEditableHoverText
+= "\n" + info
; //$NON-NLS-1$
773 nonEditableText
= info
;
774 nonEditableHoverText
= info
;
777 if (nonEditableInfoLabel
== null) {
778 nonEditableInfoLabel
= getEditor().getToolkit().createLabel(
779 control
, ""); //$NON-NLS-1$
780 TableWrapData layoutData
= new TableWrapData(
781 TableWrapData
.FILL_GRAB
, TableWrapData
.TOP
);
782 // Set indent to viewer ruler's width
783 if (getNameViewer().getRulerControl() != null) {
784 // TODO right justify
785 layoutData
.indent
= NameViewerE4
.RULER_WIDTH
;
787 nonEditableInfoLabel
.setLayoutData(layoutData
);
789 nonEditableLabelEllipsisListener
= new LabelEllipsisListener(
790 nonEditableInfoLabel
) {
792 public String
getLabelText() {
793 return nonEditableText
.toUpperCase();
797 .addControlListener(nonEditableLabelEllipsisListener
);
799 nonEditableInfoHover
= new DefaultToolTip(nonEditableInfoLabel
);
800 nonEditableInfoHover
.setRespectDisplayBounds(true);
803 nonEditableInfoHover
.setText(nonEditableHoverText
);
804 nonEditableInfoLabel
.setText(nonEditableText
);
806 calculateAnnotations();
814 public void setData(T data
) {
815 this.data
= HibernateProxyHelper
.deproxy(data
);
819 * If the user hitting carriage return should cause something to happen -
820 * i.e. the creation of a new composite - call this method and override the
821 * method handleSplitText().
823 protected void createLineBreakListener() {
824 lineBreakListener
= new LineBreakListener() {
826 public void handleSplitText(String text
) {
827 AbstractGroupedContainerE4
.this.handleSplitText(text
);
832 getNameViewer().getTextWidget().addVerifyListener(lineBreakListener
);
836 abstract class LabelEllipsisListener
extends ControlAdapter
{
838 private final Label label
;
841 LabelEllipsisListener(Label label
) {
845 abstract public String
getLabelText();
848 public void controlResized(ControlEvent e
) {
849 if (label
.getBounds().width
== width
) {
852 width
= label
.getBounds().width
;
853 if (label
.getBounds().width
> 0) {
854 label
.setText(TextHelper
.shortenText(getLabelText(), label
));
859 public void storeCursor() {
860 this.cursorPosition
= getNameViewer().getCursorPosition();
864 * Puts the cursor to the position it was last seen on or to the end of line
865 * if no former position is known.
867 public void placeCursor() {
868 if (cursorPosition
== 0) {
869 getNameViewer().setCursorToEOL();
871 getNameViewer().setCursorPosition(cursorPosition
);
875 public void restoreColor() {
876 setBackground(backgroundColor
);
880 public void initialize(IManagedForm form
) {
881 // TODO Auto-generated method stub
885 public void dispose() {
886 if (getControl() != null) {
887 getControl().dispose();
892 public void commit(boolean onSave
) {
899 public boolean setFormInput(Object input
) {
904 public void setFocus() {
905 getNameViewer().getControl().setFocus();
909 public boolean isStale() {
913 public void setDisabled(boolean disabled
) {
914 setEnabled(!disabled
);
917 public void setEnabled(boolean enabled
) {
918 Color color
= enabled ? control
.getForeground() : AbstractUtility
.getColor(Resources
.COLOR_DISABLED_EDITOR
);
920 getNameViewer().getTextWidget().setEditable(enabled
);
921 getNameViewer().getTextWidget().setForeground(color
);