package com.redhat.ceylon.eclipse.code.search; import static com.redhat.ceylon.eclipse.code.editor.Navigation.gotoLocation; import static com.redhat.ceylon.eclipse.code.preferences.CeylonPreferenceInitializer.FULL_LOC_SEARCH_RESULTS; import static com.redhat.ceylon.eclipse.code.search.CeylonSearchResultTreeContentProvider.LEVEL_FILE; import static com.redhat.ceylon.eclipse.code.search.CeylonSearchResultTreeContentProvider.LEVEL_FOLDER; import static com.redhat.ceylon.eclipse.code.search.CeylonSearchResultTreeContentProvider.LEVEL_MODULE; import static com.redhat.ceylon.eclipse.code.search.CeylonSearchResultTreeContentProvider.LEVEL_PACKAGE; import static com.redhat.ceylon.eclipse.code.search.CeylonSearchResultTreeContentProvider.LEVEL_PROJECT; import static com.redhat.ceylon.eclipse.ui.CeylonPlugin.PLUGIN_ID; import static com.redhat.ceylon.eclipse.ui.CeylonPlugin.getOutlineFont; import static com.redhat.ceylon.eclipse.ui.CeylonResources.CEYLON_SEARCH; import static com.redhat.ceylon.eclipse.ui.CeylonResources.CONFIG_LABELS; import static com.redhat.ceylon.eclipse.ui.CeylonResources.FLAT_MODE; import static com.redhat.ceylon.eclipse.ui.CeylonResources.FOLDER_MODE; import static com.redhat.ceylon.eclipse.ui.CeylonResources.MODULE_MODE; import static com.redhat.ceylon.eclipse.ui.CeylonResources.PACKAGE_MODE; import static com.redhat.ceylon.eclipse.ui.CeylonResources.PROJECT_MODE; import static com.redhat.ceylon.eclipse.ui.CeylonResources.TREE_MODE; import static com.redhat.ceylon.eclipse.ui.CeylonResources.UNIT_MODE; import static org.eclipse.jface.action.IAction.AS_CHECK_BOX; import static org.eclipse.search.ui.IContextMenuConstants.GROUP_VIEWER_SETUP; import static org.eclipse.ui.PlatformUI.getWorkbench; import static org.eclipse.ui.dialogs.PreferencesUtil.createPreferenceDialogOn; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.Path; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.internal.ui.search.JavaSearchEditorOpener; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IStatusLineManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.StructuredViewer; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.search.ui.text.AbstractTextSearchViewPage; import org.eclipse.search.ui.text.Match; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PartInitException; import org.eclipse.ui.contexts.IContextActivation; import org.eclipse.ui.contexts.IContextService; import org.eclipse.ui.part.IPageSite; import org.eclipse.ui.texteditor.ITextEditor; import com.redhat.ceylon.eclipse.code.editor.CeylonEditor; import com.redhat.ceylon.eclipse.code.preferences.CeylonFiltersPreferencePage; import com.redhat.ceylon.eclipse.code.preferences.CeylonOutlinesPreferencePage; import com.redhat.ceylon.eclipse.ui.CeylonPlugin; public class CeylonSearchResultPage extends AbstractTextSearchViewPage { private CeylonStructuredContentProvider contentProvider; private IPropertyChangeListener propertyChangeListener; @Override public void init(IPageSite site) { super.init(site); propertyChangeListener = new IPropertyChangeListener() { @Override public void propertyChange( PropertyChangeEvent event) { StructuredViewer viewer = getViewer(); viewer.getControl() .setFont(getOutlineFont()); viewer.refresh(); } }; CeylonPlugin.getPreferences() .addPropertyChangeListener( propertyChangeListener); getWorkbench() .getThemeManager() .addPropertyChangeListener( propertyChangeListener); } @Override public void dispose() { super.dispose(); if (propertyChangeListener!=null) { CeylonPlugin.getPreferences() .removePropertyChangeListener( propertyChangeListener); getWorkbench() .getThemeManager() .removePropertyChangeListener( propertyChangeListener); propertyChangeListener = null; } } public CeylonSearchResultPage() { super(FLAG_LAYOUT_FLAT|FLAG_LAYOUT_TREE); setElementLimit(50); initGroupingActions(); } @Override protected void clear() { if (contentProvider!=null) { contentProvider.clear(); } //getViewer().refresh(); } private void configureViewer(StructuredViewer viewer) { viewer.setContentProvider(contentProvider); viewer.setLabelProvider(new MatchCountingLabelProvider(this)); viewer.setComparator(new CeylonViewerComparator()); viewer.getControl().setFont(getOutlineFont()); final IContextService contextService = (IContextService) getWorkbench() .getService(IContextService.class); viewer.getControl() .addFocusListener(new FocusListener() { private IContextActivation activation; @Override public void focusLost(FocusEvent e) { if (activation!=null) { contextService.deactivateContext(activation); } } @Override public void focusGained(FocusEvent e) { activation = contextService.activateContext( PLUGIN_ID + ".context"); } }); } @Override protected void configureTableViewer(TableViewer viewer) { contentProvider = new CeylonSearchResultContentProvider( viewer, this); configureViewer(viewer); } @Override protected void configureTreeViewer(TreeViewer viewer) { contentProvider = new CeylonSearchResultTreeContentProvider( viewer, this); configureViewer(viewer); } @Override protected void elementsChanged(Object[] elements) { if (contentProvider!=null) { contentProvider.elementsChanged(elements); } // getViewer().refresh(); } @Override protected void showMatch(Match match, int offset, int length, boolean activate) throws PartInitException { Object elem = match.getElement(); if (elem instanceof CeylonElement) { CeylonElement ce = (CeylonElement) elem; open(ce, offset, length, activate); } else if (elem instanceof IJavaElement) { IJavaElement je = (IJavaElement) elem; open(je, match, offset, length, activate); } } private void open(IJavaElement element, Match match, int offset, int length, boolean activate) throws PartInitException { IFile file = (IFile) element.getResource(); if (file==null) { //a binary archive IEditorPart editor = new JavaSearchEditorOpener() .openMatch(match); if (editor instanceof ITextEditor) { ITextEditor textEditor = (ITextEditor) editor; textEditor.selectAndReveal(offset, length); } } else { //a source file in the workspace IWorkbenchPage page = getSite().getPage(); if (offset>=0 && length!=0) { openAndSelect(page, file, offset, length, activate); } else { open(page, file, activate); } } } private void open(CeylonElement element, int offset, int length, boolean activate) throws PartInitException { IFile file = element.getFile(); if (file==null) { String path = element.getVirtualFile().getPath(); gotoLocation(new Path(path), offset, length); } else { IWorkbenchPage page = getSite().getPage(); if (offset>=0 && length!=0) { openAndSelect(page, file, offset, length, activate); } else { open(page, file, activate); } } } private static final String GROUP_CATEGORIES = PLUGIN_ID + ".search.CeylonSearchResultPage.categories"; private static final String GROUP_LAYOUT = PLUGIN_ID + ".search.CeylonSearchResultPage.layout"; private static final String GROUP_GROUPING = PLUGIN_ID + ".search.CeylonSearchResultPage.grouping"; private static final String KEY_GROUPING = PLUGIN_ID + ".search.CeylonSearchResultPage.grouping"; private static final String KEY_CATEGORIES = PLUGIN_ID + ".search.CeylonSearchResultPage.categories"; private GroupAction fGroupFileAction; private GroupAction fGroupPackageAction; private GroupAction fGroupModuleAction; private GroupAction fGroupFolderAction; private GroupAction fGroupProjectAction; private LayoutAction fLayoutFlatAction; private LayoutAction fLayoutTreeAction; private Action fCategoriesAction; private int fCurrentGrouping; private boolean fShowCategories; private void initGroupingActions() { fGroupProjectAction = new GroupAction("Project", "Group by Project", PROJECT_MODE, LEVEL_PROJECT); fGroupFolderAction = new GroupAction("Source Folder", "Group by Source Folder", FOLDER_MODE, LEVEL_FOLDER); fGroupModuleAction = new GroupAction("Module", "Group by Module", MODULE_MODE, LEVEL_MODULE); fGroupPackageAction = new GroupAction("Package", "Group by Package", PACKAGE_MODE, LEVEL_PACKAGE); fGroupFileAction = new GroupAction("Source File", "Group by Source File", UNIT_MODE, LEVEL_FILE); fLayoutTreeAction = new LayoutAction("Tree", "Show as Tree", TREE_MODE, FLAG_LAYOUT_TREE); fLayoutFlatAction = new LayoutAction("Flat", "Show as List", FLAT_MODE, FLAG_LAYOUT_FLAT); fCategoriesAction = new Action("Categories") { { setToolTipText("Group by Match Category"); ImageDescriptor desc = CeylonPlugin.imageRegistry() .getDescriptor(CEYLON_SEARCH); setImageDescriptor(desc); setChecked(fShowCategories); } @Override public void run() { setShowCategories(); setChecked(fShowCategories); } }; } private void updateGroupingActions() { fGroupProjectAction.setChecked( fCurrentGrouping == LEVEL_PROJECT); fGroupFolderAction.setChecked( fCurrentGrouping == LEVEL_FOLDER); fGroupModuleAction.setChecked( fCurrentGrouping == LEVEL_MODULE); fGroupPackageAction.setChecked( fCurrentGrouping == LEVEL_PACKAGE); fGroupFileAction.setChecked( fCurrentGrouping == LEVEL_FILE); } private void updateLayoutActions() { int layout = getLayout(); fLayoutFlatAction.setChecked( layout==FLAG_LAYOUT_FLAT); fLayoutTreeAction.setChecked( layout==FLAG_LAYOUT_TREE); } @Override protected void fillToolbar(IToolBarManager tbm) { super.fillToolbar(tbm); tbm.appendToGroup(GROUP_VIEWER_SETUP, new Separator(GROUP_LAYOUT)); tbm.appendToGroup(GROUP_LAYOUT, fLayoutFlatAction); tbm.appendToGroup(GROUP_LAYOUT, fLayoutTreeAction); updateLayoutActions(); if (getLayout() != FLAG_LAYOUT_FLAT) { tbm.appendToGroup(GROUP_VIEWER_SETUP, new Separator(GROUP_CATEGORIES)); tbm.appendToGroup(GROUP_CATEGORIES, fCategoriesAction); fShowCategories = getSettings() .getBoolean(KEY_CATEGORIES); contentProvider.setShowCategories(fShowCategories); updateCategoriesAction(); tbm.appendToGroup(GROUP_VIEWER_SETUP, new Separator(GROUP_GROUPING)); tbm.appendToGroup(GROUP_GROUPING, fGroupProjectAction); tbm.appendToGroup(GROUP_GROUPING, fGroupFolderAction); tbm.appendToGroup(GROUP_GROUPING, fGroupModuleAction); tbm.appendToGroup(GROUP_GROUPING, fGroupPackageAction); tbm.appendToGroup(GROUP_GROUPING, fGroupFileAction); try { fCurrentGrouping = getSettings() .getInt(KEY_GROUPING); } catch (NumberFormatException nfe) { //missing key fCurrentGrouping = LEVEL_PROJECT; } contentProvider.setLevel(fCurrentGrouping); updateGroupingActions(); } getSite() .getActionBars() .updateActionBars(); } private void updateCategoriesAction() { fCategoriesAction.setChecked(fShowCategories); } @Override protected void fillContextMenu(IMenuManager mgr) { super.fillContextMenu(mgr); MenuManager submenu = new MenuManager("Find"); submenu.setActionDefinitionId(CeylonEditor.FIND_MENU_ID); ISelection selection = getViewer().getSelection(); submenu.add(new FindReferencesAction(this, selection)); submenu.add(new FindAssignmentsAction(this, selection)); submenu.add(new FindSubtypesAction(this, selection)); submenu.add(new FindRefinementsAction(this, selection)); mgr.add(submenu); } @Override public void makeContributions(IMenuManager menuManager, IToolBarManager toolBarManager, IStatusLineManager statusLineManager) { final IPreferenceStore prefs = CeylonPlugin.getPreferences(); final Action showLocAction = new Action("Show Full Paths", AS_CHECK_BOX) { @Override public void run() { prefs.setValue(FULL_LOC_SEARCH_RESULTS, isChecked()); getViewer().refresh(); } }; showLocAction.setChecked(prefs.getBoolean( FULL_LOC_SEARCH_RESULTS)); //pref can be changed from ReferencesPopup! prefs.addPropertyChangeListener(new IPropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent event) { if (FULL_LOC_SEARCH_RESULTS.equals(event.getProperty())) { showLocAction.setChecked(prefs.getBoolean( FULL_LOC_SEARCH_RESULTS)); } } }); menuManager.add(showLocAction); super.makeContributions(menuManager, toolBarManager, statusLineManager); ImageDescriptor desc = CeylonPlugin.imageRegistry() .getDescriptor(CONFIG_LABELS); Action configureAction = new Action("Configure Labels...", desc) { @Override public void run() { Shell shell = getSite().getShell(); createPreferenceDialogOn(shell, CeylonOutlinesPreferencePage.ID, new String[] { CeylonOutlinesPreferencePage.ID, CeylonPlugin.COLORS_AND_FONTS_PAGE_ID, CeylonFiltersPreferencePage.ID }, null).open(); } }; menuManager.add(configureAction); } private class GroupAction extends Action { private int fGrouping; public GroupAction(String label, String tooltip, String imageKey, int grouping) { super(label); setToolTipText(tooltip); ImageDescriptor desc = CeylonPlugin.imageRegistry() .getDescriptor(imageKey); setImageDescriptor(desc); fGrouping = grouping; } @Override public boolean isEnabled() { return getLayout()!= FLAG_LAYOUT_FLAT; } @Override public void run() { setGrouping(fGrouping); } } private class LayoutAction extends Action { private int layout; public LayoutAction(String label, String tooltip, String imageKey, int layout) { super(label); setToolTipText(tooltip); ImageDescriptor desc = CeylonPlugin.imageRegistry() .getDescriptor(imageKey); setImageDescriptor(desc); this.layout = layout; } @Override public void run() { setLayout(layout); setChecked(getLayout()==layout); } } void setGrouping(int grouping) { fCurrentGrouping = grouping; contentProvider.setLevel(grouping); updateGroupingActions(); getSettings().put(KEY_GROUPING, fCurrentGrouping); getViewPart().updateLabel(); } void setShowCategories() { fShowCategories = !fShowCategories; contentProvider.setShowCategories(fShowCategories); updateCategoriesAction(); getSettings().put(KEY_CATEGORIES, fShowCategories); } }