sbool installInternalFrameSwitcher_v2_debug;
svoid installInternalFrameSwitcher_v2(final JDesktopPane desktop) {
swing {
new DesktopListener desktopListener;
desktop.addContainerListener(desktopListener);
new SwitchDispatcher<JInternalFrame>(new DesktopSwitcher(desktop), desktopListener).start();
}
}
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<JInternalFrame> {
private final List<JInternalFrame> 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 implements Switcher<JInternalFrame> {
private final JDesktopPane jDesktopPane;
private SwitchDialog<JInternalFrame> switchDialog;
public DesktopSwitcher(JDesktopPane jDesktopPane) {
this.jDesktopPane = jDesktopPane;
switchDialog = new SwitchDialog<>(SwingUtilities.getWindowAncestor(jDesktopPane), new ArrayList<JInternalFrame>());
initMouseListener();
}
public void previous(List<JInternalFrame> switchableComponentList) {
showMenu(switchableComponentList);
switchDialog.selectPrevious();
}
public void next(List<JInternalFrame> switchableComponentList) {
showMenu(switchableComponentList);
switchDialog.selectNext();
}
public void dismiss() {
hideMenu();
}
@Override
public JDesktopPane getDesktop() {
return jDesktopPane;
}
@Override
public boolean hasFocus() {
return switchDialog.hasFocus() || switchDialog.getList().hasFocus();
}
public SwitchDialog<JInternalFrame> getSwitchDialog() {
return switchDialog;
}
private void showMenu(List<JInternalFrame> switchableComponentList) {
switchDialog.setSwitchableComponents(switchableComponentList);
if (!switchableComponentList.isEmpty()) {
switchDialog.pack();
switchDialog.setLocationRelativeTo(jDesktopPane);
switchDialog.setVisible(true);
}
}
private void hideMenu() {
if (switchDialog != null && switchDialog.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<T> implements KeyEventDispatcher {
private static final KeyStroke nextStroke = KeyStroke.getKeyStroke("ctrl TAB");
private static final KeyStroke previousStroke = KeyStroke.getKeyStroke("ctrl shift TAB");
private final Switcher<T> switcher;
private final SwitchableComponentsListener<T> desktopListener;
public SwitchDispatcher(Switcher<T> switcher, SwitchableComponentsListener<T> 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();
if (!shouldSwitch) {
return false;
}
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_v2_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<T> {
/**
* 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 T
*/
List<T> getSwitchableComponentList();
}
/**
* This class will do the actual switching based on the lists of components it receives.
*
* @param <T> - The type of the components that can be switched. {@link javax.swing.JInternalFrame} initially but
* will be extended for tabs and other components.
*/
sinterface Switcher<T> {
/**
* Trigger this to select the previous component in the list
*
* @param switchableComponentList - list of all the switchable components
*/
void previous(List<T> switchableComponentList);
/**
* Trigger this to select the next component in the list
*
* @param switchableComponentList - list of all the switchable components
*/
void next(List<T> switchableComponentList);
/**
* This method will hide the dialog that shows all the switchable components if it exists.
*/
void dismiss();
/**
* Returns the desktop pane on which the switcher is working
*/
JDesktopPane getDesktop();
/**
* Checks whether the switcher component currently has focus
* @return - true if the switch dialog is open and has focus; false otherwise
*/
boolean hasFocus();
}
sclass SwitchDialog<T> extends JDialog {
private final JList<T> list;
public SwitchDialog(Window owner, List<T> titles) {
super(owner);
setUndecorated(true);
list = new JList<>(new Vector<>(titles));
addFocusListener(focusLostListener);
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;
list.setSelectedIndex(indexToSelect);
}
public void selectPrevious() {
int indexToSelect = list.getSelectedIndex() != 0
? list.getSelectedIndex() - 1
: list.getModel().getSize() - 1;
list.setSelectedIndex(indexToSelect > -1 ? indexToSelect : 0);
}
public T getSelected() {
return list.getSelectedValue();
}
public void unselect() {
list.setSelectedIndex(-1);
}
public void setSwitchableComponents(List<T> switchableComponents) {
T oldSelection = list.getSelectedValue();
list.setListData(new Vector<>(switchableComponents));
list.setSelectedValue(oldSelection, false);
}
public JList<T> getList() {
return list;
}
private final FocusAdapter focusLostListener = new FocusAdapter {
public void focusLost(FocusEvent e) {
dispose();
}
};
}
Began life as a copy of #1016825
download show line numbers debug dex old transpilations
Travelled to 14 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, irmadwmeruwu, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt
No comments. add comment
| Snippet ID: | #1016948 |
| Snippet name: | installInternalFrameSwitcher_v2 |
| Eternal ID of this version: | #1016948/14 |
| Text MD5: | f0c4e3ee36cf88d4eaff3456c7eb859f |
| Author: | stefan |
| Category: | javax / gui |
| Type: | JavaX fragment (include) |
| Public (visible to everyone): | Yes |
| Archived (hidden from active list): | No |
| Created/modified: | 2018-09-26 17:21:32 |
| Source code size: | 10033 bytes / 311 lines |
| Pitched / IR pitched: | No / No |
| Views / Downloads: | 792 / 841 |
| Version history: | 13 change(s) |
| Referenced in: | [show references] |