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
;
12 import org
.apache
.log4j
.Logger
;
13 import org
.eclipse
.core
.runtime
.Assert
;
14 import org
.eclipse
.jface
.text
.IDocument
;
15 import org
.eclipse
.jface
.text
.TextViewer
;
16 import org
.eclipse
.jface
.viewers
.ISelection
;
17 import org
.eclipse
.jface
.viewers
.ISelectionChangedListener
;
18 import org
.eclipse
.jface
.viewers
.ISelectionProvider
;
19 import org
.eclipse
.swt
.SWT
;
20 import org
.eclipse
.swt
.custom
.StyledText
;
21 import org
.eclipse
.swt
.dnd
.DND
;
22 import org
.eclipse
.swt
.dnd
.DragSource
;
23 import org
.eclipse
.swt
.dnd
.DragSourceAdapter
;
24 import org
.eclipse
.swt
.dnd
.DragSourceEvent
;
25 import org
.eclipse
.swt
.dnd
.DragSourceListener
;
26 import org
.eclipse
.swt
.dnd
.Transfer
;
27 import org
.eclipse
.swt
.events
.FocusAdapter
;
28 import org
.eclipse
.swt
.events
.FocusEvent
;
29 import org
.eclipse
.swt
.events
.FocusListener
;
30 import org
.eclipse
.swt
.events
.ModifyListener
;
31 import org
.eclipse
.swt
.graphics
.Color
;
32 import org
.eclipse
.swt
.graphics
.Font
;
33 import org
.eclipse
.swt
.graphics
.Image
;
34 import org
.eclipse
.swt
.widgets
.Composite
;
35 import org
.eclipse
.swt
.widgets
.Control
;
36 import org
.eclipse
.swt
.widgets
.Label
;
37 import org
.eclipse
.ui
.forms
.IManagedForm
;
38 import org
.eclipse
.ui
.forms
.widgets
.TableWrapData
;
39 import org
.eclipse
.ui
.forms
.widgets
.TableWrapLayout
;
41 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
42 import eu
.etaxonomy
.taxeditor
.ITaxEditorConstants
;
43 import eu
.etaxonomy
.taxeditor
.TaxEditorPlugin
;
44 import eu
.etaxonomy
.taxeditor
.actions
.WidgetTransfer
;
45 import eu
.etaxonomy
.taxeditor
.editor
.name
.NameViewer
;
48 * Formats <code>GroupedComposite</code> with cosmetic and layout properties specific to the
49 * Editor. This should be used to maintain a consistent look and feel for all Editor
50 * freetext area components, such as DescriptionElementComposite.
52 * Requires an <code>IManagedForm</code>, whose <code>input</code> is set to the contents
53 * of {@link #getData()} when the <code>GroupedComposite</code> gets focus, i.e. to
54 * populate the property sheet with the data.
57 * The <code>IManagedForm</code> is also required to have a <code>Taxon</code> in its
58 * own <code>getData()</code>.
61 * The <code>IManagedForm</code> can also used for drawing borders by calling the method
62 * <code>createBorderSupport()</code>.
68 abstract public class GroupedComposite
extends Composite
implements IHasPropertySource
{
69 private static final Logger logger
= Logger
.getLogger(GroupedComposite
.class);
71 protected NameViewer textViewer
;
72 protected IManagedForm managedForm
;
73 private Label nonEditableInfo
;
75 protected Taxon taxon
;
77 private CompositeBorderDecorator borderDecorator
;
78 private FocusListener focusListener
;
79 private LineBreakListener lineBreakListener
;
80 private ParseListener parseListener
;
86 public GroupedComposite(Composite parent
, IManagedForm managedForm
) {
87 super(parent
, SWT
.NONE
);
91 this.managedForm
= managedForm
;
93 Object formData
= managedForm
.getForm().getBody().getData();
94 Assert
.isTrue(formData
instanceof Taxon
,
95 "Managed form must have a Taxon in its data field.");
96 taxon
= (Taxon
) formData
;
99 protected void createLineWrapSupport() {
100 if (textViewer
instanceof NameViewer
) {
101 new LineWrapSupport(textViewer
, managedForm
);
103 logger
.warn("Can't create line wrap support because textViewer has not been initialized.");
107 protected void createContent() {
108 setLayoutData(new TableWrapData(TableWrapData
.FILL_GRAB
));
109 TableWrapLayout layout
= new TableWrapLayout();
110 layout
.leftMargin
= 0;
111 layout
.topMargin
= 0;
112 layout
.bottomMargin
= 0;
113 layout
.verticalSpacing
= 0;
116 Color groupBackgroundColor
= TaxEditorPlugin
.getDefault().
117 getColor(ITaxEditorConstants
.GROUP_GRAY_BKG_COLOR
);
118 setBackground(groupBackgroundColor
);
121 public Taxon
getTaxon() {
125 protected void createTextViewer() {
126 textViewer
= new NameViewer(this);
128 focusListener
= new FocusAdapter() {
129 public void focusGained(FocusEvent e
) {
134 textViewer
.getTextWidget().addFocusListener(focusListener
);
140 public void setIcon(Image icon
) {
141 if (textViewer
instanceof NameViewer
) {
142 textViewer
.setIcon(icon
);
144 logger
.warn("Can't set icon because textViewer has not been initialized.");
151 public void setIndent(int indent
) {
152 if (getLayout() instanceof TableWrapLayout
) {
153 TableWrapLayout layout
= ((TableWrapLayout
) getLayout());
154 layout
.leftMargin
= indent
;
155 this.setLayout(layout
);
157 logger
.warn("Couldn't indent - composite's layout must be TableWrapLayout.");
162 * @see org.eclipse.swt.widgets.Composite#setFocus()
164 public boolean setFocus() {
172 protected void setSelection() {
173 managedForm
.setInput(this);
177 * @see org.eclipse.swt.widgets.Control#setFont(org.eclipse.swt.graphics.Font)
179 public void setFont(Font font
) {
180 if (textViewer
!= null) {
181 textViewer
.getTextWidget().setFont(font
);
183 logger
.warn("Can't set font because textViewer has not been initalized.");
188 * If <code>textViewer</code> has already been set, it will show a
189 * <code>prompt</code> along the lines of "Click here to start entering data"
194 public void createEmptyViewerPrompt(final String prompt
) {
195 Assert
.isNotNull(textViewer
);
196 // new EmptyTextViewerPrompt(getTextViewer(), prompt);
198 final StyledText textControl
= textViewer
.getTextWidget();
199 final IDocument document
= textViewer
.getDocument();
200 final Font promptFont
= TaxEditorPlugin
.getDefault()
201 .getFont(ITaxEditorConstants
.DEFAULT_PROMPT_FONT
);
202 setFocusListener(new FocusListener() {
205 public void focusGained(FocusEvent e
) {
206 if (document
.get().equals(prompt
)) {
207 textControl
.setFont(getViewerFont());
213 public void focusLost(FocusEvent e
) {
214 if (document
.getLength() == 0) {
220 textControl
.addFocusListener(getFocusListener());
222 if (document
.getLength() == 0) {
223 textControl
.setFont(promptFont
);
224 document
.set(prompt
);
228 abstract protected Font
getViewerFont();
230 protected void initEmptyText() {
231 textViewer
.getTextWidget().setFont(
232 TaxEditorPlugin
.getDefault()
233 .getFont(ITaxEditorConstants
.DEFAULT_PROMPT_FONT
));
235 textViewer
.getDocument().set(getEmptyTextPrompt());
238 protected String
getEmptyTextPrompt() {
239 return "Click to edit";
242 private void setFocusListener(FocusListener focusListener
) {
243 this.focusListener
= focusListener
;
246 private FocusListener
getFocusListener() {
247 return focusListener
;
253 public void createBorderSupport() {
255 if (textViewer
== null) {
256 logger
.warn("Could not create border support - getTextViewer() returned null.");
258 borderDecorator
= new CompositeBorderDecorator(
259 textViewer
.getTextWidget(), managedForm
);
260 borderDecorator
.setLoseFocus(false);
261 textViewer
.getTextWidget().addFocusListener(borderDecorator
);
265 public void drawBorder() {
266 borderDecorator
.paintBorder();
272 protected void setDirty(boolean isDirty
) {
273 managedForm
.dirtyStateChanged();
276 protected ContextMenu
createContextMenu() {
277 if (textViewer
!= null) {
278 ContextMenu contextMenu
= new ContextMenu(textViewer
.getRulerControl());
279 textViewer
.getTextWidget().setMenu(contextMenu
.getMenu());
282 logger
.warn("Can't create menu because textViewer has not been initalized.");
287 public void unpaintBorder() {
288 if (borderDecorator
!= null) {
289 borderDecorator
.unpaintBorder();
293 private Control draggableControl
;
294 private DragSource dragSource
;
296 protected void setDraggableControl(Control control
) {
297 draggableControl
= control
;
300 public DragSource
getDragSource() {
304 public void setIsDraggable(boolean draggable
) {
308 if (dragSource
!= null) {
309 // Already initialized
313 if (draggableControl
== null) {
314 throw new NullPointerException(
315 "Draggable control must be set to add draggability");
318 Transfer
[] types
= new Transfer
[] { WidgetTransfer
.getInstance() };
319 int operations
= DND
.DROP_MOVE
| DND
.DROP_COPY
| DND
.DROP_LINK
;
321 dragSource
= new DragSource(draggableControl
, operations
);
322 dragSource
.setTransfer(types
);
323 dragSource
.addDragListener(dragSourceListener
);
331 * Drag listener which passes the Composite as the data in a drag event.
333 DragSourceListener dragSourceListener
= new DragSourceAdapter() {
335 public void dragStart(DragSourceEvent event
) {
336 if (textViewer
!= null) {
337 textViewer
.getTextWidget().setFocus();
342 public void dragSetData(DragSourceEvent event
) {
343 WidgetTransfer
.getInstance().setWidget(GroupedComposite
.this);
348 * nonEditableInfo is a label displayed underneath a GroupedComposite's
349 * input field. For instance, NameComposites display things like name relations,
350 * sec. references, etc. here.
354 public void setNonEditableInfo(String info
) {
355 if (nonEditableInfo
== null) {
356 nonEditableInfo
= new Label(this, SWT
.WRAP
);
357 nonEditableInfo
.setLayoutData(new TableWrapData(TableWrapData
.FILL_GRAB
, TableWrapData
.TOP
));
359 info
= nonEditableInfo
.getText() + ", " + info
;
361 nonEditableInfo
.setText(info
.toUpperCase());
365 * If the user entering text requires parsing, call this method and override
366 * the method parse().
368 protected void createParser() {
369 if (textViewer
!= null) {
370 parseListener
= new ParseListener() {
372 public void parse(String text
) {
373 GroupedComposite
.this.parse(text
);
376 textViewer
.getTextWidget().addModifyListener(parseListener
);
378 logger
.warn("Can't create parser because textViewer has not been initalized.");
382 protected void parse(String text
) {
383 logger
.warn("No parse method defined for this composite.");
387 * If the user hitting carriage return should cause something to happen -
388 * i.e. the creation of a new composite - call this method and override
389 * the method handleSplitText().
391 protected void createLineBreakListener() {
392 if (textViewer
!= null) {
393 lineBreakListener
= new LineBreakListener() {
395 public void handleSplitText(String text
) {
396 GroupedComposite
.this.handleSplitText(text
);
400 textViewer
.getTextWidget().addVerifyListener(lineBreakListener
);
401 textViewer
.getTextWidget().addKeyListener(lineBreakListener
);
403 logger
.warn("Can't create line break listener because textViewer has not been initalized.");
407 protected void handleSplitText(String text
) {
408 logger
.warn("No handleSplitText method defined for this composite.");
412 * @see eu.etaxonomy.taxeditor.editor.name.GroupedComposite#dispose()
414 public void dispose () {
416 if (dragSource
!= null) {
417 dragSource
.removeDragListener(dragSourceListener
);
420 if (textViewer
!= null) {
421 StyledText textWidget
= textViewer
.getTextWidget();
423 if (focusListener
!= null) {
424 textWidget
.removeFocusListener(focusListener
);
427 if (parseListener
!= null) {
428 textWidget
.removeModifyListener(parseListener
);
431 if (lineBreakListener
!= null) {
432 textWidget
.removeVerifyListener(lineBreakListener
);
433 textWidget
.removeKeyListener(lineBreakListener
);
436 if (borderDecorator
!= null) {
437 textWidget
.removeFocusListener(borderDecorator
);