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
;
12 import java
.lang
.reflect
.Method
;
15 import org
.apache
.log4j
.Logger
;
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
.TextViewer
;
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
.ModifyEvent
;
32 import org
.eclipse
.swt
.events
.ModifyListener
;
33 import org
.eclipse
.swt
.events
.MouseAdapter
;
34 import org
.eclipse
.swt
.events
.MouseEvent
;
35 import org
.eclipse
.swt
.graphics
.Color
;
36 import org
.eclipse
.swt
.graphics
.Font
;
37 import org
.eclipse
.swt
.graphics
.Image
;
38 import org
.eclipse
.swt
.widgets
.Composite
;
39 import org
.eclipse
.swt
.widgets
.Control
;
40 import org
.eclipse
.swt
.widgets
.Display
;
41 import org
.eclipse
.swt
.widgets
.Label
;
42 import org
.eclipse
.swt
.widgets
.Menu
;
43 import org
.eclipse
.ui
.IWorkbenchPart
;
44 import org
.eclipse
.ui
.forms
.widgets
.TableWrapData
;
45 import org
.eclipse
.ui
.forms
.widgets
.TableWrapLayout
;
47 import eu
.etaxonomy
.cdm
.common
.CdmUtils
;
48 import eu
.etaxonomy
.cdm
.hibernate
.HibernateProxyHelper
;
49 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
50 import eu
.etaxonomy
.cdm
.model
.name
.NameRelationship
;
51 import eu
.etaxonomy
.cdm
.model
.name
.NonViralName
;
52 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameBase
;
53 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
54 import eu
.etaxonomy
.taxeditor
.editor
.CdmDataTransfer
;
55 import eu
.etaxonomy
.taxeditor
.editor
.EditorUtil
;
56 import eu
.etaxonomy
.taxeditor
.labels
.ILabelImageStrategy
;
57 import eu
.etaxonomy
.taxeditor
.labels
.LabelImageProvider
;
58 import eu
.etaxonomy
.taxeditor
.model
.ImageResources
;
59 import eu
.etaxonomy
.taxeditor
.model
.NameHelper
;
60 import eu
.etaxonomy
.taxeditor
.model
.TextHelper
;
61 import eu
.etaxonomy
.taxeditor
.operations
.CreateSynonymInNewGroupOperation
;
62 import eu
.etaxonomy
.taxeditor
.parser
.ParseHandler
;
63 import eu
.etaxonomy
.taxeditor
.preference
.Resources
;
66 * Formats <code>GroupedComposite</code> with cosmetic and layout properties specific to the
67 * Editor. This should be used to maintain a consistent look and feel for all Editor
68 * freetext area components, such as DescriptionElementComposite.
70 * Requires an <code>IManagedForm</code>, whose <code>input</code> is set to the contents
71 * of {@link #getData()} when the <code>GroupedComposite</code> gets focus, i.e. to
72 * populate the property sheet with the data.
75 * The <code>IManagedForm</code> is also required to have a <code>Taxon</code> in its
76 * own <code>getData()</code>.
79 * The <code>IManagedForm</code> can also used for drawing borders by calling the method
80 * <code>createBorderSupport()</code>.
88 abstract public class AbstractGroupedContainer
<T
extends TaxonBase
> {
89 private static final Logger logger
= Logger
.getLogger(AbstractGroupedContainer
.class);
94 public static final int SELECTED_FOCUS
= 1;
95 /** Constant <code>SELECTED_NO_FOCUS=2</code> */
96 public static final int SELECTED_NO_FOCUS
= 2;
97 /** Constant <code>NOT_SELECTED=3</code> */
98 public static final int NOT_SELECTED
= 3;
101 * ************ COMPOSITE TYPES ************
103 public String compositeType
;
104 /** Constant <code>ACCEPTED_TAXON="accepted_name_composite"</code> */
105 public static final String ACCEPTED_TAXON
= "accepted_name_composite";
106 /** Constant <code>HOMOTYPIC_SYNONYM="homotypic_name_composite"</code> */
107 public static final String HOMOTYPIC_SYNONYM
= "homotypic_name_composite";
108 /** Constant <code>HETEROTYPIC_SYNONYM="heterotypic_name_composite"</code> */
109 public static final String HETEROTYPIC_SYNONYM
= "heterotypic_name_composite";
110 /** Constant <code>MISAPPLIED_NAME="misappliedname_name_composite"</code> */
111 public static final String MISAPPLIED_NAME
= "misappliedname_name_composite";
112 /** Constant <code>CONCEPTRELATION="concept_name_composite"</code> */
113 public static final String CONCEPTRELATION
= "concept_name_composite";
116 * ************ INDENTATIONS ************
118 public static final int ACCEPTED_INDENT
= 20;
119 /** Constant <code>SYNONYM_INDENT=40</code> */
120 public static final int SYNONYM_INDENT
= 40;
121 /** Constant <code>MISAPPLIEDNAME_INDENT=40</code> */
122 public static final int MISAPPLIEDNAME_INDENT
= 40;
123 /** Constant <code>CONCEPT_INDENT=40</code> */
124 public static final int CONCEPT_INDENT
= 40;
128 * ************ ICONS ************
130 public static final Image ACCEPTED_ICON
= ImageResources
.getImage(ImageResources
.BLACK_SQUARE_ICON
);
131 /** Constant <code>HOMOTYPIC_SYNONYM_ICON</code> */
132 public static final Image HOMOTYPIC_SYNONYM_ICON
= ImageResources
.getImage(ImageResources
.HOMOTYPIC_SYN_ICON
);
133 /** Constant <code>HOMOTYPIC_SYNONYM_ORIGINAL_COMBINATION_ICON</code> */
134 public static final Image HOMOTYPIC_SYNONYM_ORIGINAL_COMBINATION_ICON
= ImageResources
.getImage(
135 ImageResources
.HOMOTYPIC_SYN_ORIGINAL_ICON
);
136 /** Constant <code>HETEROTYPIC_SYNONYM_ICON</code> */
137 public static final Image HETEROTYPIC_SYNONYM_ICON
= ImageResources
.getImage(ImageResources
.HETEROTYPIC_SYN_ICON
);
138 /** Constant <code>HETEROTYPIC_SYNONYM_ORIGINAL_COMBINATION_ICON</code> */
139 public static final Image HETEROTYPIC_SYNONYM_ORIGINAL_COMBINATION_ICON
= ImageResources
.getImage(
140 ImageResources
.HETEROTYPIC_SYN_ORIGINAL_ICON
);
141 /** Constant <code>MISAPPLIEDNAME_ICON</code> */
142 public static final Image MISAPPLIEDNAME_ICON
= ImageResources
.getImage(ImageResources
.MISAPPLIED_NAME_ICON
);
143 /** Constant <code>CONCEPT_ICON</code> */
144 public static final Image CONCEPT_ICON
= ImageResources
.getImage(ImageResources
.CONCEPT_ICON
);
145 /** Constant <code>AUTONYM_ICON</code> */
146 public static final Image AUTONYM_ICON
= ImageResources
147 .getImage(ImageResources
.AUTONYM_ICON
);
148 /** Constant <code>MOVE</code> */
149 public static final Image MOVE
= ImageResources
.getImage(ImageResources
.MOVE_ICON
);
152 * ************ TRANSFORMATIONS ************
154 public static final String ADD_GROUP_BASIONYM
= "add_group_basionym";
155 /** Constant <code>REMOVE_GROUP_BASIONYM="remove_group_basionym"</code> */
156 public static final String REMOVE_GROUP_BASIONYM
= "remove_group_basionym";
158 private static final String EMPTY_NAME_PROMPT
= "Click to add name";
160 protected ParseHandler parseHandler
;
162 private FocusListener nameCompositeFocusListener
;
163 private ModifyListener nameCompositeModifyListener
;
165 final Color not_editable_color
= new Color(Display
.getDefault(), 105, 114, 124);
168 * 1st column: Return value expected from the last method mentioned in the object path (3rd column et seq.) to enable the freetext.
169 * 2nd column: The class the last method mentioned in the object path should be a member of. This should be null if there is no need to narrow this.
170 * 3rd column et seq.: The sequence of method names reflects the object path to the desired method starting from a member of TaxonBase.
172 private Object
[][] enableFreetextFor
= {
173 {"", null, "getName", "getAppendedPhrase"},
174 {false, null, "getName", "isProtectedAuthorshipCache"},
175 {false, null, "getName", "isProtectedNameCache"},
176 // {false, "eu.etaxonomy.cdm.model.agent.Team", "getName", "getCombinationAuthorTeam", "isProtectedNomenclaturalTitleCache"}
181 protected TaxonNameEditor editor
;
183 protected NameViewer nameViewer
;
185 private AbstractGroup
<T
> group
;
187 private Label nonEditableInfoLabel
;
188 private DefaultToolTip nonEditableInfoHover
;
190 private static AbstractGroupedContainer selection
;
192 private FocusListener focusListener
;
193 private LineBreakListener lineBreakListener
;
195 private int cursorPosition
;
197 protected Composite control
;
199 private Color backgroundColor
;
202 * <p>Constructor for AbstractGroupedContainer.</p>
204 * @param editor a {@link eu.etaxonomy.taxeditor.editor.name.TaxonNameEditor} object.
205 * @param group a {@link eu.etaxonomy.taxeditor.editor.name.AbstractGroup} object.
206 * @param taxonBase a T object.
207 * @param <T> a T object.
209 public AbstractGroupedContainer(TaxonNameEditor editor
, AbstractGroup
<T
> group
, T taxonBase
){
210 this.editor
= editor
;
220 createLineWrapSupport();
221 createLineBreakListener();
223 setMenu(editor
.getMenu());
225 setDraggableControl(new Control
[]{getControl(), getNameViewer().getRulerControl()});
227 createEmptyViewerPrompt(EMPTY_NAME_PROMPT
);
229 parseHandler
= ParseHandler
.NewInstance(getNameViewer().getTextWidget(), taxonBase
.getName());
231 initializeComposite();
237 logger
.trace(this.getClass().getSimpleName() + " created");
243 * <p>createListener</p>
245 protected void createListener(){
246 nameCompositeModifyListener
= new ModifyListener(){
248 public void modifyText(ModifyEvent e
) {
249 // mark the composite dirty
252 NonViralName name
= parseHandler
.parse();
253 getTaxonBase().setName(name
);
254 getTaxonBase().setTitleCache((getTaxonBase().generateTitle()));
256 // show errors resulting from parsing
258 // store the position of the cursor
260 // notify selection listener
261 setDelayedSelection();
264 nameCompositeFocusListener
= new FocusAdapter(){
267 * @see org.eclipse.swt.events.FocusAdapter#focusLost(org.eclipse.swt.events.FocusEvent)
270 public void focusLost(FocusEvent e
) {
280 private void addListener(){
281 getNameViewer().getTextWidget().addModifyListener(nameCompositeModifyListener
);
282 getNameViewer().getTextWidget().addFocusListener(nameCompositeFocusListener
);
285 private void removeListener(){
286 getNameViewer().getTextWidget().removeModifyListener(nameCompositeModifyListener
);
287 getNameViewer().getTextWidget().removeFocusListener(nameCompositeFocusListener
);
291 * Initialize the composite specific code
293 protected abstract void initializeComposite();
296 * <p>getEmptyTextPrompt</p>
298 * @return a {@link java.lang.String} object.
300 protected String
getEmptyTextPrompt() {
301 return EMPTY_NAME_PROMPT
;
307 private void showNameRelations() {
308 TaxonNameBase
<?
, ?
> name
= getName();
313 ILabelImageStrategy strategy
= LabelImageProvider
.getLabelStrategy(name
);
314 LabelImageProvider labelProvider
= new LabelImageProvider(strategy
);
316 Set
<NameRelationship
> nameRelations
= name
.getNameRelations();
317 if (nameRelations
.size() == 0) {
320 for (NameRelationship nameRelation
: nameRelations
) {
321 String typeLabel
= null;
322 TaxonNameBase
<?
, ?
> relatedName
= null;
324 if (name
.equals(nameRelation
.getFromName())) {
325 typeLabel
= labelProvider
.getNameRelationTypeLabel(
326 nameRelation
.getType());
327 relatedName
= nameRelation
.getToName();
329 typeLabel
= labelProvider
.getNameRelationTypeInverseLabel(
330 nameRelation
.getType());
331 relatedName
= nameRelation
.getFromName();
334 // setNonEditableInfo(typeLabel + " " + NameHelper.getDisplayName(relatedName));
339 * <p>initTextViewer</p>
341 protected void initTextViewer() {
345 String text
= NameHelper
.getDisplayNameWithRef(getData());
347 if (text
.length() == 0) {
350 getNameViewer().setText(text
);
357 * <p>calculateErrors</p>
359 synchronized protected void calculateErrors() {
360 getNameViewer().clearErrors();
361 getNameViewer().setShowParsingErrors(getName());
365 * <p>handleSplitText</p>
367 * @param text a {@link java.lang.String} object.
369 protected void handleSplitText(String text
) {
370 // Create a synonym in a new homotypic group using text as name
371 TaxonNameBase synonymName
= ParseHandler
.quickParse(text
);
373 EditorUtil
.executeOperation(new CreateSynonymInNewGroupOperation
374 ("New Heterotypic Synonym", editor
.getUndoContext(), editor
.getTaxon(), synonymName
, editor
));
375 logger
.debug("new heterotypic synonym created through entering of line break");
379 * Refreshes the display with latest data from the model.
381 * Note: Will not parse the text and not calculate errors!
383 public void refresh() {
386 String text
= NameHelper
.getDisplayNameWithRef(getTaxonBase());
388 if (text
.length() == 0) {
392 getNameViewer().getTextWidget().setText(text
);
396 updateNonEditableInfo();
404 * <p>updateNonEditableInfo</p>
406 protected abstract void updateNonEditableInfo();
411 private void isFreeTextEnabled() {
412 // Decide whether editing of freetext is allowed or not.
413 if (freetextEditingAllowed()) {
416 getNameViewer().getTextWidget().setEditable(true);
418 // restore foreground font color again
419 getNameViewer().getTextWidget().setForeground(control
.getForeground());
422 getNameViewer().getTextWidget().setEditable(false);
424 // grey out text as a non-editable indicator
425 getNameViewer().getTextWidget().setForeground(not_editable_color
);
430 * Checks whether the freetext should be editable based on specific empty fields.
433 private boolean freetextEditingAllowed() {
434 boolean enableFreetext
= true;
436 enableFreetext
&= taxonFieldsEmpty();
438 return enableFreetext
;
442 * Checks whether specific fields of specific type have specific values.
443 * This generic implementation can easily go completely nuts if enableFreetextFor was filled wrong.
446 private boolean taxonFieldsEmpty() {
447 boolean enableFreetext
= true;
449 if (getTaxonBase() != null) {
450 for (Object
[] methodSequence
: enableFreetextFor
) {
451 int sequenceCount
= 0;
452 Object taxonObject
= HibernateProxyHelper
.deproxy(getTaxonBase());
453 Object referenceType
= null;
454 boolean useReference
= false;
455 Class
<?
extends CdmBase
> referenceInstance
= null;
456 for (Object method
: methodSequence
) {
459 if (sequenceCount
== 1) {
460 referenceType
= method
;
461 } else if (sequenceCount
== 2) {
463 if (method
!= null) {
464 referenceInstance
= (Class
<?
extends CdmBase
>) Class
.forName((String
) method
);
467 useReference
= false;
469 } catch (ClassNotFoundException e
) {
470 logger
.error("Class " + method
+ " could not be found: ", e
);
474 Method getter
= null;
476 if (taxonObject
!= null) { // authorTeams can be null
477 Class
<?
extends Object
> clazz
= taxonObject
.getClass();
478 boolean goOn
= false;
479 if (methodSequence
.length
== sequenceCount
) {
481 if (referenceInstance
.newInstance().isInstanceOf((Class
<?
extends CdmBase
>) clazz
)) {
494 getter
= clazz
.getMethod((String
)method
, (Class
<?
>[])null);
495 taxonObject
= HibernateProxyHelper
.deproxy(getter
.invoke(taxonObject
, (Object
[])null));
496 if (methodSequence
.length
== sequenceCount
) {
497 enableFreetext
&= isEqual(referenceType
, taxonObject
);
498 // if (!enableFreetext) {
499 // logger.error("Freetext disabled for: " + taxonBase);
504 } catch (Exception e
) {
506 logger
.error("Method " + method
+ " could not be called: " + e
.getMessage());
513 logger
.warn("TaxonBase is null. This should not happen.");
516 return enableFreetext
;
520 * Checks whether two objects are equal. Only works for cases of interest.
521 * @param referenceType
525 private boolean isEqual(Object referenceType
, Object object
) {
526 boolean equal
= false;
527 if (referenceType
instanceof Boolean
) {
528 if ((Boolean
)referenceType
.equals((Boolean
)object
)) {
534 // This can only be a String in our cases so far. Needs reimplementation in case this is not always the case.
535 if (referenceType
.equals(CdmUtils
.Nz((String
)object
))) {
545 * Parse the text and calculate errors
547 public void parseAndCalculateErrors(){
549 parseHandler
.parse();
555 * <p>getTaxonBase</p>
557 * @return the taxonBase
559 public T
getTaxonBase() {
566 * @return a {@link eu.etaxonomy.cdm.model.name.TaxonNameBase} object.
568 public TaxonNameBase
getName(){
569 return getTaxonBase().getName();
575 public void persistName(){
577 logger
.warn("Found dirty composite: " + this + ". Name: " + getNameViewer().getTextWidget().getText());
578 getTaxonBase().setName(parseHandler
.parseAndResolveDuplicates());
580 getTaxonBase().setTitleCache((getTaxonBase().generateTitle()));
586 * <p>Getter for the field <code>group</code>.</p>
588 * @return a {@link eu.etaxonomy.taxeditor.editor.name.AbstractGroup} object.
590 public AbstractGroup
getGroup(){
597 public void remove(){
598 getGroup().remove(this);
602 * <p>createControl</p>
604 protected void createControl() {
605 control
= editor
.getToolkit().createComposite(group
.getControl());
607 control
.setLayoutData(new TableWrapData(TableWrapData
.FILL_GRAB
));
608 TableWrapLayout layout
= new TableWrapLayout();
609 layout
.leftMargin
= 0;
610 layout
.rightMargin
= 0;
611 layout
.topMargin
= 5;
612 layout
.bottomMargin
= 5;
614 layout
.verticalSpacing
= 0;
615 layout
.horizontalSpacing
= 0;
617 control
.setLayout(layout
);
622 * <p>Getter for the field <code>control</code>.</p>
624 * @return a {@link org.eclipse.swt.widgets.Composite} object.
626 public Composite
getControl(){
631 * <p>createLineWrapSupport</p>
633 protected void createLineWrapSupport() {
634 new LineWrapSupport(getNameViewer(), editor
.getManagedForm());
639 * <p>createTextViewer</p>
641 protected void createTextViewer() {
642 nameViewer
= new NameViewer(control
);
644 focusListener
= new FocusAdapter() {
645 public void focusGained(FocusEvent e
) {
646 for(AbstractGroupedContainer container
: editor
.getGroupedContainers()){
647 container
.colorSelected(NOT_SELECTED
);
649 editor
.getManagedForm().setInput(AbstractGroupedContainer
.this);
651 colorSelected(SELECTED_FOCUS
);
654 nameViewer
.getTextWidget().addFocusListener(focusListener
);
657 MouseAdapter mouseListener
= new MouseAdapter() {
658 public void mouseDown(MouseEvent e
) {
662 control
.addMouseListener(mouseListener
);
663 nameViewer
.getRulerControl().addMouseListener(mouseListener
);
664 nameViewer
.getTextWidget().addMouseListener(mouseListener
);
670 * @param icon a {@link org.eclipse.swt.graphics.Image} object.
672 public void setIcon(Image icon
) {
673 getNameViewer().setIcon(icon
);
679 * @param indent a int.
681 public void setIndent(int indent
) {
682 if (control
.getLayout() instanceof TableWrapLayout
) {
683 TableWrapLayout layout
= ((TableWrapLayout
) control
.getLayout());
684 layout
.leftMargin
= indent
;
685 layout
.rightMargin
= ACCEPTED_INDENT
;
686 control
.setLayout(layout
);
688 logger
.warn("Couldn't indent - composite's layout must be TableWrapLayout.");
695 public void setSelected() {
696 getNameViewer().getTextWidget().setFocus();
704 public boolean isSelected(){
705 return editor
.getSelectedObject() == this;
709 * <p>colorSelected</p>
713 public void colorSelected(int mode
){
714 if(!control
.isDisposed()){
715 String colorString
= null;
719 colorString
= Resources
.COLOR_CONTROL_SELECTED_FOCUS
;
721 case SELECTED_NO_FOCUS
:
722 colorString
= Resources
.COLOR_CONTROL_SELECTED
;
725 colorString
= Resources
.COLOR_COMPOSITE_BACKGROUND
;
728 backgroundColor
= EditorUtil
.getColor(colorString
);
730 setBackground(backgroundColor
);
736 * <p>setDelayedSelection</p>
738 protected void setDelayedSelection(){
739 //TODO this might be done better
740 // this is the quickest solution i could come up with and it improves performance
741 // please reimplement if you know better.
745 Display display
= Display
.getCurrent();
746 Runnable runnable
= new Runnable() {
749 editor
.getManagedForm().setInput(selection
);
752 display
.timerExec(1000, runnable
);
757 * <p>setBackground</p>
759 * @param color a {@link org.eclipse.swt.graphics.Color} object.
761 public void setBackground(Color color
) {
762 control
.setBackground(color
);
764 for(Control child
: control
.getChildren()){
765 child
.setBackground(color
);
768 getNameViewer().setBackground(color
);
772 * @see org.eclipse.swt.widgets.Control#setFont(org.eclipse.swt.graphics.Font)
777 * @param font a {@link org.eclipse.swt.graphics.Font} object.
779 public void setFont(Font font
) {
780 getNameViewer().getTextWidget().setFont(font
);
784 * <p>Getter for the field <code>nameViewer</code>.</p>
786 * @return a {@link eu.etaxonomy.taxeditor.editor.name.NameViewer} object.
788 public NameViewer
getNameViewer() {
789 if (nameViewer
== null){
790 throw new RuntimeException("The Name Viewer is corrupt for Name Container: " + getTaxonBase().getName().getTitleCache());
796 * If <code>textViewer</code> has already been set, it will show a
797 * <code>prompt</code> along the lines of "Click here to start entering data"
800 * @param prompt a {@link java.lang.String} object.
802 public void createEmptyViewerPrompt(final String prompt
) {
804 Assert
.isNotNull(getNameViewer());
806 final StyledText textControl
= getNameViewer().getTextWidget();
807 final IDocument document
= getNameViewer().getDocument();
809 setFocusListener(new FocusListener() {
812 public void focusGained(FocusEvent e
) {
813 if (document
.get().equals(prompt
)) {
814 textControl
.setFont(getViewerFont());
820 public void focusLost(FocusEvent e
) {
821 if (document
.getLength() == 0) {
827 textControl
.addFocusListener(getFocusListener());
829 if (document
.getLength() == 0) {
830 textControl
.setFont(EditorUtil
.getFont(Resources
.FONT_DEFAULT_PROMPT
));
831 document
.set(prompt
);
836 * <p>getViewerFont</p>
838 * @return a {@link org.eclipse.swt.graphics.Font} object.
840 abstract protected Font
getViewerFont();
843 * <p>initEmptyText</p>
845 protected void initEmptyText() {
846 Font defaultFont
= EditorUtil
.getFont(Resources
.FONT_DEFAULT_PROMPT
);
847 getNameViewer().getTextWidget().setFont(defaultFont
);
849 getNameViewer().getDocument().set(getEmptyTextPrompt());
854 * <p>Setter for the field <code>focusListener</code>.</p>
856 * @param focusListener a {@link org.eclipse.swt.events.FocusListener} object.
858 protected void setFocusListener(FocusListener focusListener
) {
859 this.focusListener
= focusListener
;
862 private FocusListener
getFocusListener() {
863 return focusListener
;
869 * @param isDirty a boolean.
871 public void setDirty(boolean isDirty
) {
872 editor
.getManagedForm().dirtyStateChanged();
880 public boolean isDirty(){
881 return editor
.getManagedForm().isDirty();
887 * @param menu a {@link org.eclipse.swt.widgets.Menu} object.
889 public void setMenu (Menu menu
) {
890 control
.setMenu(menu
);
892 getNameViewer().setMenu(menu
);
895 private Control
[] draggableControls
;
898 * <p>setDraggableControl</p>
900 * @param controls an array of {@link org.eclipse.swt.widgets.Control} objects.
902 protected void setDraggableControl(Control
[] controls
) {
903 draggableControls
= controls
;
907 * <p>setIsDraggable</p>
909 * @param draggable a boolean.
911 public void setIsDraggable(boolean draggable
) {
915 if (draggableControls
== null) {
916 throw new NullPointerException(
917 "Draggable controls must be set to add draggability");
920 Transfer
[] types
= new Transfer
[] { CdmDataTransfer
.getInstance() };
921 int operations
= DND
.DROP_MOVE
;
923 for(Control draggableControl
: draggableControls
){
924 DragSource dragSource
= new DragSource(draggableControl
, operations
);
925 dragSource
.setTransfer(types
);
927 dragSource
.addDragListener(new NameEditorDragListener(this));
928 dragSource
.setDragSourceEffect(new NameEditorDragSourceEffect(control
));
933 private String nonEditableText
;
935 ControlListener nonEditableResizeListener
= new ControlAdapter() {
939 public void controlResized(ControlEvent e
) {
940 if (nonEditableInfoLabel
.getBounds().width
== width
) {
943 width
= nonEditableInfoLabel
.getBounds().width
;
944 if (nonEditableInfoLabel
.getBounds().width
> 0) {
945 nonEditableInfoLabel
.setText(
946 Dialog
.shortenText(nonEditableText
.toUpperCase(),
947 nonEditableInfoLabel
));
952 private String nonEditableHoverText
;
954 private LabelEllipsisListener nonEditableLabelEllipsisListener
;
959 * nonEditableInfo is a label displayed underneath a GroupedComposite's
960 * input field. For instance, NameComposites display things like name relations,
961 * sec. references, etc. here.
963 * @param info the text to display in the label
964 * @param append whether the string should be appended to text that is already shown in the label
966 public void setNonEditableInfo(String info
, boolean append
) {
967 // TODO non editable info should only be drawn once, when everything else is drawn
968 info
= info
.toUpperCase();
971 nonEditableText
+= ", " + info
;
972 nonEditableHoverText
+= "\n" + info
;
974 nonEditableText
= info
;
975 nonEditableHoverText
= info
;
978 if (nonEditableInfoLabel
== null) {
979 nonEditableInfoLabel
= editor
.getToolkit().createLabel(control
, "");
980 TableWrapData layoutData
= new TableWrapData(TableWrapData
.FILL_GRAB
, TableWrapData
.TOP
);
981 // Set indent to viewer ruler's width
982 if (getNameViewer().getRulerControl() != null) {
983 // TODO right justify
984 layoutData
.indent
= NameViewer
.RULER_WIDTH
;
986 nonEditableInfoLabel
.setLayoutData(layoutData
);
990 nonEditableLabelEllipsisListener
= new LabelEllipsisListener(nonEditableInfoLabel
) {
992 public String
getLabelText() {
993 return nonEditableText
.toUpperCase();
996 nonEditableInfoLabel
.addControlListener(nonEditableLabelEllipsisListener
);
998 nonEditableInfoHover
= new DefaultToolTip(nonEditableInfoLabel
);
999 nonEditableInfoHover
.setRespectDisplayBounds(true);
1002 nonEditableInfoHover
.setText(nonEditableHoverText
);
1003 nonEditableInfoLabel
.setText(nonEditableText
);
1007 * <p>Getter for the field <code>data</code>.</p>
1009 * @return a T object.
1016 * <p>Setter for the field <code>data</code>.</p>
1018 * @param data a T object.
1020 public void setData(T data
){
1021 this.data
= (T
) HibernateProxyHelper
.deproxy(data
);
1025 * If the user hitting carriage return should cause something to happen -
1026 * i.e. the creation of a new composite - call this method and override
1027 * the method handleSplitText().
1029 protected void createLineBreakListener() {
1030 lineBreakListener
= new LineBreakListener() {
1032 public void handleSplitText(String text
) {
1033 AbstractGroupedContainer
.this.handleSplitText(text
);
1037 getNameViewer().getTextWidget().addVerifyListener(lineBreakListener
);
1038 getNameViewer().getTextWidget().addKeyListener(lineBreakListener
);
1041 abstract class LabelEllipsisListener
extends ControlAdapter
{
1043 private Label label
;
1046 LabelEllipsisListener(Label label
) {
1050 abstract public String
getLabelText();
1052 public void controlResized(ControlEvent e
) {
1053 if (label
.getBounds().width
== width
) {
1056 width
= label
.getBounds().width
;
1057 if (label
.getBounds().width
> 0) {
1058 label
.setText(TextHelper
.shortenText(getLabelText(), label
));
1064 * <p>storeCursor</p>
1066 public void storeCursor() {
1067 this.cursorPosition
= getNameViewer().getCursorPosition();
1071 * Puts the cursor to the position it was last seen on or to the end of line
1072 * if no former position is known.
1074 public void placeCursor(){
1075 if(cursorPosition
== 0){
1076 getNameViewer().setCursorToEOL();
1078 getNameViewer().setCursorPosition(cursorPosition
);
1085 * <p>Setter for the field <code>group</code>.</p>
1087 * @param group a {@link eu.etaxonomy.taxeditor.editor.name.AbstractGroup} object.
1089 public void setGroup(AbstractGroup
<T
> group
) {
1096 * <p>restoreColor</p>
1098 public void restoreColor() {
1099 setBackground(backgroundColor
);