diff --git a/src/sql/base/browser/ui/table/media/table.css b/src/sql/base/browser/ui/table/media/table.css index 903c3621a3..eaff00c275 100644 --- a/src/sql/base/browser/ui/table/media/table.css +++ b/src/sql/base/browser/ui/table/media/table.css @@ -101,7 +101,8 @@ padding: 4px; z-index: 100000; cursor: default; - display: inline-block; + display: flex; + flex-direction: column; margin: 0; position: absolute; } @@ -118,10 +119,14 @@ background: none repeat scroll 0 0 #000000; } +.slick-header-menu-image-button-container { + flex: 0 0 auto; +} + .slick-header-menu a.monaco-button.monaco-text-button { width: 60px; - margin: 6px 6px 6px 6px; - padding: 4px; + margin: 5px; + padding: 2px; } .slick-header-menu .searchbox-row @@ -130,6 +135,7 @@ align-items: center; padding-left: 5px; margin-top: 5px; + flex: 0 0 auto; } .slick-header-menu .searchbox-row .select-all-checkbox @@ -168,7 +174,6 @@ { border: 1px solid #BFBDBD; font-size: 8pt; - height: 250px; margin-top: 6px; overflow: hidden; padding: 1px; @@ -176,6 +181,7 @@ align-content: flex-start; display: flex; flex-direction: column; + flex: 1 1 auto; } .slick-header-menu .filter .filter-option { @@ -188,6 +194,7 @@ display: flex; flex-direction: row; width: 100%; + flex: 0 0 auto; } .slick-header-menu .filter-menu-button { diff --git a/src/sql/base/browser/ui/table/plugins/headerFilter.plugin.ts b/src/sql/base/browser/ui/table/plugins/headerFilter.plugin.ts index 2aaf372263..e84d7461cf 100644 --- a/src/sql/base/browser/ui/table/plugins/headerFilter.plugin.ts +++ b/src/sql/base/browser/ui/table/plugins/headerFilter.plugin.ts @@ -84,6 +84,7 @@ export class HeaderFilter { private disposableStore = new DisposableStore(); private columnButtonMapping: Map = new Map(); private previouslyFocusedElement: HTMLElement; + private listContainer?: HTMLElement; constructor(private readonly contextViewProvider: IContextViewProvider, private readonly notificationProvider?: NotificationProvider, private readonly options: ITableFilterOptions = DefaultTableFilterOptions) { } @@ -180,7 +181,7 @@ export class HeaderFilter { } private createButtonMenuItem(title: string, command: HeaderFilterCommands, iconClass: string): Button { - const buttonContainer = append(this.menu, $('')); + const buttonContainer = append(this.menu, $('.slick-header-menu-image-button-container')); const button = new Button(buttonContainer); button.icon = { id: `slick-header-menuicon ${iconClass}` }; button.label = title; @@ -278,8 +279,8 @@ export class HeaderFilter { this.filteredListData = this.listData; - const filter = append(this.menu, $('.filter')); - this.list = new List('TableFilter', filter, new TableFilterListDelegate(), [new TableFilterListRenderer()], { + this.listContainer = append(this.menu, $('.filter')); + this.list = new List('TableFilter', this.listContainer, new TableFilterListDelegate(), [new TableFilterListRenderer()], { multipleSelectionSupport: false, keyboardSupport: true, mouseSupport: true, @@ -347,29 +348,26 @@ export class HeaderFilter { } this.previouslyFocusedElement = document.activeElement as HTMLElement; await this.createFilterMenu(filterButton); - // Get the absolute coordinates of the filter button - const offset = jQuery(filterButton).offset(); - // Calculate the position of menu item - let menuleft = offset.left - this.menu.offsetWidth + filterButton.offsetWidth; - let menutop = offset.top + filterButton.offsetHeight; - // Make sure the entire menu is on screen. - // If there is not enough vertical space under the filter button, we will move up the menu. - // If the left of the menu is off screen (negative value), we will show the menu next to the left edge of window. + // Try to fit the menu in the screen. // We don't really consider the case when there is not enough space to show the entire menu since in that case the application is not usable already. - if (menutop + this.menu.offsetHeight > window.innerHeight) { - menutop = window.innerHeight - this.menu.offsetHeight; - } - menuleft = menuleft > 0 ? menuleft : 0; + + const offset = jQuery(filterButton).offset(); + // If there is not enough vertical space under the filter button, we will move up the menu. + const menuTop = offset.top + this.menu.offsetHeight <= window.innerHeight ? offset.top : window.innerHeight - this.menu.offsetHeight; + // Make sure the menu is on the screen horizontally. + const menuLeft = offset.left + filterButton.offsetWidth + this.menu.offsetWidth <= window.innerWidth ? offset.left + filterButton.offsetWidth : window.innerWidth - this.menu.offsetWidth; this.contextViewProvider.showContextView({ getAnchor: () => { return { - x: menuleft, - y: menutop + x: menuLeft, + y: menuTop }; }, render: (container: HTMLElement) => { container.appendChild(this.menu); + // Set the list size to its container size so that scrolling works correctly.. + this.list.layout(this.listContainer.clientHeight); return { dispose: () => { this.disposeMenu(); @@ -401,6 +399,11 @@ export class HeaderFilter { // first add it to the document so that we can get the actual size of the menu // later, it will be added to the correct container this.menu = append(document.body, $('.slick-header-menu')); + const MenuVerticalPadding = 10; + const MenuBarHeight = 30; + const DefaultMenuHeight = 350; + // Make sure the menu can fit in the screen. + this.menu.style.height = `${Math.min(DefaultMenuHeight, window.innerHeight - MenuBarHeight) - MenuVerticalPadding}px`; this.sortAscButton = this.createButtonMenuItem(localize('table.sortAscending', "Sort Ascending"), 'sort-asc', 'ascending'); this.sortDescButton = this.createButtonMenuItem(localize('table.sortDescending', "Sort Descending"), 'sort-desc', 'descending');