package LinGUIne.parts.advanced; import java.util.LinkedList; import org.eclipse.jface.dialogs.InputDialog; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.resource.FontDescriptor; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.ScrolledComposite; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.ControlListener; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.ColorDialog; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.List; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import LinGUIne.extensions.IEditorSettings; import LinGUIne.model.AnnotationSetContents; import LinGUIne.model.TextDataContents; import LinGUIne.model.annotations.IAnnotation; import LinGUIne.model.annotations.Tag; import LinGUIne.model.annotations.TextAnnotation; /** * Settings view for the TextAnnotationSetEditor to enable addition and removal * of Tags and Annotations. * * @author Kyle Mullins */ public class TextAnnotationSetSettings implements IEditorSettings { private Composite parentComposite; private GlobalPanel globalPanel; private TagPanel tagPanel; private LocalPanel localPanel; private TextAnnotationSetEditor parentEditor; private TextDataContents textContents; private AnnotationSetContents annotationContents; private Tag selectedTag; private LinkedList<IAnnotation> annotationsAtLocation; private IAnnotation selectedAnnotation; private int caretOffset; private Point selectionOffsets; /** * Creates a new settings view for the given TextAnnotationSetEditor and its * contents. * * @param editor The editor to which this settings view is tied. * @param data The text contents of the editor. * @param annotations The annotation contents of the editor. */ public TextAnnotationSetSettings(TextAnnotationSetEditor editor, TextDataContents data, AnnotationSetContents annotations){ parentEditor = editor; textContents = data; annotationContents = annotations; selectedTag = null; caretOffset = 0; annotationsAtLocation = new LinkedList<IAnnotation>(); selectedAnnotation = null; } @Override public void createComposite(Composite parent) { parentComposite = parent; parentComposite.setLayout(new GridLayout(1, false)); //Set up a scrollable container so the components aren't squashed final ScrolledComposite scrollable = new ScrolledComposite( parentComposite, SWT.V_SCROLL); scrollable.setLayoutData(new GridData(GridData.FILL_BOTH)); GridLayout layout = new GridLayout(1, false); layout.verticalSpacing = 15; final Composite container = new Composite(scrollable, SWT.NONE); container.setLayout(layout); scrollable.setContent(container); scrollable.setExpandHorizontal(true); scrollable.setExpandVertical(true); scrollable.addControlListener(new ControlListener(){ boolean haveResized; @Override public void controlMoved(ControlEvent e) {} @Override public void controlResized(ControlEvent e) { Rectangle r = scrollable.getClientArea(); if(!haveResized){ scrollable.setMinSize(parentComposite.computeSize(r.width, SWT.DEFAULT)); haveResized = true; } } }); globalPanel = new GlobalPanel(container); tagPanel = new TagPanel(container); localPanel = new LocalPanel(container); globalPanel.populate(); tagPanel.populate(); localPanel.populate(); } @Override public Composite getParent() { return parentComposite; } /** * Called whenever the caret position in the editor changes. * * @param newCaretOffset The new character offset of the caret. */ public void caretMoved(int newCaretOffset){ caretOffset = newCaretOffset; annotationsAtLocation.clear(); //Find all the annotations overlapping at the cursor location for(Tag tag: annotationContents.getTags()){ for(IAnnotation annotation: annotationContents.getAnnotations(tag)){ if(annotation instanceof TextAnnotation){ TextAnnotation textAnnotation = (TextAnnotation)annotation; if(textAnnotation.isIndexInRange(caretOffset)){ annotationsAtLocation.add(textAnnotation); } } } } if(localPanel != null){ localPanel.update(); } } /** * Called whenever the current selection in the editor changes. * * @param newSelectionOffsets The start and end position of the new * selection. */ public void selectionChanged(Point newSelectionOffsets){ if(newSelectionOffsets.x == newSelectionOffsets.y){ selectionOffsets = null; } else{ selectionOffsets = newSelectionOffsets; } } /** * Sub-panel for actions and information regarding the current caret * position or text selection in the editor. * * @author Kyle Mullins */ private class LocalPanel{ private Composite thePanel; private List lstTagsAtLocation; private Text txtAnnotationText; private Button btnAddAnnotation; private Button btnRemoveAnnotation; public LocalPanel(Composite parent){ thePanel = new Composite(parent, SWT.BORDER); thePanel.setLayout(new GridLayout(1, false)); GridData layoutData = new GridData(GridData.FILL_BOTH); layoutData.heightHint = 275; thePanel.setLayoutData(layoutData); } public void populate(){ Label lblHeader = new Label(thePanel, SWT.NONE); lblHeader.setText("Current Selection"); FontDescriptor descriptor = FontDescriptor.createFrom( lblHeader.getFont()); descriptor = descriptor.setStyle(SWT.BOLD).setHeight(10); lblHeader.setFont(descriptor.createFont(lblHeader.getDisplay())); Label lblTagsAtLocation = new Label(thePanel, SWT.NONE); lblTagsAtLocation.setText("Tags in selection:"); lstTagsAtLocation = new List(thePanel, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL); lstTagsAtLocation.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); lstTagsAtLocation.addSelectionListener(new SelectionListener(){ @Override public void widgetSelected(SelectionEvent e) { if(lstTagsAtLocation.getSelectionCount() != 0){ String selection = lstTagsAtLocation.getSelection()[0]; for(IAnnotation annotation: annotationsAtLocation){ if(annotation.getTag().getName().equals(selection)){ selectedAnnotation = annotation; } } } else{ selectedAnnotation = null; } update(false); } @Override public void widgetDefaultSelected(SelectionEvent e) {} }); Label lblSelectedAnnotation = new Label(thePanel, SWT.NONE); lblSelectedAnnotation.setText("Annotation text:"); txtAnnotationText = new Text(thePanel, SWT.BORDER | SWT.WRAP | SWT.V_SCROLL); txtAnnotationText.setLayoutData(new GridData(GridData.FILL_BOTH)); txtAnnotationText.setEditable(false); Composite annotationButtons = new Composite(thePanel, SWT.NONE); annotationButtons.setLayout(new GridLayout(2, false)); annotationButtons.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); btnAddAnnotation = new Button(annotationButtons, SWT.NONE); btnAddAnnotation.setText("Add"); btnAddAnnotation.addSelectionListener(new SelectionListener(){ @Override public void widgetSelected(SelectionEvent e) { int startIndex = selectionOffsets == null ? caretOffset - 1 : selectionOffsets.x; int length = selectionOffsets == null ? 1 : selectionOffsets.y - selectionOffsets.x; TextAnnotation newAnnotation = new TextAnnotation( selectedTag, startIndex, length); annotationContents.addAnnotation(newAnnotation); parentEditor.annotationsChanged(); parentEditor.setDirty(true); } @Override public void widgetDefaultSelected(SelectionEvent e) {} }); btnRemoveAnnotation = new Button(annotationButtons, SWT.NONE); btnRemoveAnnotation.setText("Remove"); btnRemoveAnnotation.addSelectionListener(new SelectionListener(){ @Override public void widgetSelected(SelectionEvent e) { annotationContents.removeAnnotation(selectedAnnotation); parentEditor.annotationsChanged(); parentEditor.setDirty(true); } @Override public void widgetDefaultSelected(SelectionEvent e) {} }); update(); } public void update(){ update(true); } private void update(boolean shouldUpdateList){ if(shouldUpdateList){ selectedAnnotation = null; lstTagsAtLocation.removeAll(); for(IAnnotation annotation: annotationsAtLocation){ lstTagsAtLocation.add(annotation.getTag().getName()); } if(!annotationsAtLocation.isEmpty()){ lstTagsAtLocation.setSelection(0); selectedAnnotation = annotationsAtLocation.getFirst(); } } if(selectedAnnotation != null){ if(selectedAnnotation instanceof TextAnnotation){ TextAnnotation textAnnotation = (TextAnnotation)selectedAnnotation; txtAnnotationText.setEnabled(true); txtAnnotationText.setText(textAnnotation.getText(textContents)); } else{ txtAnnotationText.setEnabled(false); txtAnnotationText.setText(""); } btnRemoveAnnotation.setEnabled(true); } else{ txtAnnotationText.setEnabled(false); txtAnnotationText.setText(""); btnRemoveAnnotation.setEnabled(false); } if(selectedTag != null){ btnAddAnnotation.setEnabled(true); } else{ btnAddAnnotation.setEnabled(false); } } } /** * Sub-panel for actions and information regarding the currently selected * Tag. * * @author Kyle Mullins */ private class TagPanel{ private Composite thePanel; private Label lblTagColor; private Button btnChangeColor; private Color defaultLabelColor; private Text txtTagComment; private Button chkTagEnabled; public TagPanel(Composite parent){ thePanel = new Composite(parent, SWT.BORDER); thePanel.setLayout(new GridLayout(1, false)); GridData layoutData = new GridData(GridData.FILL_BOTH); layoutData.heightHint = 175; thePanel.setLayoutData(layoutData); } public void populate(){ Label lblHeader = new Label(thePanel, SWT.NONE); lblHeader.setText("Current Tag"); FontDescriptor descriptor = FontDescriptor.createFrom( lblHeader.getFont()); descriptor = descriptor.setStyle(SWT.BOLD).setHeight(10); lblHeader.setFont(descriptor.createFont(lblHeader.getDisplay())); Composite colorPanel = new Composite(thePanel, SWT.NONE); colorPanel.setLayout(new GridLayout(3, false)); colorPanel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); Label lblColorText = new Label(colorPanel, SWT.NONE); lblColorText.setText("Color:"); lblTagColor = new Label(colorPanel, SWT.NONE); lblTagColor.setText(" "); btnChangeColor = new Button(colorPanel, SWT.NONE); btnChangeColor.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true, 1, 1)); btnChangeColor.setText("Change..."); btnChangeColor.addSelectionListener(new SelectionListener(){ @Override public void widgetSelected(SelectionEvent e) { ColorDialog newColorDialog = new ColorDialog( thePanel.getShell()); RGB selectedRGB = newColorDialog.open(); if(selectedRGB != null){ Color newColor = new Color(Display.getCurrent(), selectedRGB); if(!newColor.equals(selectedTag.getColor())){ selectedTag.setColor(newColor); parentEditor.annotationsChanged(); parentEditor.setDirty(true); update(); } } } @Override public void widgetDefaultSelected(SelectionEvent e) {} }); defaultLabelColor = lblTagColor.getBackground(); Label lblTagComment = new Label(thePanel, SWT.NONE); lblTagComment.setText("Comment:"); txtTagComment = new Text(thePanel, SWT.BORDER | SWT.V_SCROLL | SWT.WRAP); txtTagComment.setLayoutData(new GridData(GridData.FILL_BOTH)); txtTagComment.addModifyListener(new ModifyListener(){ @Override public void modifyText(ModifyEvent e) { if(selectedTag != null && !selectedTag.getComment().equals( txtTagComment.getText())){ selectedTag.setComment(txtTagComment.getText()); parentEditor.setDirty(true); } } }); chkTagEnabled = new Button(thePanel, SWT.CHECK); chkTagEnabled.setText("Is Enabled"); chkTagEnabled.addSelectionListener(new SelectionListener(){ @Override public void widgetSelected(SelectionEvent e) { selectedTag.setEnabled(chkTagEnabled.getSelection()); parentEditor.annotationsChanged(); } @Override public void widgetDefaultSelected(SelectionEvent e) {} }); update(); } public void update(){ if(selectedTag != null){ txtTagComment.setText(selectedTag.getComment()); chkTagEnabled.setSelection(selectedTag.getEnabled()); lblTagColor.setBackground(selectedTag.getColor()); txtTagComment.setEnabled(true); btnChangeColor.setEnabled(true); chkTagEnabled.setEnabled(true); } else{ txtTagComment.setText(""); chkTagEnabled.setSelection(false); lblTagColor.setBackground(defaultLabelColor); txtTagComment.setEnabled(false); btnChangeColor.setEnabled(false); chkTagEnabled.setEnabled(false); } } } /** * Sub-panel for actions and information regarding the entire contents of * the editor the settings panel is tied to. * * @author Kyle Mullins */ private class GlobalPanel{ private Composite thePanel; private List lstAllTags; private Button btnAddTag; public GlobalPanel(Composite parent){ thePanel = new Composite(parent, SWT.BORDER); thePanel.setLayout(new GridLayout(1, false)); GridData layoutData = new GridData(GridData.FILL_BOTH); layoutData.heightHint = 150; thePanel.setLayoutData(layoutData); } public void populate(){ Label lblHeader = new Label(thePanel, SWT.NONE); lblHeader.setText("Current File"); FontDescriptor descriptor = FontDescriptor.createFrom( lblHeader.getFont()); descriptor = descriptor.setStyle(SWT.BOLD).setHeight(10); lblHeader.setFont(descriptor.createFont(lblHeader.getDisplay())); lstAllTags = new List(thePanel, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL); lstAllTags.setLayoutData(new GridData(GridData.FILL_BOTH)); lstAllTags.addSelectionListener(new SelectionListener(){ @Override public void widgetSelected(SelectionEvent e) { if(lstAllTags.getSelectionCount() != 0){ String tagName = lstAllTags.getSelection()[0]; selectedTag = annotationContents.getTag(tagName); } else{ selectedTag = null; } localPanel.update(); tagPanel.update(); } @Override public void widgetDefaultSelected(SelectionEvent e) {} }); btnAddTag = new Button(thePanel, SWT.NONE); btnAddTag.setText("Add Tag"); btnAddTag.addSelectionListener(new SelectionListener(){ @Override public void widgetSelected(SelectionEvent e) { Shell theShell = thePanel.getShell(); InputDialog tagNamePrompt = new InputDialog(theShell, "New Tag", "Input new tag name:", "", null); if(tagNamePrompt.open() == InputDialog.OK){ String newTagName = tagNamePrompt.getValue(); if(!annotationContents.containsTag(newTagName)){ Tag newTag = new Tag(newTagName,Display.getCurrent(). getSystemColor(SWT.COLOR_BLUE), ""); annotationContents.addTag(newTag); selectedTag = newTag; update(); tagPanel.update(); } else{ MessageDialog.openError(theShell, "Error", "A tag already exists with the given name."); } } } @Override public void widgetDefaultSelected(SelectionEvent e) {} }); update(); } public void update(){ lstAllTags.removeAll(); for(Tag tag: annotationContents.getTags()){ lstAllTags.add(tag.getName()); } if(selectedTag != null){ lstAllTags.setSelection(new String[]{selectedTag.getName()}); } } } }