blob: c006558c9cf65773226eb150339c7ae1040f0361 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2009 Jingwen Ou and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Jingwen Ou - initial API and implementation
*******************************************************************************/
package org.eclipse.mylyn.internal.sandbox.ui.editors;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ControlContribution;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.FindReplaceDocumentAdapter;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.TextViewer;
import org.eclipse.mylyn.commons.ui.CommonImages;
import org.eclipse.mylyn.commons.workbench.editors.CommonTextSupport;
import org.eclipse.mylyn.commons.workbench.forms.CommonFormUtil;
import org.eclipse.mylyn.internal.bugzilla.ui.editor.BugzillaTaskEditorPage;
import org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPage;
import org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPart;
import org.eclipse.mylyn.tasks.ui.editors.TaskEditor;
import org.eclipse.mylyn.tasks.ui.editors.TaskEditorPartDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.RowData;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.editor.IFormPage;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.ScrolledForm;
/**
* A bugzilla task editor page that has wiki facilities.
*
* @author Jingwen Ou
*/
public class ExtensibleBugzillaTaskEditorPage extends BugzillaTaskEditorPage {
private Action toggleFindAction;
private static final Color HIGHLIGHTER_YELLOW = new Color(Display.getDefault(), 255, 238, 99);
private static final StyleRange HIGHLIGHT_STYLE_RANGE = new StyleRange(0, 0, null, HIGHLIGHTER_YELLOW);
public ExtensibleBugzillaTaskEditorPage(TaskEditor editor) {
super(editor);
}
private void addFindAction(IToolBarManager toolBarManager) {
if (toggleFindAction != null && toggleFindAction.isChecked()) {
ControlContribution findTextboxControl = new ControlContribution("Find") {
@Override
protected Control createControl(Composite parent) {
FormToolkit toolkit = getTaskEditor().getHeaderForm().getToolkit();
Composite findComposite = toolkit.createComposite(parent);
findComposite.setLayout(new RowLayout());
findComposite.setBackground(null);
final Text findText = toolkit.createText(findComposite, "", SWT.FLAT);
findText.setLayoutData(new RowData(100, SWT.DEFAULT));
findText.setData(FormToolkit.KEY_DRAW_BORDER, FormToolkit.TEXT_BORDER);
findText.setFocus();
toolkit.adapt(findText, false, false);
findText.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetDefaultSelected(SelectionEvent event) {
try {
setReflow(false);
findAndHighlight(ExtensibleBugzillaTaskEditorPage.this, findText.getText());
// always toggle attachment part close after every search, since all ExpandableComposites are open
AbstractTaskEditorPart attachmentsPart = getPart(AbstractTaskEditorPage.ID_PART_ATTACHMENTS);
CommonFormUtil.setExpanded((ExpandableComposite) attachmentsPart.getControl(), false);
} finally {
setReflow(true);
}
reflow();
}
});
toolkit.paintBordersFor(findComposite);
return findComposite;
}
};
toolBarManager.appendToGroup(IWorkbenchActionConstants.MB_ADDITIONS, findTextboxControl);
}
if (toggleFindAction == null) {
toggleFindAction = new Action("", SWT.TOGGLE) {
@Override
public void run() {
getTaskEditor().updateHeaderToolBar();
}
};
toggleFindAction.setImageDescriptor(CommonImages.FIND);
toggleFindAction.setToolTipText("Find");
//getManagedForm().getForm().setData(TaskEditorFindHandler.KEY_FIND_ACTION, toggleFindAction);
}
toolBarManager.appendToGroup(IWorkbenchActionConstants.MB_ADDITIONS, toggleFindAction);
}
@Override
public boolean canPerformAction(String actionId) {
if (actionId.equals(ActionFactory.FIND.getId())) {
return true;
}
return super.canPerformAction(actionId);
}
@Override
protected Set<TaskEditorPartDescriptor> createPartDescriptors() {
Set<TaskEditorPartDescriptor> descriptors = super.createPartDescriptors();
boolean hasPartNewComment = false;
for (TaskEditorPartDescriptor taskEditorPartDescriptor : descriptors) {
if (taskEditorPartDescriptor.getId().equals(ID_PART_NEW_COMMENT)) {
descriptors.remove(taskEditorPartDescriptor);
hasPartNewComment = true;
break;
}
}
if (hasPartNewComment) {
descriptors.add(new TaskEditorPartDescriptor(ID_PART_NEW_COMMENT) {
@Override
public AbstractTaskEditorPart createPart() {
return new ExtensibleTaskEditorNewCommentPart();
}
}.setPath(PATH_COMMENTS));
}
return descriptors;
}
@Override
public void doAction(String actionId) {
if (actionId.equals(ActionFactory.FIND.getId())) {
if (toggleFindAction != null) {
toggleFindAction.setChecked(!toggleFindAction.isChecked());
toggleFindAction.run();
}
}
super.doAction(actionId);
}
@Override
public void fillToolBar(IToolBarManager toolBarManager) {
super.fillToolBar(toolBarManager);
addFindAction(toolBarManager);
}
private static void findTextViewerControl(Composite composite, List<TextViewer> found) {
if (!composite.isDisposed()) {
for (Control child : composite.getChildren()) {
TextViewer viewer = CommonTextSupport.getTextViewer(child);
if (viewer != null && viewer.getDocument().get().length() > 0) {
found.add(viewer);
}
// have to do this since TaskEditorCommentPart.expendComment(..) will dispose the TextViewer when the ExpandableComposite is close
if (child instanceof ExpandableComposite) {
CommonFormUtil.setExpanded((ExpandableComposite) child, true);
}
if (child instanceof Composite) {
findTextViewerControl((Composite) child, found);
}
}
}
}
private static boolean findAndHighlightTextViewer(TextViewer viewer, FindReplaceDocumentAdapter adapter,
String findString, int startOffset) throws BadLocationException {
IRegion matchRegion = adapter.find(startOffset, findString, true, false, false, false);
if (matchRegion != null) {
int widgetOffset = matchRegion.getOffset();
int length = matchRegion.getLength();
HIGHLIGHT_STYLE_RANGE.start = widgetOffset;
HIGHLIGHT_STYLE_RANGE.length = length;
viewer.getTextWidget().setStyleRange(HIGHLIGHT_STYLE_RANGE);
findAndHighlightTextViewer(viewer, adapter, findString, widgetOffset + length);
return true;
}
return false;
}
public static void findAndHighlight(IFormPage page, String findString) {
IManagedForm form = page.getManagedForm();
if (form == null) {
return;
}
ScrolledForm scrolledForm = form.getForm();
if (scrolledForm == null) {
return;
}
List<TextViewer> found = new ArrayList<TextViewer>();
findTextViewerControl(scrolledForm.getBody(), found);
for (TextViewer viewer : found) {
try {
// Wiping previous highlighted element
viewer.setRedraw(false);
viewer.refresh();
viewer.setRedraw(true);
FindReplaceDocumentAdapter adapter = new FindReplaceDocumentAdapter(viewer.getDocument());
if (!findAndHighlightTextViewer(viewer, adapter, findString, -1)) {
// toggle close if can't match the keyword
Composite comp = viewer.getControl().getParent();
while (comp != null) {
if (comp instanceof ExpandableComposite) {
ExpandableComposite ex = (ExpandableComposite) comp;
CommonFormUtil.setExpanded(ex, false);
break;
}
comp = comp.getParent();
}
}
} catch (BadLocationException e) {
//ignore
}
}
}
}