Libraryless. Click here for Pure Java version (4190L/28K).
// Adapted from: https://github.com/topalavlad/ComponentSwitcher sbool installInternalFrameSwitcher_v3_debug; static SwitchDispatcher installInternalFrameSwitcher_v3(final JDesktopPane desktop) { ret swing -> SwitchDispatcher { new DesktopListener desktopListener; desktop.addContainerListener(desktopListener); SwitchDispatcher dispatcher = new(new DesktopSwitcher(desktop), desktopListener); dispatcher.start(); ret dispatcher; }; } sclass JInternalFrameCellRenderer extends DefaultListCellRenderer { static int marginW = 20, marginH = 3; public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); setText(((JInternalFrame) value).getTitle()); setMargin(marginW, marginH, this); ret c; } } sclass DesktopListener extends ContainerAdapter implements SwitchableComponentsListener { private final List frames = new ArrayList<>(); private final boolean titleOptional; private final InternalFrameAdapter frameActivatedListener = new InternalFrameAdapter() { @Override public void internalFrameActivated(InternalFrameEvent e) { JInternalFrame frame = e.getInternalFrame(); frames.remove(frame); frames.add(0, frame); } }; public DesktopListener() { this(false); } public DesktopListener(boolean titleOptional) { this.titleOptional = titleOptional; } @Override public void componentAdded(final ContainerEvent e) { if (e.getChild() instanceof JInternalFrame) { final JInternalFrame frame = (JInternalFrame) e.getChild(); if (isTitleOptional() || frame.getTitle() != null && !frame.getTitle().trim().isEmpty()) { frames.add(frame); frame.addInternalFrameListener(frameActivatedListener); } } } @Override public void componentRemoved(final ContainerEvent e) { if (e.getChild() instanceof JInternalFrame) { JInternalFrame frame = (JInternalFrame) e.getChild(); frames.remove(frame); frame.removeInternalFrameListener(frameActivatedListener); } } private boolean isTitleOptional() { return titleOptional; } public List<JInternalFrame> getSwitchableComponentList() { return frames; } } sclass DesktopSwitcher { private final JDesktopPane jDesktopPane; private SwitchDialog switchDialog; bool instaSwitch; public DesktopSwitcher(JDesktopPane jDesktopPane) { this.jDesktopPane = jDesktopPane; switchDialog = new SwitchDialog(SwingUtilities.getWindowAncestor(jDesktopPane), new ArrayList<JInternalFrame>()); initMouseListener(); } public void previous(List<JInternalFrame> switchableComponentList) { bool vis = isVisible(); showMenu(switchableComponentList); switchDialog.selectPrevious(); if (instaSwitch && !vis) switchDialog.selectPrevious(); } public void next(List<JInternalFrame> switchableComponentList) { bool vis = isVisible(); showMenu(switchableComponentList); switchDialog.selectNext(); if (instaSwitch && !vis) switchDialog.selectNext(); } public void dismiss() { hideMenu(); } public JDesktopPane getDesktop() { return jDesktopPane; } public boolean hasFocus() { return switchDialog.hasFocus() || switchDialog.getList().hasFocus(); } public SwitchDialog getSwitchDialog() { return switchDialog; } private void showMenu(List<JInternalFrame> switchableComponentList) { switchDialog.setSwitchableComponents(switchableComponentList); if (!switchableComponentList.isEmpty()) { switchDialog.pack(); switchDialog.setLocationRelativeTo(jDesktopPane); switchDialog.setVisible(true); } } bool isVisible() { ret switchDialog != null && switchDialog.isVisible(); } private void hideMenu() { if (isVisible()) { pcall { JInternalFrame selected = switchDialog.getSelected(); if (selected != null) { switchDialog.unselect(); selected.setSelected(true); selected.toFront(); } } switchDialog.dispose(); } } private void initMouseListener() { switchDialog.getList().addMouseListener(new MouseAdapter() { @Override public void mouseReleased(final MouseEvent e) { hideMenu(); } }); } } sclass SwitchDispatcher implements KeyEventDispatcher { private static final KeyStroke nextStroke = KeyStroke.getKeyStroke("ctrl TAB"); private static final KeyStroke previousStroke = KeyStroke.getKeyStroke("ctrl shift TAB"); DesktopSwitcher switcher; SwitchableComponentsListener desktopListener; F0<Bool> shouldSwitch; // check for additional focused components here bool instaSwitch = true; // actually switch to previous frame on first Ctrl+Tab (otherwise Ctrl+Tab just brings up the switcher list) public SwitchDispatcher(DesktopSwitcher switcher, SwitchableComponentsListener switchableComponentsListener) { this.switcher = switcher; this.desktopListener = switchableComponentsListener; } public void start() { KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(this); } public void stop() { KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher(this); } public boolean dispatchKeyEvent(KeyEvent e) { boolean _shouldSwitch = isDesktopPaneFocused(e.getComponent(), switcher.getDesktop()) || switcher.hasFocus() || isTrue(callF(shouldSwitch)); if (!_shouldSwitch) false; switcher.instaSwitch = instaSwitch; // copy config KeyStroke keyStrokeForEvent = KeyStroke.getKeyStrokeForEvent(e); boolean next = nextStroke.equals(keyStrokeForEvent); boolean previous = previousStroke.equals(keyStrokeForEvent); boolean dismiss = e.getKeyCode() == KeyEvent.VK_CONTROL && !e.isControlDown(); if (installInternalFrameSwitcher_v3_debug) print("Have keystroke: " + keyStrokeForEvent + ", " + next + "/" + previous + "/" + dismiss); if (next) { switcher.next(desktopListener.getSwitchableComponentList()); } else if (previous) { switcher.previous(desktopListener.getSwitchableComponentList()); } else if (dismiss) { switcher.dismiss(); } return next || previous || dismiss; } private boolean isDesktopPaneFocused(Component component, JDesktopPane desktop) { return getDesktopPaneParent(component) == desktop; } private JDesktopPane getDesktopPaneParent(Component component) { Component parent = component; while (parent != null && !(parent instanceof JDesktopPane)) { parent = parent.getParent(); } return (JDesktopPane) parent; } } sinterface SwitchableComponentsListener { /** * Get a list of the components that the user can switch through. * Ideally, this would be sorted by the last focused order. * * @return - list of switchable components of type JInternalFrame */ List<JInternalFrame> getSwitchableComponentList(); } sclass SwitchDialog extends JDialog { private final JList<JInternalFrame> list; public SwitchDialog(Window owner, List<JInternalFrame> titles) { super(owner); setUndecorated(true); list = new JList<>(new Vector<>(titles)); addFocusListener(focusLostListener); onWindowClosed(this, r { /* AWT keeps references to stale components around! e.g. last in java.util.LinkedList keyEventDispatchers in java.awt.DefaultKeyboardFocusManager value in sun.awt.MostRecentKeyValue shadowMostRecentKeyValue in sun.awt.AppContext appContext in java.awt.EventQueue So we free the links to JInternalFrames: */ list.setModel(new DefaultListModel); }); initList(); setContentPane(jCenteredSection(" Frames ", list)); pack(); } private void initList() { list.setCellRenderer(new JInternalFrameCellRenderer); list.setSelectedIndex(0); list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); list.addFocusListener(focusLostListener); list.setSelectionModel(new DefaultListSelectionModel() { public void removeSelectionInterval(int index0, int index1) {} public void addSelectionInterval(int index0, int index1) { super.setSelectionInterval(index0, index1); } }); } public void selectNext() { int indexToSelect = list.getSelectedIndex() != list.getModel().getSize() - 1 ? list.getSelectedIndex() + 1 : 0; setSelectedIndexAndScroll(list, indexToSelect); } public void selectPrevious() { int indexToSelect = list.getSelectedIndex() != 0 ? list.getSelectedIndex() - 1 : list.getModel().getSize() - 1; setSelectedIndexAndScroll(list, indexToSelect > -1 ? indexToSelect : 0); } public JInternalFrame getSelected() { return list.getSelectedValue(); } public void unselect() { list.setSelectedIndex(-1); } public void setSwitchableComponents(List<JInternalFrame> switchableComponents) { JInternalFrame oldSelection = list.getSelectedValue(); list.setListData(new Vector<>(switchableComponents)); list.setSelectedValue(oldSelection, false); } public JList<JInternalFrame> getList() { return list; } private final FocusAdapter focusLostListener = new FocusAdapter { public void focusLost(FocusEvent e) { dispose(); } }; }
Began life as a copy of #1016948
download show line numbers debug dex old transpilations
Travelled to 11 computer(s): bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, irmadwmeruwu, ishqpsrjomds, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt
No comments. add comment
Snippet ID: | #1019718 |
Snippet name: | installInternalFrameSwitcher_v3 |
Eternal ID of this version: | #1019718/19 |
Text MD5: | 66ed36a75126910349e8cff717f752c5 |
Transpilation MD5: | cfaaec6151b77f21a70f02310626506b |
Author: | stefan |
Category: | javax / gui |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2020-10-06 14:03:30 |
Source code size: | 10010 bytes / 298 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 354 / 485 |
Version history: | 18 change(s) |
Referenced in: | [show references] |