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
.apache
.commons
.lang
.StringUtils
;
17 import org
.eclipse
.core
.runtime
.Assert
;
18 import org
.eclipse
.jface
.dialogs
.Dialog
;
19 import org
.eclipse
.jface
.text
.IDocument
;
20 import org
.eclipse
.jface
.text
.Position
;
21 import org
.eclipse
.jface
.window
.DefaultToolTip
;
22 import org
.eclipse
.swt
.custom
.StyledText
;
23 import org
.eclipse
.swt
.dnd
.DND
;
24 import org
.eclipse
.swt
.dnd
.DragSource
;
25 import org
.eclipse
.swt
.dnd
.Transfer
;
26 import org
.eclipse
.swt
.events
.ControlAdapter
;
27 import org
.eclipse
.swt
.events
.ControlEvent
;
28 import org
.eclipse
.swt
.events
.ControlListener
;
29 import org
.eclipse
.swt
.events
.FocusAdapter
;
30 import org
.eclipse
.swt
.events
.FocusEvent
;
31 import org
.eclipse
.swt
.events
.FocusListener
;
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
.common
.CdmBase
;
52 import eu
.etaxonomy
.cdm
.model
.name
.INonViralName
;
53 import eu
.etaxonomy
.cdm
.model
.name
.NameRelationship
;
54 import eu
.etaxonomy
.cdm
.model
.name
.TaxonName
;
55 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
56 import eu
.etaxonomy
.cdm
.strategy
.parser
.ParserProblem
;
57 import eu
.etaxonomy
.taxeditor
.editor
.CdmDataTransfer
;
58 import eu
.etaxonomy
.taxeditor
.editor
.EditorUtil
;
59 import eu
.etaxonomy
.taxeditor
.editor
.l10n
.Messages
;
60 import eu
.etaxonomy
.taxeditor
.editor
.name
.TaxonNameEditor
;
61 import eu
.etaxonomy
.taxeditor
.editor
.name
.container
.EditorAnnotation
.EditorAnnotationType
;
62 import eu
.etaxonomy
.taxeditor
.editor
.name
.dnd
.NameEditorDragListener
;
63 import eu
.etaxonomy
.taxeditor
.editor
.name
.dnd
.NameEditorDragSourceEffect
;
64 import eu
.etaxonomy
.taxeditor
.editor
.name
.operation
.CreateSynonymInNewGroupOperation
;
65 import eu
.etaxonomy
.taxeditor
.labels
.ILabelImageStrategy
;
66 import eu
.etaxonomy
.taxeditor
.labels
.LabelImageProvider
;
67 import eu
.etaxonomy
.taxeditor
.model
.IElementHasDetails
;
68 import eu
.etaxonomy
.taxeditor
.model
.NameHelper
;
69 import eu
.etaxonomy
.taxeditor
.model
.TextHelper
;
70 import eu
.etaxonomy
.taxeditor
.parser
.ParseHandler
;
71 import eu
.etaxonomy
.taxeditor
.preference
.Resources
;
74 * Formats <code>GroupedComposite</code> with cosmetic and layout properties
75 * specific to the Editor. This should be used to maintain a consistent look and
76 * feel for all Editor freetext area components, such as
77 * DescriptionElementComposite.
79 * Requires an <code>IManagedForm</code>, whose <code>input</code> is set to the
80 * contents of {@link #getData()} when the <code>GroupedComposite</code> gets
81 * focus, i.e. to populate the property sheet with the data.
84 * The <code>IManagedForm</code> is also required to have a <code>Taxon</code>
85 * in its own <code>getData()</code>.
88 * The <code>IManagedForm</code> can also used for drawing borders by calling
89 * the method <code>createBorderSupport()</code>.
96 abstract public class AbstractGroupedContainer
<T
extends TaxonBase
> implements
97 IFormPart
, IContainerConstants
, IElementHasDetails
{
99 protected ParseHandler parseHandler
;
101 private FocusListener nameCompositeFocusListener
;
102 private ModifyListener nameCompositeModifyListener
;
104 protected NameViewer nameViewer
;
106 private AbstractGroup group
;
108 private Label nonEditableInfoLabel
;
109 private DefaultToolTip nonEditableInfoHover
;
111 private static AbstractGroupedContainer selection
;
113 private FocusListener focusListener
;
114 private LineBreakListener lineBreakListener
;
116 private int cursorPosition
;
118 protected Composite control
;
120 private Color backgroundColor
;
121 private boolean isDirty
;
125 * Constructor for AbstractGroupedContainer.
129 * a {@link eu.etaxonomy.taxeditor.editor.name.TaxonNameEditor}
133 * {@link eu.etaxonomy.taxeditor.editor.name.container.AbstractGroup}
140 public AbstractGroupedContainer(T taxonBase
) {
142 parseHandler
= ParseHandler
.NewInstance(taxonBase
.getName());
145 public void createContent() {
149 createLineWrapSupport();
150 createLineBreakListener();
152 setMenu(getEditor().getMenu());
154 setDraggableControl(new Control
[] { getControl(),
155 getNameViewer().getRulerControl() });
157 createEmptyViewerPrompt(EMPTY_NAME_PROMPT
);
159 initializeComposite();
171 protected void createListener() {
172 nameCompositeModifyListener
= new ModifyListener() {
175 public void modifyText(ModifyEvent e
) {
176 // mark the composite dirty
179 String text
= nameViewer
.getTextWidget().getText();
181 TaxonName name
= (TaxonName
)parseHandler
.parse(text
);
182 getTaxonBase().setName(name
);
183 getTaxonBase().setTitleCache((getTaxonBase().generateTitle()));
185 // show errors resulting from parsing
186 calculateAnnotations();
187 // store the position of the cursor
189 // notify selection listener
190 setDelayedSelection();
193 nameCompositeFocusListener
= new FocusAdapter() {
199 * org.eclipse.swt.events.FocusAdapter#focusLost(org.eclipse.swt
200 * .events.FocusEvent)
203 public void focusLost(FocusEvent e
) {
213 protected void addListener() {
214 getNameViewer().getTextWidget().addModifyListener(
215 nameCompositeModifyListener
);
216 getNameViewer().getTextWidget().addFocusListener(
217 nameCompositeFocusListener
);
220 protected void removeListener() {
221 getNameViewer().getTextWidget().removeModifyListener(
222 nameCompositeModifyListener
);
223 getNameViewer().getTextWidget().removeFocusListener(
224 nameCompositeFocusListener
);
228 * Initialize the composite specific code
230 protected abstract void initializeComposite();
237 * @return a {@link java.lang.String} object.
239 protected String
getEmptyTextPrompt() {
240 return EMPTY_NAME_PROMPT
;
246 private void showNameRelations() {
247 TaxonName name
= getName();
252 ILabelImageStrategy strategy
= LabelImageProvider
253 .getLabelStrategy(name
);
254 LabelImageProvider labelProvider
= new LabelImageProvider(strategy
);
256 Set
<NameRelationship
> nameRelations
= name
.getNameRelations();
257 if (nameRelations
.size() == 0) {
260 // for (NameRelationship nameRelation : nameRelations) {
261 // String typeLabel = null;
262 // TaxonName relatedName = null;
264 // if (name.equals(nameRelation.getFromName())) {
265 // typeLabel = labelProvider.getNameRelationTypeLabel(
266 // nameRelation.getType());
267 // relatedName = nameRelation.getToName();
269 // typeLabel = labelProvider.getNameRelationTypeInverseLabel(
270 // nameRelation.getType());
271 // relatedName = nameRelation.getFromName();
274 // setNonEditableInfo(typeLabel + " " +
275 // NameHelper.getDisplayName(relatedName));
284 protected void initTextViewer() {
286 // showNameRelations();
292 String text
= NameHelper
.getDisplayNameWithRef(getData());
294 if (text
.length() == 0) {
297 getNameViewer().setText(text
);
300 calculateAnnotations();
308 synchronized protected void calculateAnnotations() {
309 getNameViewer().clearAnnotations();
316 public void showAnnotations() {
318 if (getName() != null && getName().hasProblem()) {
319 showParsingProblems();
322 if (!isNameParsable()) {
325 new EditorAnnotation(EditorAnnotationType
.WARNING
,
327 Messages
.AbstractGroupedContainer_EDIT_IN_DETAILS_VIEW
));
330 if (isNameUsedMultipleTimes()) {
331 getNameViewer().addAnnotation(
332 new EditorAnnotation(EditorAnnotationType
.WARNING
, 0,
333 Messages
.AbstractGroupedContainer_MULTIPLE_USE
));
341 private void showParsingProblems() {
342 String text
= getNameViewer().getTextWidget().getText();
344 TaxonName name
= getName();
349 List
<ParserProblem
> parsingProblems
= name
.getParsingProblems();
351 for (ParserProblem problem
: parsingProblems
) {
352 getNameViewer().addAnnotation(new EditorAnnotation(problem
),
353 getParsingProblemPosition());
357 private Position
getParsingProblemPosition() {
358 String text
= getNameViewer().getTextWidget().getText();
360 if (getName() != null && getName().hasProblem() && text
.length() > 0) {
361 int start
= getName().getProblemStarts();
362 int length
= getName().getProblemEnds() - start
;
364 if (start
== -1 || getName().getProblemEnds() == -1) {
368 // Don't let squigglies try to draw beyond the end of the text
369 if (text
.length() < start
+ length
) {
370 length
= text
.length() - start
;
375 return new Position(start
, length
);
386 * a {@link java.lang.String} object.
388 protected void handleSplitText(String text
) {
389 // Create a synonym in a new homotypic group using text as name
390 TaxonName synonymName
= TaxonName
.castAndDeproxy(
391 ParseHandler
.parseReferencedName(text
, null));
393 EditorUtil
.executeOperation(new CreateSynonymInNewGroupOperation(
394 Messages
.AbstractGroupedContainer_NEW_HETERO_SYNONYM
, getEditor().getUndoContext(),
395 getEditor().getTaxon(), synonymName
, getEditor()));
399 * Refreshes the display with latest data from the model.
401 * Note: Will not parse the text and not calculate errors!
404 public void refresh() {
405 // showNameRelations();
407 String text
= NameHelper
.getDisplayNameWithRef(getTaxonBase());
409 if (getNameViewer().getTextWidget() == null) {
410 // we might get here via dnd. Look slike it can be ignored
414 if (text
.length() == 0) {
416 } else if (!getNameViewer().getTextWidget().getText().equals(text
)) {
418 getNameViewer().getTextWidget().setText(text
);
422 updateNonEditableInfo();
434 protected abstract void updateIcon();
436 protected abstract void updateIndent();
440 * updateNonEditableInfo
443 protected abstract void updateNonEditableInfo();
448 protected void enableFreeText() {
449 setEnabled(isFreetextEditingAllowed());
453 * Checks whether the freetext should be editable based on specific empty
458 private boolean isFreetextEditingAllowed() {
459 boolean enableFreetext
= true;
461 enableFreetext
|= isNameUsedMultipleTimes();
462 enableFreetext
&= isNameParsable();
464 return enableFreetext
;
468 * Checks whether there are more than one, non-orphaned taxon bases
469 * attached to the taxon name
473 private boolean isNameUsedMultipleTimes() {
475 TaxonName name
= getName();
477 Set
<TaxonBase
> taxonBases
= name
.getTaxonBases();
478 Iterator
<TaxonBase
> tbItr
= taxonBases
.iterator();
479 int nonOrphanedTaxonBaseCount
= taxonBases
.size();
481 while(tbItr
.hasNext()) {
482 TaxonBase
<?
> tb
= tbItr
.next();
483 if(tb
.isOrphaned()) {
484 nonOrphanedTaxonBaseCount
--;
487 if(nonOrphanedTaxonBaseCount
> 1) {
494 private boolean isNameParsable() {
495 TaxonName name
= getName();
500 boolean isParsable
= true;
501 isParsable
&= StringUtils
.isBlank(name
.getAppendedPhrase()); // taxonFieldsEmpty();
503 isParsable
&= !name
.isProtectedAuthorshipCache();
504 isParsable
&= !name
.isProtectedNameCache();
510 * Parse the text and calculate errors
512 public void parseAndCalculateAnnotations() {
514 String unparsedNameString
= getNameViewer().getTextWidget().getText();
515 parseHandler
.parse(unparsedNameString
);
517 calculateAnnotations();
525 * @return the taxonBase
527 public T
getTaxonBase() {
536 * @return a {@link eu.etaxonomy.cdm.model.name.TaxonNameBase} object.
538 public TaxonName
getName() {
539 return CdmBase
.deproxy(getTaxonBase().getName());
547 public void persistName() {
549 getNameViewer().getTextWidget().setEnabled(false);
550 final String unparsedNameString
= getNameViewer().getTextWidget()
552 // Job job = new Job("Persisting Name"){
555 // protected IStatus run(IProgressMonitor monitor) {
557 final TaxonName name
= (TaxonName
)parseHandler
558 .parseAndResolveDuplicates(unparsedNameString
);
560 // Display.getDefault().asyncExec(new Runnable(){
561 // public void run() {
562 getTaxonBase().setName(name
);
563 getTaxonBase().setTitleCache((getTaxonBase().generateTitle()));
565 getNameViewer().getTextWidget().setEnabled(true);
570 // return Status.OK_STATUS;
575 // job.setPriority(Job.DECORATE);
582 * Getter for the field <code>group</code>.
586 * {@link eu.etaxonomy.taxeditor.editor.name.container.AbstractGroup}
589 public AbstractGroup
getGroup() {
591 throw new IllegalStateException("Group shall not be null."); //$NON-NLS-1$
601 public void remove() {
602 getGroup().remove(this);
610 protected void createControl() {
611 control
= getEditor().getToolkit().createComposite(
612 getGroup().getControl());
614 control
.setLayoutData(new TableWrapData(TableWrapData
.FILL_GRAB
));
615 TableWrapLayout layout
= new TableWrapLayout();
616 layout
.leftMargin
= 0;
617 layout
.rightMargin
= 0;
618 layout
.topMargin
= 5;
619 layout
.bottomMargin
= 5;
621 layout
.verticalSpacing
= 0;
622 layout
.horizontalSpacing
= 0;
624 control
.setLayout(layout
);
631 protected TaxonNameEditor
getEditor() {
632 return getGroup().getEditor();
637 * Getter for the field <code>control</code>.
640 * @return a {@link org.eclipse.swt.widgets.Composite} object.
642 public Composite
getControl() {
648 * createLineWrapSupport
651 protected void createLineWrapSupport() {
652 new LineWrapSupport(getNameViewer(), getEditor().getManagedForm());
660 protected void createTextViewer() {
661 nameViewer
= new NameViewer(control
);
663 focusListener
= new FocusAdapter() {
665 public void focusGained(FocusEvent e
) {
669 for (AbstractGroupedContainer container
: getEditor()
670 .getGroupedContainers()) {
671 container
.colorSelected(NOT_SELECTED
);
673 getEditor().getManagedForm().setInput(
674 AbstractGroupedContainer
.this);
676 colorSelected(SELECTED_FOCUS
);
679 nameViewer
.getTextWidget().addFocusListener(focusListener
);
682 MouseAdapter mouseListener
= new MouseAdapter() {
684 public void mouseDown(MouseEvent e
) {
688 control
.addMouseListener(mouseListener
);
689 nameViewer
.getRulerControl().addMouseListener(mouseListener
);
690 nameViewer
.getTextWidget().addMouseListener(mouseListener
);
699 * a {@link org.eclipse.swt.graphics.Image} object.
701 public void setIcon(Image icon
) {
702 getNameViewer().setIcon(icon
);
713 public void setIndent(int indent
) {
714 if (control
.getLayout() instanceof TableWrapLayout
) {
715 TableWrapLayout layout
= ((TableWrapLayout
) control
.getLayout());
716 layout
.leftMargin
= indent
;
717 layout
.rightMargin
= ACCEPTED_INDENT
;
718 control
.setLayout(layout
);
721 new RuntimeException(
722 "Couldn't indent - composite's layout must be TableWrapLayout."); //$NON-NLS-1$
731 public void setSelected() {
732 getNameViewer().getTextWidget().setFocus();
742 public boolean isSelected() {
743 return getEditor().getSelectedContainer() == this;
754 public void colorSelected(int mode
) {
755 if (!control
.isDisposed()) {
756 String colorString
= null;
760 colorString
= Resources
.COLOR_CONTROL_SELECTED_FOCUS
;
762 case SELECTED_NO_FOCUS
:
763 colorString
= Resources
.COLOR_CONTROL_SELECTED
;
766 colorString
= Resources
.COLOR_COMPOSITE_BACKGROUND
;
769 backgroundColor
= EditorUtil
.getColor(colorString
);
771 setBackground(backgroundColor
);
777 * setDelayedSelection
780 protected void setDelayedSelection() {
781 // TODO this might be done better
782 // this is the quickest solution i could come up with and it improves
784 // please reimplement if you know better.
788 Display display
= Display
.getCurrent();
789 Runnable runnable
= new Runnable() {
793 getEditor().getManagedForm().setInput(selection
);
796 display
.timerExec(1000, runnable
);
806 * a {@link org.eclipse.swt.graphics.Color} object.
808 public void setBackground(Color color
) {
809 control
.setBackground(color
);
811 for (Control child
: control
.getChildren()) {
812 child
.setBackground(color
);
815 getNameViewer().setBackground(color
);
822 * org.eclipse.swt.widgets.Control#setFont(org.eclipse.swt.graphics.Font)
830 * a {@link org.eclipse.swt.graphics.Font} object.
832 public void setFont(Font font
) {
833 getNameViewer().getTextWidget().setFont(font
);
838 * Getter for the field <code>nameViewer</code>.
841 * @return a {@link eu.etaxonomy.taxeditor.editor.name.container.NameViewer}
844 public NameViewer
getNameViewer() {
845 if (nameViewer
== null) {
846 throw new RuntimeException(
847 "The Name Viewer is corrupt for Name Container: " //$NON-NLS-1$
848 + getTaxonBase().getName().getTitleCache());
854 * If <code>textViewer</code> has already been set, it will show a
855 * <code>prompt</code> along the lines of
856 * "Click here to start entering data" when empty.
859 * a {@link java.lang.String} object.
861 public void createEmptyViewerPrompt(final String prompt
) {
863 Assert
.isNotNull(getNameViewer());
865 final StyledText textControl
= getNameViewer().getTextWidget();
866 final IDocument document
= getNameViewer().getDocument();
868 setFocusListener(new FocusListener() {
871 public void focusGained(FocusEvent e
) {
872 if (document
.get().equals(prompt
)) {
873 textControl
.setFont(getViewerFont());
874 document
.set(""); //$NON-NLS-1$
879 public void focusLost(FocusEvent e
) {
880 if (document
.getLength() == 0) {
886 textControl
.addFocusListener(getFocusListener());
888 if (document
.getLength() == 0) {
889 textControl
.setFont(EditorUtil
890 .getFont(Resources
.FONT_DEFAULT_PROMPT
));
891 document
.set(prompt
);
900 * @return a {@link org.eclipse.swt.graphics.Font} object.
902 abstract protected Font
getViewerFont();
909 protected void initEmptyText() {
910 Font defaultFont
= EditorUtil
.getFont(Resources
.FONT_DEFAULT_PROMPT
);
911 getNameViewer().getTextWidget().setFont(defaultFont
);
913 getNameViewer().getDocument().set(getEmptyTextPrompt());
919 * Setter for the field <code>focusListener</code>.
922 * @param focusListener
923 * a {@link org.eclipse.swt.events.FocusListener} object.
925 protected void setFocusListener(FocusListener focusListener
) {
926 this.focusListener
= focusListener
;
929 private FocusListener
getFocusListener() {
930 return focusListener
;
941 public void setDirty(boolean isDirty
) {
943 getEditor().getManagedForm().dirtyStateChanged();
945 this.isDirty
= isDirty
;
956 public boolean isDirty() {
966 * a {@link org.eclipse.swt.widgets.Menu} object.
968 public void setMenu(Menu menu
) {
969 control
.setMenu(menu
);
971 getNameViewer().setMenu(menu
);
974 private Control
[] draggableControls
;
978 * setDraggableControl
982 * an array of {@link org.eclipse.swt.widgets.Control} objects.
984 protected void setDraggableControl(Control
[] controls
) {
985 draggableControls
= controls
;
996 public void setIsDraggable(boolean draggable
) {
1000 if (draggableControls
== null) {
1001 throw new NullPointerException(
1002 "Draggable controls must be set to add draggability"); //$NON-NLS-1$
1005 Transfer
[] types
= new Transfer
[] { CdmDataTransfer
.getInstance() };
1006 int operations
= DND
.DROP_MOVE
;
1008 for (Control draggableControl
: draggableControls
) {
1009 DragSource dragSource
= new DragSource(draggableControl
,
1011 dragSource
.setTransfer(types
);
1013 dragSource
.addDragListener(new NameEditorDragListener(this));
1014 dragSource
.setDragSourceEffect(new NameEditorDragSourceEffect(
1020 private String nonEditableText
;
1022 ControlListener nonEditableResizeListener
= new ControlAdapter() {
1027 public void controlResized(ControlEvent e
) {
1028 if (nonEditableInfoLabel
.getBounds().width
== width
) {
1031 width
= nonEditableInfoLabel
.getBounds().width
;
1032 if (nonEditableInfoLabel
.getBounds().width
> 0) {
1033 nonEditableInfoLabel
.setText(Dialog
.shortenText(
1034 nonEditableText
.toUpperCase(), nonEditableInfoLabel
));
1039 private String nonEditableHoverText
;
1041 private LabelEllipsisListener nonEditableLabelEllipsisListener
;
1045 private boolean enabled
;
1048 * nonEditableInfo is a label displayed underneath a GroupedComposite's
1049 * input field. For instance, NameComposites display things like name
1050 * relations, sec. references, etc. here.
1053 * the text to display in the label
1055 * whether the string should be appended to text that is already
1056 * shown in the label
1058 public void setNonEditableInfo(String info
, boolean append
) {
1059 // TODO non editable info should only be drawn once, when everything
1061 info
= info
.toUpperCase();
1064 nonEditableText
+= ", " + info
; //$NON-NLS-1$
1065 nonEditableHoverText
+= "\n" + info
; //$NON-NLS-1$
1067 nonEditableText
= info
;
1068 nonEditableHoverText
= info
;
1071 if (nonEditableInfoLabel
== null) {
1072 nonEditableInfoLabel
= getEditor().getToolkit().createLabel(
1073 control
, ""); //$NON-NLS-1$
1074 TableWrapData layoutData
= new TableWrapData(
1075 TableWrapData
.FILL_GRAB
, TableWrapData
.TOP
);
1076 // Set indent to viewer ruler's width
1077 if (getNameViewer().getRulerControl() != null) {
1078 // TODO right justify
1079 layoutData
.indent
= NameViewer
.RULER_WIDTH
;
1081 nonEditableInfoLabel
.setLayoutData(layoutData
);
1083 nonEditableLabelEllipsisListener
= new LabelEllipsisListener(
1084 nonEditableInfoLabel
) {
1086 public String
getLabelText() {
1087 return nonEditableText
.toUpperCase();
1090 nonEditableInfoLabel
1091 .addControlListener(nonEditableLabelEllipsisListener
);
1093 nonEditableInfoHover
= new DefaultToolTip(nonEditableInfoLabel
);
1094 nonEditableInfoHover
.setRespectDisplayBounds(true);
1097 nonEditableInfoHover
.setText(nonEditableHoverText
);
1098 nonEditableInfoLabel
.setText(nonEditableText
);
1100 calculateAnnotations();
1105 * Getter for the field <code>data</code>.
1108 * @return a T object.
1111 public T
getData() {
1117 * Setter for the field <code>data</code>.
1123 public void setData(T data
) {
1124 this.data
= HibernateProxyHelper
.deproxy(data
);
1128 * If the user hitting carriage return should cause something to happen -
1129 * i.e. the creation of a new composite - call this method and override the
1130 * method handleSplitText().
1132 protected void createLineBreakListener() {
1133 lineBreakListener
= new LineBreakListener() {
1135 public void handleSplitText(String text
) {
1136 AbstractGroupedContainer
.this.handleSplitText(text
);
1141 getNameViewer().getTextWidget().addVerifyListener(lineBreakListener
);
1145 abstract class LabelEllipsisListener
extends ControlAdapter
{
1147 private final Label label
;
1150 LabelEllipsisListener(Label label
) {
1154 abstract public String
getLabelText();
1157 public void controlResized(ControlEvent e
) {
1158 if (label
.getBounds().width
== width
) {
1161 width
= label
.getBounds().width
;
1162 if (label
.getBounds().width
> 0) {
1163 label
.setText(TextHelper
.shortenText(getLabelText(), label
));
1173 public void storeCursor() {
1174 this.cursorPosition
= getNameViewer().getCursorPosition();
1178 * Puts the cursor to the position it was last seen on or to the end of line
1179 * if no former position is known.
1181 public void placeCursor() {
1182 if (cursorPosition
== 0) {
1183 getNameViewer().setCursorToEOL();
1185 getNameViewer().setCursorPosition(cursorPosition
);
1191 * Setter for the field <code>group</code>.
1196 * {@link eu.etaxonomy.taxeditor.editor.name.container.AbstractGroup}
1199 public void setGroup(AbstractGroup group
) {
1208 public void restoreColor() {
1209 setBackground(backgroundColor
);
1216 * org.eclipse.ui.forms.IFormPart#initialize(org.eclipse.ui.forms.IManagedForm
1220 public void initialize(IManagedForm form
) {
1221 // TODO Auto-generated method stub
1228 * @see org.eclipse.ui.forms.IFormPart#dispose()
1231 public void dispose() {
1232 if (getControl() != null) {
1234 getControl().dispose();
1241 * @see org.eclipse.ui.forms.IFormPart#commit(boolean)
1244 public void commit(boolean onSave
) {
1253 * @see org.eclipse.ui.forms.IFormPart#setFormInput(java.lang.Object)
1256 public boolean setFormInput(Object input
) {
1263 * @see org.eclipse.ui.forms.IFormPart#setFocus()
1266 public void setFocus() {
1267 getNameViewer().getControl().setFocus();
1273 * @see org.eclipse.ui.forms.IFormPart#isStale()
1276 public boolean isStale() {
1280 public void setDisabled(boolean disabled
) {
1281 this.enabled
= !disabled
;
1282 setEnabled(enabled
);
1285 public void setEnabled(boolean enabled
) {
1286 this.enabled
= enabled
;
1287 Color color
= enabled ? control
.getForeground() : EditorUtil
.getColor(Resources
.COLOR_DISABLED_EDITOR
);
1289 getNameViewer().getTextWidget().setEditable(enabled
);
1290 getNameViewer().getTextWidget().setEnabled(enabled
);
1291 getNameViewer().getTextWidget().setForeground(color
);
1294 public boolean isEnabled(){