#23912 Adopt actions
This commit is contained in:
parent
735c6d3b4c
commit
ec89a599b3
2 changed files with 63 additions and 41 deletions
|
@ -188,10 +188,15 @@
|
|||
}
|
||||
|
||||
.search-viewlet .linematch {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
position: relative;
|
||||
line-height: 22px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.search-viewlet .linematch > .match {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.search-viewlet .linematch.changedOrRemoved {
|
||||
|
@ -224,6 +229,35 @@
|
|||
background: url("action-query-clear.svg") center center no-repeat;
|
||||
}
|
||||
|
||||
.search-viewlet .monaco-tree .monaco-tree-row .monaco-action-bar {
|
||||
line-height: 1em;
|
||||
display: none;
|
||||
padding: 0 0.8em 0 0.4em;
|
||||
}
|
||||
|
||||
.search-viewlet .monaco-tree .monaco-tree-row .monaco-action-bar .action-item {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.search-viewlet .monaco-tree .monaco-tree-row.focused .monaco-action-bar {
|
||||
width: 0; /* in order to support a11y with keyboard, we use width: 0 to hide the actions, which still allows to "Tab" into the actions */
|
||||
display: block;
|
||||
}
|
||||
|
||||
.search-viewlet .monaco-tree .monaco-tree-row:hover:not(.highlighted) .monaco-action-bar,
|
||||
.search-viewlet .monaco-tree .monaco-tree-row.focused .monaco-action-bar {
|
||||
width: inherit;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.search-viewlet .monaco-tree .monaco-tree-row .monaco-action-bar .action-label {
|
||||
margin-right: 0.2em;
|
||||
margin-top: 4px;
|
||||
background-repeat: no-repeat;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.search-viewlet .action-remove {
|
||||
background: url("action-remove.svg") center center no-repeat;
|
||||
}
|
||||
|
|
|
@ -12,11 +12,11 @@ import * as DOM from 'vs/base/browser/dom';
|
|||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { IAction, IActionRunner } from 'vs/base/common/actions';
|
||||
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { CountBadge } from 'vs/base/browser/ui/countBadge/countBadge';
|
||||
import { FileLabel } from 'vs/workbench/browser/labels';
|
||||
import { ITree, IDataSource, ISorter, IAccessibilityProvider, IFilter, IRenderer } from 'vs/base/parts/tree/browser/tree';
|
||||
import { ClickBehavior, DefaultController } from 'vs/base/parts/tree/browser/treeDefaults';
|
||||
import { ContributableActionProvider } from 'vs/workbench/browser/actionBarRegistry';
|
||||
import { Match, SearchResult, FileMatch, FileMatchOrMatch, SearchModel } from 'vs/workbench/parts/search/common/searchModel';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
|
@ -93,40 +93,10 @@ export class SearchSorter implements ISorter {
|
|||
}
|
||||
}
|
||||
|
||||
class SearchActionProvider extends ContributableActionProvider {
|
||||
|
||||
constructor(private viewlet: SearchViewlet, @IInstantiationService private instantiationService: IInstantiationService) {
|
||||
super();
|
||||
}
|
||||
|
||||
public hasActions(tree: ITree, element: any): boolean {
|
||||
let input = <SearchResult>tree.getInput();
|
||||
return element instanceof FileMatch || (element instanceof Match && input.searchModel.isReplaceActive()) || super.hasActions(tree, element);
|
||||
}
|
||||
|
||||
public getActions(tree: ITree, element: any): TPromise<IAction[]> {
|
||||
return super.getActions(tree, element).then(actions => {
|
||||
let input = <SearchResult>tree.getInput();
|
||||
if (element instanceof FileMatch) {
|
||||
actions.unshift(new RemoveAction(tree, element));
|
||||
if (input.searchModel.isReplaceActive() && element.count() > 0) {
|
||||
actions.unshift(this.instantiationService.createInstance(ReplaceAllAction, tree, element, this.viewlet));
|
||||
}
|
||||
}
|
||||
if (element instanceof Match) {
|
||||
if (input.searchModel.isReplaceActive()) {
|
||||
actions.unshift(this.instantiationService.createInstance(ReplaceAction, tree, element, this.viewlet), new RemoveAction(tree, element));
|
||||
}
|
||||
}
|
||||
|
||||
return actions;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
interface IFileMatchTemplate {
|
||||
label: FileLabel;
|
||||
badge: CountBadge;
|
||||
actions: ActionBar;
|
||||
}
|
||||
|
||||
interface IMatchTemplate {
|
||||
|
@ -135,6 +105,7 @@ interface IMatchTemplate {
|
|||
match: HTMLElement;
|
||||
replace?: HTMLElement;
|
||||
after: HTMLElement;
|
||||
actions: ActionBar;
|
||||
}
|
||||
|
||||
export class SearchRenderer extends Disposable implements IRenderer {
|
||||
|
@ -142,7 +113,7 @@ export class SearchRenderer extends Disposable implements IRenderer {
|
|||
private static FILE_MATCH_TEMPLATE_ID = 'fileMatch';
|
||||
private static MATCH_TEMPLATE_ID = 'match';
|
||||
|
||||
constructor(actionRunner: IActionRunner, viewlet: SearchViewlet, @IWorkspaceContextService private contextService: IWorkspaceContextService,
|
||||
constructor(actionRunner: IActionRunner, private viewlet: SearchViewlet, @IWorkspaceContextService private contextService: IWorkspaceContextService,
|
||||
@IInstantiationService private instantiationService: IInstantiationService) {
|
||||
super();
|
||||
}
|
||||
|
@ -174,7 +145,7 @@ export class SearchRenderer extends Disposable implements IRenderer {
|
|||
|
||||
public renderElement(tree: ITree, element: any, templateId: string, templateData: any): void {
|
||||
if (SearchRenderer.FILE_MATCH_TEMPLATE_ID === templateId) {
|
||||
this.renderFileMatch(<FileMatch>element, <IFileMatchTemplate>templateData);
|
||||
this.renderFileMatch(tree, <FileMatch>element, <IFileMatchTemplate>templateData);
|
||||
} else if (SearchRenderer.MATCH_TEMPLATE_ID === templateId) {
|
||||
this.renderMatch(tree, <Match>element, <IMatchTemplate>templateData);
|
||||
}
|
||||
|
@ -185,33 +156,45 @@ export class SearchRenderer extends Disposable implements IRenderer {
|
|||
let fileMatchElement = DOM.append(container, DOM.$('.filematch'));
|
||||
const label = this.instantiationService.createInstance(FileLabel, fileMatchElement, void 0);
|
||||
const badge = new CountBadge(DOM.append(fileMatchElement, DOM.$('.badge')));
|
||||
return { label, badge };
|
||||
const actions = new ActionBar(fileMatchElement, { animated: false });
|
||||
return { label, badge, actions };
|
||||
}
|
||||
|
||||
private renderMatchTemplate(tree: ITree, templateId: string, container: HTMLElement): IMatchTemplate {
|
||||
DOM.addClass(container, 'linematch');
|
||||
|
||||
const parent = DOM.append(container, DOM.$('a.plain'));
|
||||
const parent = DOM.append(container, DOM.$('a.plain.match'));
|
||||
const before = DOM.append(parent, DOM.$('span'));
|
||||
const match = DOM.append(parent, DOM.$('span.findInFileMatch'));
|
||||
const replace = DOM.append(parent, DOM.$('span.replaceMatch'));
|
||||
const after = DOM.append(parent, DOM.$('span'));
|
||||
const actions = new ActionBar(container, { animated: false });
|
||||
|
||||
return {
|
||||
parent,
|
||||
before,
|
||||
match,
|
||||
replace,
|
||||
after
|
||||
after,
|
||||
actions
|
||||
};
|
||||
}
|
||||
|
||||
private renderFileMatch(fileMatch: FileMatch, templateData: IFileMatchTemplate): void {
|
||||
private renderFileMatch(tree: ITree, fileMatch: FileMatch, templateData: IFileMatchTemplate): void {
|
||||
templateData.label.setFile(fileMatch.resource());
|
||||
|
||||
let count = fileMatch.count();
|
||||
templateData.badge.setCount(count);
|
||||
templateData.badge.setTitleFormat(count > 1 ? nls.localize('searchMatches', "{0} matches found", count) : nls.localize('searchMatch', "{0} match found", count));
|
||||
|
||||
let input = <SearchResult>tree.getInput();
|
||||
templateData.actions.clear();
|
||||
|
||||
const actions: IAction[] = [];
|
||||
if (input.searchModel.isReplaceActive() && count > 0) {
|
||||
actions.push(this.instantiationService.createInstance(ReplaceAllAction, tree, fileMatch, this.viewlet));
|
||||
}
|
||||
actions.push(new RemoveAction(tree, fileMatch));
|
||||
templateData.actions.push(actions, { icon: true, label: false });
|
||||
}
|
||||
|
||||
private renderMatch(tree: ITree, match: Match, templateData: IMatchTemplate): void {
|
||||
|
@ -225,6 +208,11 @@ export class SearchRenderer extends Disposable implements IRenderer {
|
|||
templateData.replace.textContent = replace ? strings.escape(match.replaceString) : '';
|
||||
templateData.after.textContent = strings.escape(preview.after);
|
||||
templateData.parent.title = (preview.before + (templateData.replace ? match.replaceString : preview.inside) + preview.after).trim().substr(0, 999);
|
||||
|
||||
templateData.actions.clear();
|
||||
if (searchModel.isReplaceActive()) {
|
||||
templateData.actions.push([this.instantiationService.createInstance(ReplaceAction, tree, match, this.viewlet), new RemoveAction(tree, match)], { icon: true, label: false });
|
||||
}
|
||||
}
|
||||
|
||||
public disposeTemplate(tree: ITree, templateId: string, templateData: any): void {
|
||||
|
|
Loading…
Reference in a new issue