diff --git a/user-console/src/main/java/org/pentaho/mantle/client/MantleApplication.java b/user-console/src/main/java/org/pentaho/mantle/client/MantleApplication.java index debb92e3975..44f193c1279 100644 --- a/user-console/src/main/java/org/pentaho/mantle/client/MantleApplication.java +++ b/user-console/src/main/java/org/pentaho/mantle/client/MantleApplication.java @@ -344,6 +344,7 @@ public void onMantleSettingsLoaded( MantleSettingsLoadedEvent event ) { RootPanel.get( "pucMenuBar" ).add( MantleXul.getInstance().getMenubar() ); RootPanel.get( "pucBurgerToolbar" ).add( MantleXul.getInstance().getBurgerToolbarWrapper() ); + RootPanel.get( "pucTabsMenuBar" ).add( MantleXul.getInstance().getTabsMenuBarWrapper() ); RootPanel.get( "pucPerspectives" ).add( PerspectiveManager.getInstance() ); RootPanel.get( "pucToolBar" ).add( MantleXul.getInstance().getToolbar() ); RootPanel.get( "pucUserDropDown" ).add( getUserDropDown() ); @@ -360,6 +361,7 @@ public void onMantleSettingsLoaded( MantleSettingsLoadedEvent event ) { contentDeck.add( new Label() ); contentDeck.showWidget( 0 ); contentDeck.add( SolutionBrowserPanel.getInstance() ); + if ( showOnlyPerspective && !StringUtils.isEmpty( startupPerspective ) ) { SolutionBrowserPanel.getInstance().setVisible( false ); } diff --git a/user-console/src/main/java/org/pentaho/mantle/client/admin/ChangePasswordByUserDialog.java b/user-console/src/main/java/org/pentaho/mantle/client/admin/ChangePasswordByUserDialog.java index 35602d8d770..32d4a963550 100644 --- a/user-console/src/main/java/org/pentaho/mantle/client/admin/ChangePasswordByUserDialog.java +++ b/user-console/src/main/java/org/pentaho/mantle/client/admin/ChangePasswordByUserDialog.java @@ -77,6 +77,9 @@ public ChangePasswordByUserDialog( MantleController controller ) { cancelBtn.setStylePrimaryName( "pentaho-button" ); cancelBtn.addClickHandler( new CancelListener() ); + setResponsive( true ); + setWidthCategory( WidthCategory.EXTRASMALL ); + this.controller = controller; } @@ -84,8 +87,6 @@ public ChangePasswordByUserDialog( MantleController controller ) { protected DialogBox createManagedDialog() { DialogBox dialog = super.createManagedDialog(); dialog.setStyleDependentName( "change-password", true ); - dialog.setResponsive( true ); - dialog.setWidthCategory( DialogBox.DialogWidthCategory.EXTRA_SMALL ); return dialog; } diff --git a/user-console/src/main/java/org/pentaho/mantle/client/admin/ChangePasswordDialog.java b/user-console/src/main/java/org/pentaho/mantle/client/admin/ChangePasswordDialog.java index 25206b77468..829ce5e9ee2 100644 --- a/user-console/src/main/java/org/pentaho/mantle/client/admin/ChangePasswordDialog.java +++ b/user-console/src/main/java/org/pentaho/mantle/client/admin/ChangePasswordDialog.java @@ -72,6 +72,9 @@ public ChangePasswordDialog( UpdatePasswordController controller ) { cancelBtn.setStylePrimaryName( "pentaho-button" ); cancelBtn.addClickHandler( new CancelListener() ); + setResponsive( true ); + setWidthCategory( WidthCategory.EXTRASMALL ); + this.controller = controller; } @@ -79,8 +82,6 @@ public ChangePasswordDialog( UpdatePasswordController controller ) { protected DialogBox createManagedDialog() { DialogBox dialog = super.createManagedDialog(); dialog.setStyleDependentName( "change-password", true ); - dialog.setResponsive( true ); - dialog.setWidthCategory( DialogBox.DialogWidthCategory.EXTRA_SMALL ); return dialog; } diff --git a/user-console/src/main/java/org/pentaho/mantle/client/admin/RoleDialog.java b/user-console/src/main/java/org/pentaho/mantle/client/admin/RoleDialog.java index 91583cd8c35..141ab0c49cd 100644 --- a/user-console/src/main/java/org/pentaho/mantle/client/admin/RoleDialog.java +++ b/user-console/src/main/java/org/pentaho/mantle/client/admin/RoleDialog.java @@ -63,6 +63,10 @@ public RoleDialog( UserRolesAdminPanelController controller ) { cancelBtn.setStylePrimaryName( "pentaho-button" ); cancelBtn.addClickHandler( new CancelListener() ); + setResponsive( true ); + setWidthCategory( WidthCategory.EXTRASMALL ); + setMinimumHeightCategory( MinimumHeightCategory.CONTENT ); + this.controller = controller; } @@ -70,9 +74,6 @@ public RoleDialog( UserRolesAdminPanelController controller ) { protected DialogBox createManagedDialog() { DialogBox dialog = super.createManagedDialog(); dialog.setStyleDependentName( "new-role", true ); - dialog.setResponsive( true ); - dialog.setWidthCategory( DialogBox.DialogWidthCategory.EXTRA_SMALL ); - dialog.setMinimumHeightCategory( DialogBox.DialogMinimumHeightCategory.CONTENT ); return dialog; } diff --git a/user-console/src/main/java/org/pentaho/mantle/client/admin/UserDialog.java b/user-console/src/main/java/org/pentaho/mantle/client/admin/UserDialog.java index 121fdc7271f..cbce040a1be 100644 --- a/user-console/src/main/java/org/pentaho/mantle/client/admin/UserDialog.java +++ b/user-console/src/main/java/org/pentaho/mantle/client/admin/UserDialog.java @@ -80,6 +80,9 @@ public UserDialog( UserRolesAdminPanelController controller ) { cancelBtn.setStylePrimaryName( "pentaho-button" ); cancelBtn.addClickHandler( new CancelListener() ); + setResponsive( true ); + setWidthCategory( WidthCategory.EXTRASMALL ); + this.controller = controller; } @@ -87,8 +90,6 @@ public UserDialog( UserRolesAdminPanelController controller ) { protected DialogBox createManagedDialog() { DialogBox dialog = super.createManagedDialog(); dialog.setStyleDependentName( "new-user", true ); - dialog.setResponsive( true ); - dialog.setWidthCategory( DialogBox.DialogWidthCategory.EXTRA_SMALL ); return dialog; } diff --git a/user-console/src/main/java/org/pentaho/mantle/client/commands/SaveCommand.java b/user-console/src/main/java/org/pentaho/mantle/client/commands/SaveCommand.java index d2ee277f740..eb15bcc93be 100644 --- a/user-console/src/main/java/org/pentaho/mantle/client/commands/SaveCommand.java +++ b/user-console/src/main/java/org/pentaho/mantle/client/commands/SaveCommand.java @@ -37,6 +37,7 @@ import com.google.gwt.core.client.JsArrayString; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Label; +import org.pentaho.mantle.client.ui.tabs.MantleTabPanel; public class SaveCommand extends AbstractCommand { @@ -442,9 +443,11 @@ private native void doSaveAsNativeWrapper( String elementId, String filename, St // used via JSNI private void doTabRename() { if ( tabName != null ) { // Save-As does not modify the name of the tab. - PentahoTab tab = SolutionBrowserPanel.getInstance().getContentTabPanel().getSelectedTab(); + MantleTabPanel tabPanel = SolutionBrowserPanel.getInstance().getContentTabPanel(); + PentahoTab tab = tabPanel.getSelectedTab(); tab.setLabelText( tabName ); tab.setLabelTooltip( tabName ); + tabPanel.renameMenuTab( tab ); } } diff --git a/user-console/src/main/java/org/pentaho/mantle/client/ui/tabs/MantleTab.java b/user-console/src/main/java/org/pentaho/mantle/client/ui/tabs/MantleTab.java index df94c33dce6..c82f9eff802 100644 --- a/user-console/src/main/java/org/pentaho/mantle/client/ui/tabs/MantleTab.java +++ b/user-console/src/main/java/org/pentaho/mantle/client/ui/tabs/MantleTab.java @@ -47,11 +47,13 @@ import org.pentaho.gwt.widgets.client.dialogs.IDialogCallback; import org.pentaho.gwt.widgets.client.dialogs.PromptDialogBox; import org.pentaho.gwt.widgets.client.tabs.PentahoTab; +import org.pentaho.gwt.widgets.client.tabs.PentahoTabPanel; import org.pentaho.gwt.widgets.client.utils.FrameUtils; import org.pentaho.gwt.widgets.client.utils.string.StringUtils; import org.pentaho.mantle.client.messages.Messages; import org.pentaho.mantle.client.solutionbrowser.MantlePopupPanel; import org.pentaho.mantle.client.solutionbrowser.tabs.IFrameTabPanel; +import org.pentaho.mantle.client.ui.PerspectiveManager; public class MantleTab extends org.pentaho.gwt.widgets.client.tabs.PentahoTab { @@ -234,19 +236,23 @@ public void hidePopUpMenu() { popupMenu.hide(); } - public void onRightClick( Event event ) { - FrameUtils.setEmbedVisibility( ( (IFrameTabPanel) getTabPanel().getSelectedTab().getContent() ).getFrame(), false ); - int left; - int top; - if ( event.getTypeInt() == Event.ONKEYDOWN ) { - PentahoTab tab = getTabPanel().getTab( getTabPanel().getSelectedTabIndex() ); - left = tab.getAbsoluteLeft() + ( tab.getOffsetWidth() / 2 ); - top = tab.getAbsoluteTop() + tab.getOffsetHeight(); - } else { - left = Window.getScrollLeft() + DOM.eventGetClientX( event ); - top = Window.getScrollTop() + DOM.eventGetClientY( event ); + /** + * Select this tab. If the "Opened" perspective is not show, show it. + */ + protected void selectTabMenuItem() { + PerspectiveManager perspectiveManager = PerspectiveManager.getInstance(); + if ( !perspectiveManager.getActivePerspective().equals( PerspectiveManager.OPENED_PERSPECTIVE ) ) { + perspectiveManager.setPerspective( PerspectiveManager.OPENED_PERSPECTIVE ); } - popupMenu.setPopupPosition( adjustLeftIfNecessary( left ), top ); + fireTabSelected(); + ( (MantleTabPanel) this.getTabPanel() ).updateTabMenuText( this ); + } + + protected MenuBar getContextMenuBar(){ + return getContextMenuBar( false ); + } + + protected MenuBar getContextMenuBar( boolean addSelectItem ){ MenuBar menuBar = new MenuBar( true ) { public void onBrowserEvent( Event event ) { int type = event.getTypeInt(); @@ -263,20 +269,26 @@ public void onBrowserEvent( Event event ) { }; menuBar.setAutoOpen( true ); menuBar.setFocusOnHoverEnabled( true ); + + if ( addSelectItem ) { + MenuItem selectTabMenuItem = new MenuItem( Messages.getString( "select" ), () -> selectTabMenuItem() ); + menuBar.addItem( selectTabMenuItem ); + } + if ( getContent() instanceof IFrameTabPanel ) { MenuItem backMenuItem = - new MenuItem( Messages.getString( "back" ), new TabCommand( TABCOMMANDTYPE.BACK, popupMenu ) ); //$NON-NLS-1$ + new MenuItem( Messages.getString( "back" ), new TabCommand( TABCOMMANDTYPE.BACK, popupMenu ) ); //$NON-NLS-1$ menuBar.addItem( backMenuItem ); backMenuItem.getElement().setId( "back" ); //$NON-NLS-1$ menuBar.addSeparator(); MenuItem reloadTabMenuItem = - new MenuItem( Messages.getString( "reloadTab" ), new TabCommand( TABCOMMANDTYPE.RELOAD, popupMenu ) ); //$NON-NLS-1$ + new MenuItem( Messages.getString( "reloadTab" ), new TabCommand( TABCOMMANDTYPE.RELOAD, popupMenu ) ); //$NON-NLS-1$ menuBar.addItem( reloadTabMenuItem ); reloadTabMenuItem.getElement().setId( "reloadTab" ); //$NON-NLS-1$ } if ( getTabPanel().getTabCount() > 1 ) { MenuItem reloadAllTabsMenuItem = - new MenuItem( Messages.getString( "reloadAllTabs" ), new TabCommand( TABCOMMANDTYPE.RELOAD_ALL, popupMenu ) ); //$NON-NLS-1$ + new MenuItem( Messages.getString( "reloadAllTabs" ), new TabCommand( TABCOMMANDTYPE.RELOAD_ALL, popupMenu ) ); //$NON-NLS-1$ menuBar.addItem( reloadAllTabsMenuItem ); reloadAllTabsMenuItem.getElement().setId( "reloadAllTabs" ); //$NON-NLS-1$ } else { @@ -288,26 +300,26 @@ public void onBrowserEvent( Event event ) { menuBar.addSeparator(); if ( getContent() instanceof IFrameTabPanel ) { MenuItem openTabInNewWindowMenuItem = - new MenuItem( - Messages.getString( "openTabInNewWindow" ), new TabCommand( TABCOMMANDTYPE.NEW_WINDOW, popupMenu ) ); //$NON-NLS-1$ + new MenuItem( + Messages.getString( "openTabInNewWindow" ), new TabCommand( TABCOMMANDTYPE.NEW_WINDOW, popupMenu ) ); //$NON-NLS-1$ menuBar.addItem( openTabInNewWindowMenuItem ); openTabInNewWindowMenuItem.getElement().setId( "openTabInNewWindow" ); //$NON-NLS-1$ MenuItem createDeepLinkMenuItem = - new MenuItem( - Messages.getString( "createDeepLink" ), new TabCommand( TABCOMMANDTYPE.CREATE_DEEP_LINK, popupMenu ) ); //$NON-NLS-1$ + new MenuItem( + Messages.getString( "createDeepLink" ), new TabCommand( TABCOMMANDTYPE.CREATE_DEEP_LINK, popupMenu ) ); //$NON-NLS-1$ menuBar.addItem( createDeepLinkMenuItem ); createDeepLinkMenuItem.getElement().setId( "deepLink" ); //$NON-NLS-1$ menuBar.addSeparator(); } menuBar - .addItem( new MenuItem( Messages.getString( "closeTab" ), new TabCommand( TABCOMMANDTYPE.CLOSE, popupMenu ) ) ); //$NON-NLS-1$ + .addItem( new MenuItem( Messages.getString( "closeTab" ), new TabCommand( TABCOMMANDTYPE.CLOSE, popupMenu ) ) ); //$NON-NLS-1$ if ( getTabPanel().getTabCount() > 1 ) { MenuItem closeOtherTabsMenuItem = - new MenuItem( Messages.getString( "closeOtherTabs" ), new TabCommand( TABCOMMANDTYPE.CLOSE_OTHERS, popupMenu ) ); //$NON-NLS-1$ + new MenuItem( Messages.getString( "closeOtherTabs" ), new TabCommand( TABCOMMANDTYPE.CLOSE_OTHERS, popupMenu ) ); //$NON-NLS-1$ menuBar.addItem( closeOtherTabsMenuItem ); closeOtherTabsMenuItem.getElement().setId( "closeOtherTabs" ); //$NON-NLS-1$ MenuItem closeAllTabsMenuItem = - new MenuItem( Messages.getString( "closeAllTabs" ), new TabCommand( TABCOMMANDTYPE.CLOSE_ALL, popupMenu ) ); //$NON-NLS-1$ + new MenuItem( Messages.getString( "closeAllTabs" ), new TabCommand( TABCOMMANDTYPE.CLOSE_ALL, popupMenu ) ); //$NON-NLS-1$ menuBar.addItem( closeAllTabsMenuItem ); closeAllTabsMenuItem.getElement().setId( "closeAllTabs" ); //$NON-NLS-1$ } else { @@ -320,6 +332,23 @@ public void onBrowserEvent( Event event ) { closeOtherTabsMenuItem.getElement().setId( "closeOtherTabs" ); //$NON-NLS-1$ closeAllTabsMenuItem.getElement().setId( "closeAllTabs" ); //$NON-NLS-1$ } + return menuBar; + } + + public void onRightClick( Event event ) { + FrameUtils.setEmbedVisibility( ( (IFrameTabPanel) getTabPanel().getSelectedTab().getContent() ).getFrame(), false ); + int left; + int top; + if ( event.getTypeInt() == Event.ONKEYDOWN ) { + PentahoTab tab = getTabPanel().getTab( getTabPanel().getSelectedTabIndex() ); + left = tab.getAbsoluteLeft() + ( tab.getOffsetWidth() / 2 ); + top = tab.getAbsoluteTop() + tab.getOffsetHeight(); + } else { + left = Window.getScrollLeft() + DOM.eventGetClientX( event ); + top = Window.getScrollTop() + DOM.eventGetClientY( event ); + } + popupMenu.setPopupPosition( adjustLeftIfNecessary( left ), top ); + MenuBar menuBar = getContextMenuBar(); popupMenu.setWidget( menuBar ); if ( isIEBrowser() ) { diff --git a/user-console/src/main/java/org/pentaho/mantle/client/ui/tabs/MantleTabMenuItem.java b/user-console/src/main/java/org/pentaho/mantle/client/ui/tabs/MantleTabMenuItem.java new file mode 100644 index 00000000000..cdce938be23 --- /dev/null +++ b/user-console/src/main/java/org/pentaho/mantle/client/ui/tabs/MantleTabMenuItem.java @@ -0,0 +1,20 @@ +package org.pentaho.mantle.client.ui.tabs; + +import com.google.gwt.core.client.Scheduler; +import com.google.gwt.user.client.ui.MenuBar; + +public class MantleTabMenuItem extends com.google.gwt.user.client.ui.MenuItem { + private MantleTab mantleTab; + + public MantleTabMenuItem( MantleTab tab ) { + super( tab.getLabelText(), (Scheduler.ScheduledCommand) null ); + mantleTab = tab; + refreshContextMenu(); + } + + public void refreshContextMenu() { + MenuBar contextMenuBar = mantleTab.getContextMenuBar( true ); + contextMenuBar.addStyleName( "tabsMenuContextSubMenu" ); + setSubMenu( contextMenuBar ); + } +} diff --git a/user-console/src/main/java/org/pentaho/mantle/client/ui/tabs/MantleTabPanel.java b/user-console/src/main/java/org/pentaho/mantle/client/ui/tabs/MantleTabPanel.java index 408d36bec37..b691a0cb9d7 100644 --- a/user-console/src/main/java/org/pentaho/mantle/client/ui/tabs/MantleTabPanel.java +++ b/user-console/src/main/java/org/pentaho/mantle/client/ui/tabs/MantleTabPanel.java @@ -21,18 +21,25 @@ package org.pentaho.mantle.client.ui.tabs; import com.google.gwt.core.client.GWT; +import com.google.gwt.core.client.Scheduler; import com.google.gwt.dom.client.NodeList; +import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; +import com.google.gwt.user.client.Event; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.Window.ClosingEvent; import com.google.gwt.user.client.Window.ClosingHandler; +import com.google.gwt.user.client.ui.DecoratedPopupPanel; +import com.google.gwt.user.client.ui.MenuBar; +import com.google.gwt.user.client.ui.MenuItem; import com.google.gwt.user.client.ui.PopupPanel; import com.google.gwt.user.client.ui.Widget; import org.pentaho.gwt.widgets.client.dialogs.IDialogCallback; import org.pentaho.gwt.widgets.client.dialogs.MessageDialogBox; import org.pentaho.gwt.widgets.client.tabs.PentahoTab; import org.pentaho.gwt.widgets.client.utils.FrameUtils; +import org.pentaho.gwt.widgets.client.utils.MenuBarUtils; import org.pentaho.gwt.widgets.client.utils.string.StringUtils; import org.pentaho.mantle.client.dialogs.WaitPopup; import org.pentaho.mantle.client.events.EventBusUtil; @@ -50,6 +57,7 @@ import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; public class MantleTabPanel extends org.pentaho.gwt.widgets.client.tabs.PentahoTabPanel { @@ -58,12 +66,23 @@ public class MantleTabPanel extends org.pentaho.gwt.widgets.client.tabs.PentahoT private static final String FRAME_ID_PRE = "frame_"; //$NON-NLS-1$ private static int frameIdCount = 0; + private static MenuBar tabsMenuBar; + private static MenuItem tabsMenuItem; + private static TabContextMenuBar tabsSubMenuBar; + + private static final String CLASS_EMPTY_TABS_MENU = "empty-tabs-menu"; + private static final String CLASS_FLEX_ROW = "flex-row"; + + private HashMap menuItemHashMap; + public MantleTabPanel() { this( false ); } public MantleTabPanel( boolean setupNativeHooks ) { super(); + menuItemHashMap = new HashMap<>(); + if ( setupNativeHooks ) { setupNativeHooks( this ); } @@ -85,6 +104,16 @@ public void onWindowClosing( ClosingEvent event ) { } ); } + public void setTabsMenu( MenuBar menuBar, MenuItem menuItem ) { + tabsMenuBar = menuBar; + tabsMenuItem = menuItem; + tabsSubMenuBar = new TabContextMenuBar( true ); + tabsSubMenuBar.addStyleName( "tabsSubMenuBar" ); + tabsMenuItem.setSubMenu( tabsSubMenuBar ); + tabsMenuBar.addStyleName( CLASS_FLEX_ROW ); + tabsMenuBar.addStyleName( CLASS_EMPTY_TABS_MENU ); + } + public void addTab( String text, String tooltip, boolean closeable, Widget content ) { // make sure the perspective is enabled PerspectiveManager.getInstance().enablePerspective( PerspectiveManager.OPENED_PERSPECTIVE, true ); @@ -94,6 +123,69 @@ public void addTab( String text, String tooltip, boolean closeable, Widget conte if ( getSelectedTab() == null ) { selectTab( tab ); } + MantleTabMenuItem menuItem = createTabMenuItem( tab ); + linkTabToMenuItem( tab, menuItem ); + tabsSubMenuBar.addItem( menuItem ); + contextMenuRefreshThreshold( true ); + updateTabMenuText( tab ); + } + + public void linkTabToMenuItem( PentahoTab pentahoTab, MantleTabMenuItem mantleTabMenuItem ) { + menuItemHashMap.put( pentahoTab, mantleTabMenuItem ); + } + + public MantleTabMenuItem getLinkedTabMenuItem( PentahoTab pentahoTab ) { + return menuItemHashMap.get( pentahoTab ); + } + + public void deleteTabMenuItemLinkage( PentahoTab pentahoTab ) { + menuItemHashMap.remove( pentahoTab ); + } + + public void renameMenuTab( PentahoTab tab ){ + getLinkedTabMenuItem( tab ).setText( tab.getLabelText() ); + updateTabMenuText( tab ); + } + + /** + * Update the tabsMenuBar text to reflect the currently selected tab. + * If no tab is selected, the text is empty, and the menuBar is hidden. + * @param selectedTab + */ + public void updateTabMenuText( PentahoTab selectedTab ) { + if ( selectedTab == null ) { + tabsMenuBar.addStyleName( CLASS_EMPTY_TABS_MENU ); + tabsMenuItem.setText( "" ); + } else { + tabsMenuBar.removeStyleName( CLASS_EMPTY_TABS_MENU ); + String tabMenuText; + int tabCount = getTabCount(); + if ( tabCount > 1 ) { + int tabIndex = tabsSubMenuBar.getItemIndex( getLinkedTabMenuItem( selectedTab ) ) + 1; + tabMenuText = "Tab (" + tabIndex + "/" + tabCount + ") " + selectedTab.getLabelText(); + } else { + tabMenuText = selectedTab.getLabelText(); + } + tabsMenuItem.setText( tabMenuText ); + } + } + + private MantleTabMenuItem createTabMenuItem( MantleTab tab ) { + MantleTabMenuItem tabMenuItem = new MantleTabMenuItem( tab ); + return tabMenuItem; + } + + /** + * Refresh the context menu when it changes from one to many. + * Disables/Enables "All Tabs" and "Other Tabs" menu items: + * - If a tab is added and there are now 2 tabs + * - If a tab is removed and there is now only 1 tab + * @param added + */ + private void contextMenuRefreshThreshold( boolean added ) { + if ( ( added && menuItemHashMap.size() == 2 ) || ( !added && menuItemHashMap.size() == 1 ) ) { + menuItemHashMap.values().forEach( m -> m.refreshContextMenu() ); + } } public void showNewURLTab( String tabName, String tabTooltip, String url, boolean setFileInfoInFrame, @@ -595,6 +687,9 @@ public void okPressed() { } super.closeTab( closeTab, invokePreTabCloseHook ); + tabsSubMenuBar.removeItem( getLinkedTabMenuItem( closeTab ) ); + deleteTabMenuItemLinkage( closeTab ); + contextMenuRefreshThreshold(false); if ( getTabCount() == 0 ) { allTabsClosed(); @@ -605,6 +700,9 @@ public void okPressed() { List selectedItems = SolutionBrowserPanel.getInstance().getFilesListPanel().getSelectedFileItems(); EventBusUtil.EVENT_BUS.fireEvent( new SolutionBrowserCloseEvent( selectTabContent, selectedItems ) ); } + + // now that we have closed the target tab, update the tabsMenu text to what tab is currently selected (if there is one) + updateTabMenuText( getSelectedTab() ); } public static native void clearClosingFrame( Element frame ) diff --git a/user-console/src/main/java/org/pentaho/mantle/client/ui/tabs/TabContextMenuBar.java b/user-console/src/main/java/org/pentaho/mantle/client/ui/tabs/TabContextMenuBar.java new file mode 100644 index 00000000000..bfb0b4c4f7c --- /dev/null +++ b/user-console/src/main/java/org/pentaho/mantle/client/ui/tabs/TabContextMenuBar.java @@ -0,0 +1,62 @@ +package org.pentaho.mantle.client.ui.tabs; + +import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.Event; +import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.ui.DecoratedPopupPanel; +import com.google.gwt.user.client.ui.MenuItem; +import org.pentaho.gwt.widgets.client.utils.MenuBarUtils; + +public class TabContextMenuBar extends com.google.gwt.user.client.ui.MenuBar { + + String heightPx; + String maxHeightPx; + + int height; + int top; + int menuBarTop; + + public TabContextMenuBar( boolean vertical ) { + super( vertical ); + } + + @Override + public void onBrowserEvent( Event event ) { + super.onBrowserEvent( event ); + + MenuItem item = MenuBarUtils.findItem( this, DOM.eventGetTarget( event ) ); + int type = event.getTypeInt(); + switch ( type ) { + case Event.ONMOUSEOVER: { + if ( item != null ) { + DecoratedPopupPanel popup = MenuBarUtils.getPopup( this ); + + // Set the menuBar height to be the sum of it's menuItem's heights + height = MenuBarUtils.calculatePopupHeight( item.getSubMenu() ); + + top = item.getAbsoluteTop(); + menuBarTop = this.getAbsoluteTop(); + + // if this menu is at the bottom of the screen, try to give it more space + if( Window.getClientHeight() - top < height ){ + top = Window.getClientHeight() - height; + } + + // if popup top is above the menuBar, bring it just beneath the menuBar + if ( top < menuBarTop ) { + top = menuBarTop + 1; + } + + heightPx = height + "px"; + maxHeightPx = "calc( 100vh - " + top + "px )"; + popup.getWidget().getElement().getStyle().setProperty( "height", heightPx ); + popup.getWidget().getElement().getStyle().setProperty( "maxHeight", maxHeightPx ); + + //Set popup's left to be next to the parent menuBar + popup.setPopupPosition( this.getOffsetWidth(), top ); + } + break; + } + } + } +} diff --git a/user-console/src/main/java/org/pentaho/mantle/client/ui/xul/MantleXul.java b/user-console/src/main/java/org/pentaho/mantle/client/ui/xul/MantleXul.java index 6dcbe91975d..90ef6840349 100644 --- a/user-console/src/main/java/org/pentaho/mantle/client/ui/xul/MantleXul.java +++ b/user-console/src/main/java/org/pentaho/mantle/client/ui/xul/MantleXul.java @@ -29,6 +29,8 @@ import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.DeckPanel; +import com.google.gwt.user.client.ui.MenuBar; +import com.google.gwt.user.client.ui.MenuItem; import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.Tree; @@ -51,6 +53,7 @@ import org.pentaho.mantle.client.events.SolutionBrowserSelectEventHandler; import org.pentaho.mantle.client.messages.Messages; import org.pentaho.mantle.client.objects.MantleXulOverlay; +import org.pentaho.mantle.client.solutionbrowser.SolutionBrowserPanel; import org.pentaho.mantle.client.solutionbrowser.tabs.IFrameTabPanel; import org.pentaho.ui.xul.XulException; import org.pentaho.ui.xul.XulOverlay; @@ -84,6 +87,7 @@ public class MantleXul implements IXulLoaderCallback, SolutionBrowserOpenEventHa private SimplePanel menubar = new SimplePanel(); private SimplePanel burgerToolbarWrapper = new SimplePanel(); + private SimplePanel tabsMenuBarWrapper = new SimplePanel(); private SimplePanel adminPerspective = new SimplePanel(); private DeckPanel adminContentDeck = new DeckPanel(); @@ -154,6 +158,11 @@ public void xulLoaded( GwtXulRunner runner ) { burgerToolbarWrapper.setStylePrimaryName( "burgerToolbar-Wrapper" ); burgerToolbarWrapper.setWidget( burgerToolbar ); + MenuBar tabsMenuBar = ( MenuBar ) container.getDocumentRoot().getElementById( "tabsMenuBar" ).getManagedObject(); + MenuItem tabsMenuItem = ( MenuItem ) container.getDocumentRoot().getElementById( "tabsMenu" ).getManagedObject(); + SolutionBrowserPanel.getInstance().getContentTabPanel().setTabsMenu( tabsMenuBar, tabsMenuItem ); + tabsMenuBarWrapper.setWidget( tabsMenuBar ); + // Get the menubar from the XUL doc Widget menu = (Widget) container.getDocumentRoot().getElementById( "mainMenubar" ).getManagedObject(); //$NON-NLS-1$ menubar.setWidget( menu ); @@ -323,6 +332,10 @@ public Widget getBurgerToolbarWrapper() { return burgerToolbarWrapper; } + public SimplePanel getTabsMenuBarWrapper(){ + return tabsMenuBarWrapper; + } + public Widget getMenubar() { return menubar; } diff --git a/user-console/src/main/resources/org/pentaho/mantle/public/Mantle.jsp b/user-console/src/main/resources/org/pentaho/mantle/public/Mantle.jsp index 121a0cdef10..16899b14694 100644 --- a/user-console/src/main/resources/org/pentaho/mantle/public/Mantle.jsp +++ b/user-console/src/main/resources/org/pentaho/mantle/public/Mantle.jsp @@ -12,7 +12,7 @@ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * -* Copyright (c) 2002-2021 Hitachi Vantara. All rights reserved. +* Copyright (c) 2002-2023 Hitachi Vantara. All rights reserved. --%> @@ -203,10 +203,11 @@
- +
+
diff --git a/user-console/src/main/resources/org/pentaho/mantle/public/MantleStyle.css b/user-console/src/main/resources/org/pentaho/mantle/public/MantleStyle.css index 1816028130d..9190b5a6e41 100644 --- a/user-console/src/main/resources/org/pentaho/mantle/public/MantleStyle.css +++ b/user-console/src/main/resources/org/pentaho/mantle/public/MantleStyle.css @@ -644,12 +644,6 @@ code { /* end fix BISERVER-6181 */ -/* BISERVER-6442 */ -#previewResultsTable { - overflow: hidden; - width: 525px; -} - .adminContentPanel > tbody > tr > td > div { height: 100%; } diff --git a/user-console/src/main/resources/org/pentaho/mantle/public/themes/ruby/mantleRuby.css b/user-console/src/main/resources/org/pentaho/mantle/public/themes/ruby/mantleRuby.css index 5655b35703e..045d0238fd9 100644 --- a/user-console/src/main/resources/org/pentaho/mantle/public/themes/ruby/mantleRuby.css +++ b/user-console/src/main/resources/org/pentaho/mantle/public/themes/ruby/mantleRuby.css @@ -1183,7 +1183,7 @@ div#customDropdownPopupMajor .gwt-MenuBar-vertical .gwt-MenuItem:hover:not(.gwt- border-spacing: 0; } -#mainMenubar .gwt-MenuItem { +#mainMenubar .gwt-MenuItem, #pucTabsMenuBar .gwt-MenuItem{ color: #414141; font-size: 13px; font-family: OpenSansLight; @@ -1191,7 +1191,7 @@ div#customDropdownPopupMajor .gwt-MenuBar-vertical .gwt-MenuItem:hover:not(.gwt- padding: 5px 15px; } -#mainMenubar .gwt-MenuItem-selected { +#mainMenubar .gwt-MenuItem-selected, #pucTabsMenuBar .gwt-MenuItem-selected{ background: #cc0000; border: 0 none; color: #FFF; @@ -1206,12 +1206,18 @@ div#customDropdownPopupMajor .gwt-MenuBar-vertical .gwt-MenuItem:hover:not(.gwt- #mainToolbarWrapper > tbody > tr, #mainToolbarWrapper > tbody > tr > td, #mainToolbarWrapper > tbody > tr > td > div, -#mainToolbar, -#burgerToolbar, :is(#mainToolbar, #burgerToolbar) > tbody > tr > td > table { display: contents; } +#mainToolbar, #burgerToolbar, #tabsMenuBar { + display: flex; + flex: 0 1 auto; + width: auto !important; + flex-wrap: wrap; + gap: 0; +} + :where(#pucWrapper:not(.burger-mode)) #burgerToolbar { display: none; } @@ -1226,6 +1232,16 @@ div#customDropdownPopupMajor .gwt-MenuBar-vertical .gwt-MenuItem:hover:not(.gwt- max-width: var(--flex-max-width, 10px); } +:where(#pucWrapper.burger-mode) #mainToolbar .spacer { + /* Nuke the spacer widths because these would only flex after the whole toolbar + would wrap to a new row. This ensures less rows from the start. */ + width: auto !important; +} + +:where(#pucWrapper.burger-mode) #mainToolbar { + margin-left: auto; +} + :is(#mainToolbar, #burgerToolbar) :is(.toolbar-button, .toolbar-toggle-button) { border-width: var(--puc-toolbar-button-border-width); } @@ -1582,10 +1598,14 @@ hr { } /* region Burger Menu Mode */ -#burgerBarPerspectiveMenu { +#pucTabsMenuBar { display: none; } +#pucTabsMenuBar > * { + display: contents; +} + /* puc header */ :where(.burger-mode) #pucContent { /* top: var(--puc-header-burger-mode-height); */ @@ -1595,8 +1615,9 @@ hr { display: none; } -:where(.burger-mode) #burgerBarPerspectiveMenu { - display: block; +:where(.burger-mode) #pucTabsMenuBar { + /* Show children when burger mode */ + display: contents; } :where(.burger-mode) #pucHeader { @@ -1756,9 +1777,54 @@ hr { left: calc(100vw - 210px) !important; } -:where(.burger-mode) -.toolbar-button-focus-panel:where(#openButton, #newButton, #dummyPluginContentButton, #printButton) { +:where(.burger-mode) .toolbar-button-focus-panel:where(#openButton, #newButton, #dummyPluginContentButton, #printButton) { + display: none; +} + +.pentaho-tab-bar { + display: flex; + width: 100vw; + overflow-x: auto; + scrollbar-width: thin; + overflow-y: hidden; +} + +:where(.burger-mode) .pentaho-tab-bar { + display: none; +} + +#tabsMenuBar.empty-tabs-menu { display: none; } /* endregion Burger Menu Mode */ + +#pucTabsMenuBar table td, .tabsSubMenuBar table td.gwt-MenuItem { + width: 130px; + display: inline-block; +} + +#pucTabsMenuBar table td { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +.tabsSubMenuBar table td.gwt-MenuItem { + word-wrap:break-word; +} + +.tabsSubMenuBar { + position: relative; +} + +.tabsMenuContextSubMenu, .tabsSubMenuBar { + overflow-y: auto; +} + +/* when the viewport width is 400px or less, preserve the tabsMenuBar width and shrink the context subMenu*/ +@media (max-width: 400px) { + .tabsMenuContextSubMenu table td.gwt-MenuItem { + width: calc(100vw - 235px); + } +} diff --git a/user-console/src/main/resources/org/pentaho/mantle/public/xul/mantle.xul b/user-console/src/main/resources/org/pentaho/mantle/public/xul/mantle.xul index 2d9ed26c3e7..51d8307a76a 100644 --- a/user-console/src/main/resources/org/pentaho/mantle/public/xul/mantle.xul +++ b/user-console/src/main/resources/org/pentaho/mantle/public/xul/mantle.xul @@ -70,6 +70,10 @@ tooltiptext="${burgerMenu}"/> + + + +