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
.container
;
12 import java
.util
.Iterator
;
13 import java
.util
.List
;
16 import org
.eclipse
.core
.runtime
.Assert
;
17 import org
.eclipse
.jface
.dialogs
.Dialog
;
18 import org
.eclipse
.jface
.text
.IDocument
;
19 import org
.eclipse
.jface
.text
.Position
;
20 import org
.eclipse
.jface
.window
.DefaultToolTip
;
21 import org
.eclipse
.swt
.custom
.StyledText
;
22 import org
.eclipse
.swt
.dnd
.DND
;
23 import org
.eclipse
.swt
.dnd
.DragSource
;
24 import org
.eclipse
.swt
.dnd
.Transfer
;
25 import org
.eclipse
.swt
.events
.ControlAdapter
;
26 import org
.eclipse
.swt
.events
.ControlEvent
;
27 import org
.eclipse
.swt
.events
.ControlListener
;
28 import org
.eclipse
.swt
.events
.FocusAdapter
;
29 import org
.eclipse
.swt
.events
.FocusEvent
;
30 import org
.eclipse
.swt
.events
.FocusListener
;
31 import org
.eclipse
.swt
.events
.KeyEvent
;
32 import org
.eclipse
.swt
.events
.ModifyEvent
;
33 import org
.eclipse
.swt
.events
.ModifyListener
;
34 import org
.eclipse
.swt
.events
.MouseAdapter
;
35 import org
.eclipse
.swt
.events
.MouseEvent
;
36 import org
.eclipse
.swt
.graphics
.Color
;
37 import org
.eclipse
.swt
.graphics
.Font
;
38 import org
.eclipse
.swt
.graphics
.Image
;
39 import org
.eclipse
.swt
.widgets
.Composite
;
40 import org
.eclipse
.swt
.widgets
.Control
;
41 import org
.eclipse
.swt
.widgets
.Display
;
42 import org
.eclipse
.swt
.widgets
.Label
;
43 import org
.eclipse
.swt
.widgets
.Menu
;
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
.common
.CdmUtils
;
50 import eu
.etaxonomy
.cdm
.hibernate
.HibernateProxyHelper
;
51 import eu
.etaxonomy
.cdm
.model
.name
.NameRelationship
;
52 import eu
.etaxonomy
.cdm
.model
.name
.NonViralName
;
53 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameBase
;
54 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
55 import eu
.etaxonomy
.cdm
.strategy
.parser
.ParserProblem
;
56 import eu
.etaxonomy
.taxeditor
.editor
.CdmDataTransfer
;
57 import eu
.etaxonomy
.taxeditor
.editor
.EditorUtil
;
58 import eu
.etaxonomy
.taxeditor
.editor
.name
.TaxonNameEditor
;
59 import eu
.etaxonomy
.taxeditor
.editor
.name
.container
.EditorAnnotation
.EditorAnnotationType
;
60 import eu
.etaxonomy
.taxeditor
.editor
.name
.dnd
.NameEditorDragListener
;
61 import eu
.etaxonomy
.taxeditor
.editor
.name
.dnd
.NameEditorDragSourceEffect
;
62 import eu
.etaxonomy
.taxeditor
.editor
.name
.operation
.CreateSynonymInNewGroupOperation
;
63 import eu
.etaxonomy
.taxeditor
.labels
.ILabelImageStrategy
;
64 import eu
.etaxonomy
.taxeditor
.labels
.LabelImageProvider
;
65 import eu
.etaxonomy
.taxeditor
.model
.IElementHasDetails
;
66 import eu
.etaxonomy
.taxeditor
.model
.NameHelper
;
67 import eu
.etaxonomy
.taxeditor
.model
.TextHelper
;
68 import eu
.etaxonomy
.taxeditor
.parser
.ParseHandler
;
69 import eu
.etaxonomy
.taxeditor
.preference
.Resources
;
72 * Formats <code>GroupedComposite</code> with cosmetic and layout properties
73 * specific to the Editor. This should be used to maintain a consistent look and
74 * feel for all Editor freetext area components, such as
75 * DescriptionElementComposite.
77 * Requires an <code>IManagedForm</code>, whose <code>input</code> is set to the
78 * contents of {@link #getData()} when the <code>GroupedComposite</code> gets
79 * focus, i.e. to populate the property sheet with the data.
82 * The <code>IManagedForm</code> is also required to have a <code>Taxon</code>
83 * in its own <code>getData()</code>.
86 * The <code>IManagedForm</code> can also used for drawing borders by calling
87 * the method <code>createBorderSupport()</code>.
95 abstract public class AbstractGroupedContainer
<T
extends TaxonBase
> implements
96 IFormPart
, IContainerConstants
, IElementHasDetails
{
98 protected ParseHandler parseHandler
;
100 private FocusListener nameCompositeFocusListener
;
101 private ModifyListener nameCompositeModifyListener
;
103 protected NameViewer nameViewer
;
105 private AbstractGroup group
;
107 private Label nonEditableInfoLabel
;
108 private DefaultToolTip nonEditableInfoHover
;
110 private static AbstractGroupedContainer 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
;
124 * Constructor for AbstractGroupedContainer.
128 * a {@link eu.etaxonomy.taxeditor.editor.name.TaxonNameEditor}
132 * {@link eu.etaxonomy.taxeditor.editor.name.container.AbstractGroup}
139 public AbstractGroupedContainer(T taxonBase
) {
141 parseHandler
= ParseHandler
.NewInstance(taxonBase
.getName());
144 public void createContent() {
148 createLineWrapSupport();
149 createLineBreakListener();
151 setMenu(getEditor().getMenu());
153 setDraggableControl(new Control
[] { getControl(),
154 getNameViewer().getRulerControl() });
156 createEmptyViewerPrompt(EMPTY_NAME_PROMPT
);
158 initializeComposite();
170 protected void createListener() {
171 nameCompositeModifyListener
= new ModifyListener() {
173 public void modifyText(ModifyEvent e
) {
174 // mark the composite dirty
177 String text
= nameViewer
.getTextWidget().getText();
179 NonViralName name
= parseHandler
.parse(text
);
180 getTaxonBase().setName(name
);
181 getTaxonBase().setTitleCache((getTaxonBase().generateTitle()));
183 // show errors resulting from parsing
184 calculateAnnotations();
185 // store the position of the cursor
187 // notify selection listener
188 setDelayedSelection();
191 nameCompositeFocusListener
= new FocusAdapter() {
197 * org.eclipse.swt.events.FocusAdapter#focusLost(org.eclipse.swt
198 * .events.FocusEvent)
201 public void focusLost(FocusEvent e
) {
211 private void addListener() {
212 getNameViewer().getTextWidget().addModifyListener(
213 nameCompositeModifyListener
);
214 getNameViewer().getTextWidget().addFocusListener(
215 nameCompositeFocusListener
);
218 private void removeListener() {
219 getNameViewer().getTextWidget().removeModifyListener(
220 nameCompositeModifyListener
);
221 getNameViewer().getTextWidget().removeFocusListener(
222 nameCompositeFocusListener
);
226 * Initialize the composite specific code
228 protected abstract void initializeComposite();
235 * @return a {@link java.lang.String} object.
237 protected String
getEmptyTextPrompt() {
238 return EMPTY_NAME_PROMPT
;
244 private void showNameRelations() {
245 TaxonNameBase
<?
, ?
> name
= getName();
250 ILabelImageStrategy strategy
= LabelImageProvider
251 .getLabelStrategy(name
);
252 LabelImageProvider labelProvider
= new LabelImageProvider(strategy
);
254 Set
<NameRelationship
> nameRelations
= name
.getNameRelations();
255 if (nameRelations
.size() == 0) {
258 // for (NameRelationship nameRelation : nameRelations) {
259 // String typeLabel = null;
260 // TaxonNameBase<?, ?> relatedName = null;
262 // if (name.equals(nameRelation.getFromName())) {
263 // typeLabel = labelProvider.getNameRelationTypeLabel(
264 // nameRelation.getType());
265 // relatedName = nameRelation.getToName();
267 // typeLabel = labelProvider.getNameRelationTypeInverseLabel(
268 // nameRelation.getType());
269 // relatedName = nameRelation.getFromName();
272 // setNonEditableInfo(typeLabel + " " +
273 // NameHelper.getDisplayName(relatedName));
282 protected void initTextViewer() {
284 // showNameRelations();
290 String text
= NameHelper
.getDisplayNameWithRef(getData());
292 if (text
.length() == 0) {
295 getNameViewer().setText(text
);
298 calculateAnnotations();
306 synchronized protected void calculateAnnotations() {
307 getNameViewer().clearAnnotations();
314 public void showAnnotations() {
316 if (getName().hasProblem()) {
317 showParsingProblems();
320 if (!isNameParsable()) {
323 new EditorAnnotation(EditorAnnotationType
.WARNING
,
325 "This name may only be edited in the details view."));
328 if (isNameUsedMultipleTimes()) {
329 getNameViewer().addAnnotation(
330 new EditorAnnotation(EditorAnnotationType
.WARNING
, 0,
331 "This taxons name is used multiple times."));
339 private void showParsingProblems() {
340 String text
= getNameViewer().getTextWidget().getText();
342 List
<ParserProblem
> parsingProblems
= getName().getParsingProblems();
344 for (ParserProblem problem
: parsingProblems
) {
345 getNameViewer().addAnnotation(new EditorAnnotation(problem
),
346 getParsingProblemPosition());
350 private Position
getParsingProblemPosition() {
351 String text
= getNameViewer().getTextWidget().getText();
353 if (getName().hasProblem() && text
.length() > 0) {
354 int start
= getName().getProblemStarts();
355 int length
= getName().getProblemEnds() - start
;
357 if (start
== -1 || getName().getProblemEnds() == -1) {
361 // Don't let squigglies try to draw beyond the end of the text
362 if (text
.length() < start
+ length
) {
363 length
= text
.length() - start
;
368 return new Position(start
, length
);
379 * a {@link java.lang.String} object.
381 protected void handleSplitText(String text
) {
382 // Create a synonym in a new homotypic group using text as name
383 TaxonNameBase synonymName
= ParseHandler
384 .parseReferencedName(text
, null);
386 EditorUtil
.executeOperation(new CreateSynonymInNewGroupOperation(
387 "New Heterotypic Synonym", getEditor().getUndoContext(),
388 getEditor().getTaxon(), synonymName
, getEditor()));
392 * Refreshes the display with latest data from the model.
394 * Note: Will not parse the text and not calculate errors!
396 public void refresh() {
397 // showNameRelations();
399 String text
= NameHelper
.getDisplayNameWithRef(getTaxonBase());
401 if (getNameViewer().getTextWidget() == null) {
402 // we might get here via dnd. Look slike it can be ignored
406 if (text
.length() == 0) {
408 } else if (!getNameViewer().getTextWidget().getText().equals(text
)) {
410 getNameViewer().getTextWidget().setText(text
);
414 updateNonEditableInfo();
426 protected abstract void updateIcon();
428 protected abstract void updateIndent();
432 * updateNonEditableInfo
435 protected abstract void updateNonEditableInfo();
440 private void enableFreeText() {
441 setEnabled(isFreetextEditingAllowed());
445 * Checks whether the freetext should be editable based on specific empty
450 private boolean isFreetextEditingAllowed() {
451 NonViralName name
= (NonViralName
) HibernateProxyHelper
453 boolean enableFreetext
= true;
455 enableFreetext
|= isNameUsedMultipleTimes();
456 enableFreetext
&= isNameParsable();
458 return enableFreetext
;
462 * Checks whether there are more than one, non-orphaned taxon bases
463 * attached to the taxon name
467 private boolean isNameUsedMultipleTimes() {
469 Set
<TaxonBase
> taxonBases
= getName().getTaxonBases();
470 Iterator
<TaxonBase
> tbItr
= taxonBases
.iterator();
471 int nonOrphanedTaxonBaseCount
= taxonBases
.size();
473 while(tbItr
.hasNext()) {
474 TaxonBase tb
= tbItr
.next();
475 if(tb
.isOrphaned()) {
476 nonOrphanedTaxonBaseCount
--;
479 if(nonOrphanedTaxonBaseCount
> 1) {
485 private boolean isNameParsable() {
486 TaxonNameBase name
= getName();
488 boolean isParsable
= true;
489 isParsable
&= CdmUtils
.isEmpty(name
.getAppendedPhrase()); // taxonFieldsEmpty();
491 if (name
instanceof NonViralName
) {
492 NonViralName nonViralName
= (NonViralName
) name
;
493 isParsable
&= !nonViralName
.isProtectedAuthorshipCache();
494 isParsable
&= !nonViralName
.isProtectedNameCache();
501 * Parse the text and calculate errors
503 public void parseAndCalculateAnnotations() {
505 String unparsedNameString
= getNameViewer().getTextWidget().getText();
506 parseHandler
.parse(unparsedNameString
);
508 calculateAnnotations();
516 * @return the taxonBase
518 public T
getTaxonBase() {
527 * @return a {@link eu.etaxonomy.cdm.model.name.TaxonNameBase} object.
529 public TaxonNameBase
getName() {
530 return (TaxonNameBase
) HibernateProxyHelper
.deproxy(getTaxonBase()
539 public void persistName() {
541 getNameViewer().getTextWidget().setEnabled(false);
542 final String unparsedNameString
= getNameViewer().getTextWidget()
544 // Job job = new Job("Persisting Name"){
547 // protected IStatus run(IProgressMonitor monitor) {
549 final NonViralName name
= parseHandler
550 .parseAndResolveDuplicates(unparsedNameString
);
552 // Display.getDefault().asyncExec(new Runnable(){
553 // public void run() {
554 getTaxonBase().setName(name
);
555 getTaxonBase().setTitleCache((getTaxonBase().generateTitle()));
557 getNameViewer().getTextWidget().setEnabled(true);
562 // return Status.OK_STATUS;
567 // job.setPriority(Job.DECORATE);
574 * Getter for the field <code>group</code>.
578 * {@link eu.etaxonomy.taxeditor.editor.name.container.AbstractGroup}
581 public AbstractGroup
getGroup() {
583 throw new IllegalStateException("Group shall not be null.");
593 public void remove() {
594 getGroup().remove(this);
602 protected void createControl() {
603 control
= getEditor().getToolkit().createComposite(
604 getGroup().getControl());
606 control
.setLayoutData(new TableWrapData(TableWrapData
.FILL_GRAB
));
607 TableWrapLayout layout
= new TableWrapLayout();
608 layout
.leftMargin
= 0;
609 layout
.rightMargin
= 0;
610 layout
.topMargin
= 5;
611 layout
.bottomMargin
= 5;
613 layout
.verticalSpacing
= 0;
614 layout
.horizontalSpacing
= 0;
616 control
.setLayout(layout
);
623 protected TaxonNameEditor
getEditor() {
624 return getGroup().getEditor();
629 * Getter for the field <code>control</code>.
632 * @return a {@link org.eclipse.swt.widgets.Composite} object.
634 public Composite
getControl() {
640 * createLineWrapSupport
643 protected void createLineWrapSupport() {
644 new LineWrapSupport(getNameViewer(), getEditor().getManagedForm());
652 protected void createTextViewer() {
653 nameViewer
= new NameViewer(control
);
655 focusListener
= new FocusAdapter() {
657 public void focusGained(FocusEvent e
) {
661 for (AbstractGroupedContainer container
: getEditor()
662 .getGroupedContainers()) {
663 container
.colorSelected(NOT_SELECTED
);
665 getEditor().getManagedForm().setInput(
666 AbstractGroupedContainer
.this);
668 colorSelected(SELECTED_FOCUS
);
671 nameViewer
.getTextWidget().addFocusListener(focusListener
);
674 MouseAdapter mouseListener
= new MouseAdapter() {
676 public void mouseDown(MouseEvent e
) {
680 control
.addMouseListener(mouseListener
);
681 nameViewer
.getRulerControl().addMouseListener(mouseListener
);
682 nameViewer
.getTextWidget().addMouseListener(mouseListener
);
691 * a {@link org.eclipse.swt.graphics.Image} object.
693 public void setIcon(Image icon
) {
694 getNameViewer().setIcon(icon
);
705 public void setIndent(int indent
) {
706 if (control
.getLayout() instanceof TableWrapLayout
) {
707 TableWrapLayout layout
= ((TableWrapLayout
) control
.getLayout());
708 layout
.leftMargin
= indent
;
709 layout
.rightMargin
= ACCEPTED_INDENT
;
710 control
.setLayout(layout
);
713 new RuntimeException(
714 "Couldn't indent - composite's layout must be TableWrapLayout.");
723 public void setSelected() {
724 getNameViewer().getTextWidget().setFocus();
734 public boolean isSelected() {
735 return getEditor().getSelectedContainer() == this;
746 public void colorSelected(int mode
) {
747 if (!control
.isDisposed()) {
748 String colorString
= null;
752 colorString
= Resources
.COLOR_CONTROL_SELECTED_FOCUS
;
754 case SELECTED_NO_FOCUS
:
755 colorString
= Resources
.COLOR_CONTROL_SELECTED
;
758 colorString
= Resources
.COLOR_COMPOSITE_BACKGROUND
;
761 backgroundColor
= EditorUtil
.getColor(colorString
);
763 setBackground(backgroundColor
);
769 * setDelayedSelection
772 protected void setDelayedSelection() {
773 // TODO this might be done better
774 // this is the quickest solution i could come up with and it improves
776 // please reimplement if you know better.
780 Display display
= Display
.getCurrent();
781 Runnable runnable
= new Runnable() {
784 getEditor().getManagedForm().setInput(selection
);
787 display
.timerExec(1000, runnable
);
797 * a {@link org.eclipse.swt.graphics.Color} object.
799 public void setBackground(Color color
) {
800 control
.setBackground(color
);
802 for (Control child
: control
.getChildren()) {
803 child
.setBackground(color
);
806 getNameViewer().setBackground(color
);
813 * org.eclipse.swt.widgets.Control#setFont(org.eclipse.swt.graphics.Font)
821 * a {@link org.eclipse.swt.graphics.Font} object.
823 public void setFont(Font font
) {
824 getNameViewer().getTextWidget().setFont(font
);
829 * Getter for the field <code>nameViewer</code>.
832 * @return a {@link eu.etaxonomy.taxeditor.editor.name.container.NameViewer}
835 public NameViewer
getNameViewer() {
836 if (nameViewer
== null) {
837 throw new RuntimeException(
838 "The Name Viewer is corrupt for Name Container: "
839 + getTaxonBase().getName().getTitleCache());
845 * If <code>textViewer</code> has already been set, it will show a
846 * <code>prompt</code> along the lines of
847 * "Click here to start entering data" when empty.
850 * a {@link java.lang.String} object.
852 public void createEmptyViewerPrompt(final String prompt
) {
854 Assert
.isNotNull(getNameViewer());
856 final StyledText textControl
= getNameViewer().getTextWidget();
857 final IDocument document
= getNameViewer().getDocument();
859 setFocusListener(new FocusListener() {
861 public void focusGained(FocusEvent e
) {
862 if (document
.get().equals(prompt
)) {
863 textControl
.setFont(getViewerFont());
868 public void focusLost(FocusEvent e
) {
869 if (document
.getLength() == 0) {
875 textControl
.addFocusListener(getFocusListener());
877 if (document
.getLength() == 0) {
878 textControl
.setFont(EditorUtil
879 .getFont(Resources
.FONT_DEFAULT_PROMPT
));
880 document
.set(prompt
);
889 * @return a {@link org.eclipse.swt.graphics.Font} object.
891 abstract protected Font
getViewerFont();
898 protected void initEmptyText() {
899 Font defaultFont
= EditorUtil
.getFont(Resources
.FONT_DEFAULT_PROMPT
);
900 getNameViewer().getTextWidget().setFont(defaultFont
);
902 getNameViewer().getDocument().set(getEmptyTextPrompt());
908 * Setter for the field <code>focusListener</code>.
911 * @param focusListener
912 * a {@link org.eclipse.swt.events.FocusListener} object.
914 protected void setFocusListener(FocusListener focusListener
) {
915 this.focusListener
= focusListener
;
918 private FocusListener
getFocusListener() {
919 return focusListener
;
930 public void setDirty(boolean isDirty
) {
932 getEditor().getManagedForm().dirtyStateChanged();
934 this.isDirty
= isDirty
;
944 public boolean isDirty() {
954 * a {@link org.eclipse.swt.widgets.Menu} object.
956 public void setMenu(Menu menu
) {
957 control
.setMenu(menu
);
959 getNameViewer().setMenu(menu
);
962 private Control
[] draggableControls
;
966 * setDraggableControl
970 * an array of {@link org.eclipse.swt.widgets.Control} objects.
972 protected void setDraggableControl(Control
[] controls
) {
973 draggableControls
= controls
;
984 public void setIsDraggable(boolean draggable
) {
988 if (draggableControls
== null) {
989 throw new NullPointerException(
990 "Draggable controls must be set to add draggability");
993 Transfer
[] types
= new Transfer
[] { CdmDataTransfer
.getInstance() };
994 int operations
= DND
.DROP_MOVE
;
996 for (Control draggableControl
: draggableControls
) {
997 DragSource dragSource
= new DragSource(draggableControl
,
999 dragSource
.setTransfer(types
);
1001 dragSource
.addDragListener(new NameEditorDragListener(this));
1002 dragSource
.setDragSourceEffect(new NameEditorDragSourceEffect(
1008 private String nonEditableText
;
1010 ControlListener nonEditableResizeListener
= new ControlAdapter() {
1015 public void controlResized(ControlEvent e
) {
1016 if (nonEditableInfoLabel
.getBounds().width
== width
) {
1019 width
= nonEditableInfoLabel
.getBounds().width
;
1020 if (nonEditableInfoLabel
.getBounds().width
> 0) {
1021 nonEditableInfoLabel
.setText(Dialog
.shortenText(
1022 nonEditableText
.toUpperCase(), nonEditableInfoLabel
));
1027 private String nonEditableHoverText
;
1029 private LabelEllipsisListener nonEditableLabelEllipsisListener
;
1033 private boolean enabled
;
1036 * nonEditableInfo is a label displayed underneath a GroupedComposite's
1037 * input field. For instance, NameComposites display things like name
1038 * relations, sec. references, etc. here.
1041 * the text to display in the label
1043 * whether the string should be appended to text that is already
1044 * shown in the label
1046 public void setNonEditableInfo(String info
, boolean append
) {
1047 // TODO non editable info should only be drawn once, when everything
1049 info
= info
.toUpperCase();
1052 nonEditableText
+= ", " + info
;
1053 nonEditableHoverText
+= "\n" + info
;
1055 nonEditableText
= info
;
1056 nonEditableHoverText
= info
;
1059 if (nonEditableInfoLabel
== null) {
1060 nonEditableInfoLabel
= getEditor().getToolkit().createLabel(
1062 TableWrapData layoutData
= new TableWrapData(
1063 TableWrapData
.FILL_GRAB
, TableWrapData
.TOP
);
1064 // Set indent to viewer ruler's width
1065 if (getNameViewer().getRulerControl() != null) {
1066 // TODO right justify
1067 layoutData
.indent
= NameViewer
.RULER_WIDTH
;
1069 nonEditableInfoLabel
.setLayoutData(layoutData
);
1071 nonEditableLabelEllipsisListener
= new LabelEllipsisListener(
1072 nonEditableInfoLabel
) {
1074 public String
getLabelText() {
1075 return nonEditableText
.toUpperCase();
1078 nonEditableInfoLabel
1079 .addControlListener(nonEditableLabelEllipsisListener
);
1081 nonEditableInfoHover
= new DefaultToolTip(nonEditableInfoLabel
);
1082 nonEditableInfoHover
.setRespectDisplayBounds(true);
1085 nonEditableInfoHover
.setText(nonEditableHoverText
);
1086 nonEditableInfoLabel
.setText(nonEditableText
);
1088 calculateAnnotations();
1093 * Getter for the field <code>data</code>.
1096 * @return a T object.
1098 public T
getData() {
1104 * Setter for the field <code>data</code>.
1110 public void setData(T data
) {
1111 this.data
= (T
) HibernateProxyHelper
.deproxy(data
);
1115 * If the user hitting carriage return should cause something to happen -
1116 * i.e. the creation of a new composite - call this method and override the
1117 * method handleSplitText().
1119 protected void createLineBreakListener() {
1120 lineBreakListener
= new LineBreakListener() {
1122 public void handleSplitText(String text
) {
1123 AbstractGroupedContainer
.this.handleSplitText(text
);
1127 public void keyPressed(KeyEvent e
) {
1128 // TODO Auto-generated method stub
1133 public void keyReleased(KeyEvent e
) {
1134 // TODO Auto-generated method stub
1139 getNameViewer().getTextWidget().addVerifyListener(lineBreakListener
);
1140 getNameViewer().getTextWidget().addKeyListener(lineBreakListener
);
1143 abstract class LabelEllipsisListener
extends ControlAdapter
{
1145 private final Label label
;
1148 LabelEllipsisListener(Label label
) {
1152 abstract public String
getLabelText();
1155 public void controlResized(ControlEvent e
) {
1156 if (label
.getBounds().width
== width
) {
1159 width
= label
.getBounds().width
;
1160 if (label
.getBounds().width
> 0) {
1161 label
.setText(TextHelper
.shortenText(getLabelText(), label
));
1171 public void storeCursor() {
1172 this.cursorPosition
= getNameViewer().getCursorPosition();
1176 * Puts the cursor to the position it was last seen on or to the end of line
1177 * if no former position is known.
1179 public void placeCursor() {
1180 if (cursorPosition
== 0) {
1181 getNameViewer().setCursorToEOL();
1183 getNameViewer().setCursorPosition(cursorPosition
);
1189 * Setter for the field <code>group</code>.
1194 * {@link eu.etaxonomy.taxeditor.editor.name.container.AbstractGroup}
1197 public void setGroup(AbstractGroup group
) {
1206 public void restoreColor() {
1207 setBackground(backgroundColor
);
1214 * org.eclipse.ui.forms.IFormPart#initialize(org.eclipse.ui.forms.IManagedForm
1218 public void initialize(IManagedForm form
) {
1219 // TODO Auto-generated method stub
1226 * @see org.eclipse.ui.forms.IFormPart#dispose()
1229 public void dispose() {
1230 if (getControl() != null) {
1232 getControl().dispose();
1239 * @see org.eclipse.ui.forms.IFormPart#commit(boolean)
1242 public void commit(boolean onSave
) {
1251 * @see org.eclipse.ui.forms.IFormPart#setFormInput(java.lang.Object)
1254 public boolean setFormInput(Object input
) {
1261 * @see org.eclipse.ui.forms.IFormPart#setFocus()
1264 public void setFocus() {
1265 getNameViewer().getControl().setFocus();
1271 * @see org.eclipse.ui.forms.IFormPart#isStale()
1274 public boolean isStale() {
1278 public void setDisabled(boolean disabled
) {
1279 this.enabled
= !disabled
;
1280 setEnabled(enabled
);
1283 public void setEnabled(boolean enabled
) {
1284 this.enabled
= enabled
;
1285 Color color
= enabled ? control
.getForeground() : EditorUtil
.getColor(Resources
.COLOR_DISABLED_EDITOR
);
1287 getNameViewer().getTextWidget().setEditable(enabled
);
1288 getNameViewer().getTextWidget().setEnabled(enabled
);
1289 getNameViewer().getTextWidget().setForeground(color
);
1292 public boolean isEnabled(){