Skip to content

Commit

Permalink
#60 Added a tooltip on repo dropdown items, indicating the full path …
Browse files Browse the repository at this point in the history
…of the repository.
  • Loading branch information
mhutchie committed May 1, 2019
1 parent e56379d commit e2f334c
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 21 deletions.
18 changes: 18 additions & 0 deletions media/dropdown.css
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,30 @@
padding:4px 10px;
user-select:none;
}
.dropdownOptions.showInfo .dropdownOption{
padding-right:30px;
}
.dropdownOption.selected{
background-color:rgba(128,128,128,0.15);
}
.dropdownOption:hover{
background-color:var(--vscode-menu-selectionBackground);
color:var(--vscode-menu-selectionForeground);
}
.dropdownOptionInfo{
position:absolute;
width:14px;
height:16px;
top:6px;
right:10px;
}
.dropdownOptionInfo svg{
fill:var(--vscode-menu-foreground);
opacity:0.35;
}
.dropdownOptionInfo:hover svg{
fill:var(--vscode-menu-selectionForeground);
}

.dropdown.dropdownOpen .dropdownCurrentValue{
border-radius:6px 6px 0 0;
Expand All @@ -91,6 +108,7 @@
border-radius:4px;
padding:3px 6px;
font-size:13px;
line-height:17px;
font-weight:normal;
font-family:var(--vscode-editor-font-family);
color:var(--vscode-menu-foreground);
Expand Down
42 changes: 26 additions & 16 deletions web/dropdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ class Dropdown {
private options: DropdownOption[] = [];
private selectedOption: number = 0;
private dropdownVisible: boolean = false;
private showInfo: boolean;
private changeCallback: { (value: string): void };
private escapeHtml: { (input: string): string };
private svgIcons: SvgIcons;

private elem: HTMLElement;
private currentValueElem: HTMLDivElement;
Expand All @@ -11,8 +14,11 @@ class Dropdown {
private noResultsElem: HTMLDivElement;
private filterInput: HTMLInputElement;

constructor(id: string, dropdownType: string, changeCallback: { (value: string): void }) {
constructor(id: string, showInfo: boolean, dropdownType: string, changeCallback: { (value: string): void }, escapeHtml: { (str: string): string }, svgIcons: SvgIcons) {
this.showInfo = showInfo;
this.changeCallback = changeCallback;
this.escapeHtml = escapeHtml;
this.svgIcons = svgIcons;
this.elem = document.getElementById(id)!;

let filter = document.createElement('div');
Expand Down Expand Up @@ -46,23 +52,24 @@ class Dropdown {
}
this.elem.classList.toggle('dropdownOpen');
if (this.dropdownVisible) this.filterInput.focus();
} else if ((<HTMLElement>e.target).parentNode === this.optionsElem) {
if (typeof (<HTMLElement>e.target).dataset.id !== 'undefined') {
let selectedOption = parseInt((<HTMLElement>e.target).dataset.id!);
} else if (this.dropdownVisible) {
if ((<HTMLElement>e.target).closest('.dropdown') !== this.elem) {
this.close();
if (this.selectedOption !== selectedOption) {
this.selectedOption = selectedOption;
this.render();
this.changeCallback(this.options[this.selectedOption].value);
} else {
let option = <HTMLElement | null>(<HTMLElement>e.target).closest('.dropdownOption');
if (option !== null && option.parentNode === this.optionsElem && typeof option.dataset.id !== 'undefined') {
let selectedOption = parseInt(option.dataset.id!);
this.close();
if (this.selectedOption !== selectedOption) {
this.selectedOption = selectedOption;
this.render();
this.changeCallback(this.options[this.selectedOption].value);
}
}
}
} else if ((<HTMLElement>e.target).closest('.dropdown') !== this.elem) {
this.close();
}
}, true);
document.addEventListener('contextmenu', () => {
this.close();
}, true);
document.addEventListener('contextmenu', () => this.close(), true);
document.addEventListener('keyup', (e) => {
if (e.key === 'Escape') this.close();
}, true);
Expand Down Expand Up @@ -91,14 +98,17 @@ class Dropdown {
this.currentValueElem.innerHTML = this.options[this.selectedOption].name;
let html = '';
for (let i = 0; i < this.options.length; i++) {
html += '<div class="dropdownOption' + (this.selectedOption === i ? ' selected' : '') + '" data-id="' + i + '">' + this.options[i].name + '</div>';
html += '<div class="dropdownOption' + (this.selectedOption === i ? ' selected' : '') + '" data-id="' + i + '">' + this.escapeHtml(this.options[i].name) + (this.showInfo ? '<div class="dropdownOptionInfo" title="' + this.escapeHtml(this.options[i].value) + '">' + this.svgIcons.info + '</div>' : '') + '</div>';
}
this.optionsElem.className = 'dropdownOptions' + (this.showInfo ? ' showInfo' : '');
this.optionsElem.innerHTML = html;
this.filterInput.style.display = 'none';
this.noResultsElem.style.display = 'none';
this.menuElem.style.cssText = 'opacity:0; display:block;';
this.currentValueElem.style.width = Math.max(this.menuElem.offsetWidth + 12, 130) + 'px';
this.menuElem.style.cssText = 'right:0; overflow-y:auto; max-height:294px;';
// Width must be at least 130px for the filter elements. Max height for the dropdown is [filter (31px) + 9.5 * dropdown item (28px) = 297px]
// Don't need to add 12px if showing info icons and scrollbar isn't needed. The scrollbar isn't needed if: menuElem height + filter input (25px) < 297px
this.currentValueElem.style.width = Math.max(this.menuElem.offsetWidth + (this.showInfo && this.menuElem.offsetHeight < 272 ? 0 : 12), 130) + 'px';
this.menuElem.style.cssText = 'right:0; overflow-y:auto; max-height:297px;';
if (this.dropdownVisible) this.filter();
}

Expand Down
2 changes: 2 additions & 0 deletions web/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ declare global {

type AvatarImageCollection = { [email: string]: string };

type SvgIcons = { [name: string]: string };

interface WebViewState {
gitRepos: GG.GitRepoSet;
gitBranches: string[];
Expand Down
11 changes: 6 additions & 5 deletions web/main.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
(function () {
/* Constants */
const vscode = acquireVsCodeApi();
const svgIcons = {
const svgIcons: SvgIcons = {
alert: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"/></svg>',
branch: '<svg xmlns="http://www.w3.org/2000/svg" width="10" height="16" viewBox="0 0 10 16"><path fill-rule="evenodd" d="M10 5c0-1.11-.89-2-2-2a1.993 1.993 0 0 0-1 3.72v.3c-.02.52-.23.98-.63 1.38-.4.4-.86.61-1.38.63-.83.02-1.48.16-2 .45V4.72a1.993 1.993 0 0 0-1-3.72C.88 1 0 1.89 0 3a2 2 0 0 0 1 1.72v6.56c-.59.35-1 .99-1 1.72 0 1.11.89 2 2 2 1.11 0 2-.89 2-2 0-.53-.2-1-.53-1.36.09-.06.48-.41.59-.47.25-.11.56-.17.94-.17 1.05-.05 1.95-.45 2.75-1.25S8.95 7.77 9 6.73h-.02C9.59 6.37 10 5.73 10 5zM2 1.8c.66 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2C1.35 4.2.8 3.65.8 3c0-.65.55-1.2 1.2-1.2zm0 12.41c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zm6-8c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2z"/></svg>',
close: '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="16" viewBox="0 0 12 16"><path fill-rule="evenodd" d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48L7.48 8z"/></svg>',
info: '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="16" viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"/></svg>',
tag: '<svg xmlns="http://www.w3.org/2000/svg" width="15" height="16" viewBox="0 0 15 16"><path fill-rule="evenodd" d="M7.73 1.73C7.26 1.26 6.62 1 5.96 1H3.5C2.13 1 1 2.13 1 3.5v2.47c0 .66.27 1.3.73 1.77l6.06 6.06c.39.39 1.02.39 1.41 0l4.59-4.59a.996.996 0 0 0 0-1.41L7.73 1.73zM2.38 7.09c-.31-.3-.47-.7-.47-1.13V3.5c0-.88.72-1.59 1.59-1.59h2.47c.42 0 .83.16 1.13.47l6.14 6.13-4.73 4.73-6.13-6.15zM3.01 3h2v2H3V3h.01z"/></svg>',
loading: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="32" viewBox="0 0 12 16"><path fill-rule="evenodd" d="M10.24 7.4a4.15 4.15 0 0 1-1.2 3.6 4.346 4.346 0 0 1-5.41.54L4.8 10.4.5 9.8l.6 4.2 1.31-1.26c2.36 1.74 5.7 1.57 7.84-.54a5.876 5.876 0 0 0 1.74-4.46l-1.75-.34zM2.96 5a4.346 4.346 0 0 1 5.41-.54L7.2 5.6l4.3.6-.6-4.2-1.31 1.26c-2.36-1.74-5.7-1.57-7.85.54C.5 5.03-.06 6.65.01 8.26l1.75.35A4.17 4.17 0 0 1 2.96 5z"/></svg>',
openFolder: '<svg xmlns="http://www.w3.org/2000/svg" class="openFolderIcon" viewBox="0 0 30 30"><path d="M 5 4 C 3.895 4 3 4.895 3 6 L 3 9 L 3 11 L 22 11 L 27 11 L 27 8 C 27 6.895 26.105 6 25 6 L 12.199219 6 L 11.582031 4.9707031 C 11.221031 4.3687031 10.570187 4 9.8671875 4 L 5 4 z M 2.5019531 13 C 1.4929531 13 0.77040625 13.977406 1.0664062 14.941406 L 4.0351562 24.587891 C 4.2941563 25.426891 5.0692656 26 5.9472656 26 L 15 26 L 24.052734 26 C 24.930734 26 25.705844 25.426891 25.964844 24.587891 L 28.933594 14.941406 C 29.229594 13.977406 28.507047 13 27.498047 13 L 15 13 L 2.5019531 13 z"/></svg>',
Expand Down Expand Up @@ -57,22 +58,22 @@
this.graph = new Graph('commitGraph', this.config);
this.tableElem = document.getElementById('commitTable')!;
this.footerElem = document.getElementById('footer')!;
this.repoDropdown = new Dropdown('repoSelect', 'Repos', value => {
this.repoDropdown = new Dropdown('repoSelect', true, 'Repos', value => {
this.currentRepo = value;
this.maxCommits = this.config.initialLoadCommits;
this.expandedCommit = null;
this.currentBranch = null;
this.saveState();
this.refresh(true);
});
this.branchDropdown = new Dropdown('branchSelect', 'Branches', value => {
}, escapeHtml, svgIcons);
this.branchDropdown = new Dropdown('branchSelect', false, 'Branches', value => {
this.currentBranch = value;
this.maxCommits = this.config.initialLoadCommits;
this.expandedCommit = null;
this.saveState();
this.renderShowLoading();
this.requestLoadCommits(true, () => { });
});
}, escapeHtml, svgIcons);
this.showRemoteBranchesElem = <HTMLInputElement>document.getElementById('showRemoteBranchesCheckbox')!;
this.showRemoteBranchesElem.addEventListener('change', () => {
this.showRemoteBranches = this.showRemoteBranchesElem.checked;
Expand Down

0 comments on commit e2f334c

Please sign in to comment.