/* * Licensed Materials - Property of Perforce Software, Inc. * © Copyright Perforce Software, Inc. 2014, 2021 * © Copyright IBM Corp. 2009, 2014 * © Copyright ILOG 1996, 2009 * All Rights Reserved. * * Note to U.S. Government Users Restricted Rights: * The Software and Documentation were developed at private expense and * are "Commercial Items" as that term is defined at 48 CFR 2.101, * consisting of "Commercial Computer Software" and * "Commercial Computer Software Documentation", as such terms are * used in 48 CFR 12.212 or 48 CFR 227.7202-1 through 227.7202-4, * as applicable. */ /** * This examples shows illustrates how to use various * accessibility features inside a Perforce JViews Diagrammer. */ import java.awt.AWTEvent; import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Font; import java.awt.Image; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.image.BufferedImage; import java.awt.image.WritableRaster; import java.net.URL; import java.util.Comparator; import java.util.HashMap; import java.util.Map; import java.util.ResourceBundle; import javax.swing.Box; import javax.swing.JCheckBoxMenuItem; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; import javax.swing.JToolBar; import ilog.views.IlvAccelerator; import ilog.views.IlvGrapher; import ilog.views.IlvGraphic; import ilog.views.IlvManager; import ilog.views.IlvManagerView; import ilog.views.IlvRect; import ilog.views.accelerator.IlvCycleSelectAccelerator; import ilog.views.accelerator.IlvDeleteSelectionAccelerator; import ilog.views.accelerator.IlvExpandSelectionAccelerator; import ilog.views.accelerator.IlvFitToSizeAccelerator; import ilog.views.accelerator.IlvIdentityAccelerator; import ilog.views.accelerator.IlvMoveSelectionAccelerator; import ilog.views.accelerator.IlvPopupMenuAccelerator; import ilog.views.accelerator.IlvRotateAccelerator; import ilog.views.accelerator.IlvScrollDownAccelerator; import ilog.views.accelerator.IlvScrollLeftAccelerator; import ilog.views.accelerator.IlvScrollRightAccelerator; import ilog.views.accelerator.IlvScrollUpAccelerator; import ilog.views.accelerator.IlvSelectAllAccelerator; import ilog.views.accelerator.IlvZoomInAccelerator; import ilog.views.accelerator.IlvZoomOutAccelerator; import ilog.views.diagrammer.IlvDiagrammer; import ilog.views.diagrammer.IlvDiagrammerProduct; import ilog.views.diagrammer.application.IlvDiagrammerAction; import ilog.views.diagrammer.application.IlvDiagrammerFrame; import ilog.views.diagrammer.application.IlvDiagrammerMenu; import ilog.views.diagrammer.application.IlvDiagrammerMenuBar; import ilog.views.diagrammer.project.IlvDiagrammerProject; import ilog.views.sdm.IlvSDMEngine; import ilog.views.sdm.IlvSDMView; import ilog.views.sdm.renderer.IlvRendererUtil; import ilog.views.swing.IlvPopupMenuContext; import ilog.views.swing.IlvPopupMenuManager; import ilog.views.swing.IlvSimplePopupMenu; import ilog.views.util.IlvProductUtil; import ilog.views.util.internal.IlvSplash; import ilog.views.util.swing.IlvSwingUtil; /** * This is a very simple application that shows how to use various * accessibility features inside an IlvDiagrammer. */ public class AccessibleDiagram extends IlvDiagrammerFrame { private ResourceBundle bundle; private URL backgroundStyleSheet; private URL normalBackgroundStyleSheet; private URL highContrastBackgroundStyleSheet; private URL varyShapesStyleSheet; private URL varyShapesOnStyleSheet; private URL varyShapesOffStyleSheet; /** * The color modes. */ private static int NORMAL = 0; private static int GRAYSCALE = 1; private static int DEUTAN = 2; private int colorMode = NORMAL; private boolean blockColorModeChange = false; private JMenu colorModeMenu; /** * Varying shapes modes. */ private boolean varyingShapes = false; /** * High contrast mode. */ private boolean highContrastMode = false; /** * High contrast colors, for the GUI only. */ private Color lightColor = new Color(238, 238, 238); private Color darkColor = new Color(51, 51, 51); /** * Fonts for normal contrast. */ private Map<Object, Font> normalContrastFonts = new HashMap<Object, Font>(); /** * Fonts for high contrast. */ private Map<Object, Font> highContrastFonts = new HashMap<Object, Font>(); /** * The popup menu. */ private JPopupMenu popupMenu = null; /** * The about dialog. */ private JDialog aboutDialog = null; /** * The label showing the keypress. */ private JLabel statusLabel = new JLabel("No focus on view"); /** * Comparator for the traversal order: nesting has highest, then x has * priority */ Comparator<IlvGraphic> nestedThenXThenY = new Comparator<IlvGraphic>() { Override public int compare(IlvGraphic a, IlvGraphic b) { IlvGrapher commonBag = IlvGrapher.getLowestCommonGrapher(a, b); if (commonBag != null) { while (a.getGraphicBag() != commonBag) a = (IlvGraphic) a.getGraphicBag(); while (b.getGraphicBag() != commonBag) b = (IlvGraphic) b.getGraphicBag(); } // use model coordinates, not graphic coordinates to have a // predictive behavior IlvSDMEngine engine = IlvSDMEngine.getSDMEngine(a); if (IlvSDMEngine.getSDMEngine(b) != engine) return 0; Object ma = engine.getObject(a); Object mb = engine.getObject(b); if (ma == mb) return 0; if (ma == null) return -1; if (mb == null) return 1; // does not work when coordinates are not stored in the model // or when coordinates are stored as latitude/logitude float ax = IlvRendererUtil.getGraphicPropertyAsFloat(engine, ma, "x", null, -1); float bx = IlvRendererUtil.getGraphicPropertyAsFloat(engine, mb, "x", null, -1); if (ax < bx) return -1; if (ax > bx) return 1; float ay = IlvRendererUtil.getGraphicPropertyAsFloat(engine, ma, "y", null, -1); float by = IlvRendererUtil.getGraphicPropertyAsFloat(engine, mb, "y", null, -1); if (ay < by) return -1; if (ay > by) return 1; return 0; } }; public static void main(final String[] args) { javax.swing.SwingUtilities.invokeLater(new Runnable() { Override public void run() { AccessibleDiagram app = new AccessibleDiagram(); app.init(args); } }); } public AccessibleDiagram() { super(new String[] { "-simple" }); } /** * This method is overridden to change the size of the frame. */ Override public void initFrame() { super.initFrame(); setSize(800, 400); } /** * Initializes the GUI. * * @param contentPane * The container of the application. */ Override public void init(Container contentPane) { // This sample uses JViews Diagrammer features. When deploying an // application that includes this code, you need to be in possession // of a Perforce JViews Diagrammer Deployment license. IlvProductUtil.DeploymentLicenseRequired(IlvProductUtil.JViews_Diagrammer_Deployment); bundle = ResourceBundle.getBundle("accessibledemo"); try { URL documentBase = new URL("file:./"); normalBackgroundStyleSheet = new URL(documentBase, "data/background.css"); highContrastBackgroundStyleSheet = new URL(documentBase, "data/backgroundHC.css"); varyShapesOnStyleSheet = new URL(documentBase, "data/varyshapeon.css"); varyShapesOffStyleSheet = new URL(documentBase, "data/varyshapeoff.css"); } catch (Exception ex) { ex.printStackTrace(); } super.init(contentPane); // remove the items that we don't need IlvDiagrammerMenuBar menuBar = (IlvDiagrammerMenuBar) getJMenuBar(); int idx = menuBar.getFileMenu().indexOf(IlvDiagrammerAction.printWithDialog); if (idx > 0) { try { idx--; // separator menuBar.getFileMenu().remove(idx); // the printWithDiaglog menuBar.getFileMenu().remove(idx); } catch (Exception ex) { } } // change the about dialog IlvDiagrammerMenu helpMenu = menuBar.getDiagrammerHelpMenu(); final IlvDiagrammerAction aboutAction = new IlvDiagrammerAction("Diagrammer.Action.About") { Override protected boolean isEnabled(IlvDiagrammer diagrammer) throws Exception { return true; } Override public void perform(ActionEvent e, IlvDiagrammer diagrammer) throws Exception { if (aboutDialog == null) return; aboutDialog.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE); aboutDialog.setVisible(true); } }; helpMenu.insertAction(aboutAction, 0); try { helpMenu.remove(1); } catch (Exception ex) { } // remove the properties and tree view JToolBar viewToolBar = getViewToolBar(); try { viewToolBar.remove(8); viewToolBar.remove(7); } catch (Exception ex) { } // remove the properties and tree view IlvDiagrammerMenu viewMenu = menuBar.getViewMenu(); try { viewMenu.remove(6); viewMenu.remove(5); } catch (Exception ex) { } // enhance the view menu with the high contrast mode highContrastMode = IlvSwingUtil.isHighContrastMode(); final IlvDiagrammerAction.ToggleAction hcAction = new IlvDiagrammerAction.ToggleAction( "AccessibleDiagram.HighContrast", bundle) { Override protected boolean isEnabled(IlvDiagrammer diagrammer) throws Exception { return true; } Override protected boolean isSelected(IlvDiagrammer diagrammer) throws Exception { return highContrastMode; } Override protected void setSelected(IlvDiagrammer diagrammer, boolean selected) throws Exception { if (selected) { setHighContrast(true); } else { setHighContrast(false); } } }; viewMenu.insertAction(hcAction, 0); viewMenu.insertSeparator(1); final IlvDiagrammerAction.ToggleAction vsAction = new IlvDiagrammerAction.ToggleAction( "AccessibleDiagram.VaryShapes", bundle) { Override protected boolean isEnabled(IlvDiagrammer diagrammer) throws Exception { return true; } Override protected boolean isSelected(IlvDiagrammer diagrammer) throws Exception { return varyingShapes; } Override protected void setSelected(IlvDiagrammer diagrammer, boolean selected) throws Exception { setVaryShapesCSS(selected); varyingShapes = selected; } }; viewMenu.insertAction(vsAction, 2); // submenu for the drawing mode colorModeMenu = new JMenu(getString("AccessibleDiagram.ColorMode.Name")); colorModeMenu.setOpaque(true); final JCheckBoxMenuItem[] colorModeChoices = new JCheckBoxMenuItem[3]; colorModeChoices[0] = new JCheckBoxMenuItem(getString("AccessibleDiagram.ColorMode.Normal")); colorModeChoices[1] = new JCheckBoxMenuItem(getString("AccessibleDiagram.ColorMode.Grayscale")); colorModeChoices[2] = new JCheckBoxMenuItem(getString("AccessibleDiagram.ColorMode.Deutan")); ActionListener action = new ActionListener() { Override public void actionPerformed(ActionEvent evt) { if (blockColorModeChange) return; blockColorModeChange = true; try { Object src = evt.getSource(); for (int i = 0; i < colorModeChoices.length; i++) { if (src == colorModeChoices[i]) colorMode = i; colorModeChoices[i].setSelected(false); } colorModeChoices[colorMode].setSelected(true); } finally { blockColorModeChange = false; } getCurrentDiagrammer().getView().repaint(); } }; colorModeChoices[0].setSelected(true); for (int i = 0; i < colorModeChoices.length; i++) { colorModeChoices[i].addActionListener(action); colorModeMenu.add(colorModeChoices[i]); } viewMenu.add(colorModeMenu, 3); viewMenu.insertSeparator(4); // add the status label at the right side of the menu bar menuBar.add(Box.createHorizontalGlue()); menuBar.add(statusLabel); // exchange the grapher with one that notifies the status label IlvDiagrammer diagrammer = getCurrentDiagrammer(); diagrammer.getEngine().setGrapher(new IlvGrapher() { Override protected boolean handleAccelerators(AWTEvent evt, IlvManagerView view) { if (evt instanceof KeyEvent) { KeyEvent kev = (KeyEvent) evt; if (kev.getID() == KeyEvent.KEY_PRESSED) { statusLabel.setText(getKeyEventLabel(kev)); } } return super.handleAccelerators(evt, view); } }); diagrammer.getView().setManager(diagrammer.getEngine().getGrapher()); // set the manager view to revieve TAB events IlvManagerView mgrview = diagrammer.getView(); mgrview.setFocusable(true); mgrview.setFocusCycleRoot(true); mgrview.setFocusTraversalKeysEnabled(false); mgrview.addFocusListener(new FocusListener() { Override public void focusGained(FocusEvent e) { statusLabel.setText("Key:0x----(-)---------"); } Override public void focusLost(FocusEvent e) { statusLabel.setText("No focus on view"); } }); // install the accelerators installAccelerators(diagrammer.getEngine().getGrapher()); // install the popup menu // register view view to the popup manager IlvPopupMenuManager.registerView(diagrammer.getView()); // register the menu IlvPopupMenuManager.registerMenu("MENU", popupMenu = createPopupMenu()); // allocate the about dialog aboutDialog = IlvSplash.createSplashDialog(diagrammer, null, null, null, "Perforce JViews Diagrammer Demo", "", IlvDiagrammerProduct.getVersion(), IlvDiagrammerProduct.getMinorVersion(), IlvDiagrammerProduct.getSubMinorVersion(), IlvDiagrammerProduct.getPatchLevel(), IlvDiagrammerProduct.getBuildNumber(), IlvDiagrammerProduct.getReleaseDate()); // check whether we started with high contrast node Toolkit toolkit = Toolkit.getDefaultToolkit(); Boolean highContrast = (Boolean) toolkit.getDesktopProperty("win.highContrast.on"); if (highContrast != null && highContrast.booleanValue()) { setHighContrast(true); } } /** * Loads the first diagram. */ Override protected void ready() { super.ready(); loadDiagram(); // fit to the initial part IlvSDMView view = getCurrentDiagrammer().getView(); view.fitTransformerToArea(null, new IlvManagerView.FitAreaCalculator() { Override public IlvRect getAreaToFit(IlvManagerView view) { return new IlvRect(-420, 100, 200, 200); } }, 1, true); } /** * Loads a diagram. * * @param project * The diagram project to load. */ private void loadDiagram() { try { URL documentBase = new URL("file:./"); URL url = new URL(documentBase, "data/accsample.idpr"); IlvDiagrammerProject project = new IlvDiagrammerProject(url); getCurrentDiagrammer().setProject(project); // add the style sheet for baclground backgroundStyleSheet = normalBackgroundStyleSheet; varyShapesStyleSheet = varyShapesOffStyleSheet; getCurrentDiagrammer().addStyleSheet(backgroundStyleSheet); getCurrentDiagrammer().addStyleSheet(varyShapesStyleSheet); } catch (Exception e1) { e1.printStackTrace(); } setHighContrastCSS(getCurrentDiagrammer(), highContrastMode); setVaryShapesCSS(varyingShapes); } /** * Sets the high contrast code. */ private void setHighContrast(boolean on) { if (on == highContrastMode) return; highContrastMode = on; setHighContrastCSS(getCurrentDiagrammer(), on); Container c = getCurrentDiagrammer(); while (c.getParent() != null) c = c.getParent(); setHighContrast(c, on); if (popupMenu != null) { setHighContrast(popupMenu, on); } if (aboutDialog != null) { setHighContrast(aboutDialog, on); } setHighContrast(getOverview(), on); } /** * Sets high contrast on a hierarchy of Swing components. This is usually not * needed, if the high contrast mode was set at the operating level already * when starting this demo. We do this code in this demo only to illustrate * and to be able to switch the high contrast mode dynamically on the fly. */ void setHighContrast(Container c, boolean on) { c.setForeground(on ? lightColor : darkColor); c.setBackground(on ? darkColor : lightColor); adaptFont(c, on); if (c instanceof JMenu) { Component[] cs = ((JMenu) c).getMenuComponents(); if (cs == null) return; for (int i = 0; i < cs.length; i++) { if (cs[i] instanceof Container) setHighContrast((Container) cs[i], on); } } else { Component[] cs = c.getComponents(); if (cs == null) return; for (int i = 0; i < cs.length; i++) { if (cs[i] instanceof Container) setHighContrast((Container) cs[i], on); } } } /** * Adapt the font to high contrast on a component. */ void adaptFont(Component c, boolean highContrast) { if (c.isFontSet()) { Font oldFont = c.getFont(); Font newFont = getAdapted(oldFont, c, highContrast); c.setFont(newFont); } } /** * Returns the high or low contrast font. */ Font getAdapted(Font oldFont, Object key, boolean highContrast) { Font newFont = null; if (highContrast) { if (normalContrastFonts.get(key) == null) normalContrastFonts.put(key, oldFont); newFont = (Font) highContrastFonts.get(key); if (newFont == null) { newFont = new Font(oldFont.getName(), oldFont.getStyle(), (int) (oldFont.getSize() * 1.2)); highContrastFonts.put(key, newFont); } } else { if (highContrastFonts.get(key) == null) highContrastFonts.put(key, oldFont); newFont = (Font) normalContrastFonts.get(key); if (newFont == null) { newFont = new Font(oldFont.getName(), oldFont.getStyle(), (int) (oldFont.getSize() / 1.2)); normalContrastFonts.put(key, newFont); } } return newFont; } /** * Sets the CSS for high contrast. */ private void setHighContrastCSS(IlvDiagrammer diagrammer, boolean on) { String theme = on ? IlvSDMEngine.HIGH_CONTRAST : IlvSDMEngine.NORMAL_CONTRAST; diagrammer.getEngine().setContrastAccessibilityTheme(theme); try { diagrammer.removeStyleSheet(backgroundStyleSheet); backgroundStyleSheet = on ? highContrastBackgroundStyleSheet : normalBackgroundStyleSheet; diagrammer.addStyleSheet(backgroundStyleSheet); } catch (Exception ex) { ex.printStackTrace(); } } /** * Sets the CSS for varying shapes. */ private void setVaryShapesCSS(boolean on) { IlvDiagrammer diagrammer = getCurrentDiagrammer(); try { diagrammer.removeStyleSheet(varyShapesStyleSheet); varyShapesStyleSheet = on ? varyShapesOnStyleSheet : varyShapesOffStyleSheet; diagrammer.addStyleSheet(varyShapesStyleSheet); } catch (Exception ex) { ex.printStackTrace(); } } /** * Install all accelerators. */ private void installAccelerators(IlvGrapher grapher) { // F1 -> popup menu // P -> popup menu // TAB -> select forward // Shift TAB -> select backward // F -> select forward // B -> select backward // A -> select all // Ctrl A -> deselect all // Ctrl 0 -> Identity zoom // Ctrl F -> Fit zoom // Ctrl - -> Zoom out // Ctrl + -> Zoom in // Ctrl R -> Rotate view // Arrow up -> Scroll up // Arrow down -> Scroll down // Arrow left -> Scroll left // Arrow right -> Scroll right // Shift Arrow up -> Move selection up // Shift Arrow down -> Move selection down // Shift Arrow left -> Move selection left // Shift Arrow right -> Move selection right // Delete key -> Delete selection // E -> Expand selection IlvPopupMenuAccelerator popupAcc; IlvCycleSelectAccelerator selAcc; IlvMoveSelectionAccelerator movAcc; IlvSelectAllAccelerator selAllAcc; IlvAccelerator acc; // just for shorter writing int keypress = KeyEvent.KEY_PRESSED; // int keyrelease = KeyEvent.KEY_RELEASED; int shift = KeyEvent.SHIFT_DOWN_MASK; int ctrl = KeyEvent.CTRL_DOWN_MASK; // int ctsht = KeyEvent.CTRL_MASK | KeyEvent.SHIFT_MASK; char unspecCode = KeyEvent.VK_UNDEFINED; // popup menu popupAcc = new IlvPopupMenuAccelerator(keypress, KeyEvent.VK_F1, 0, true); grapher.addAccelerator(popupAcc); popupAcc = new IlvPopupMenuAccelerator(keypress, unspecCode, 'p', 0, true); grapher.addAccelerator(popupAcc); popupAcc = new IlvPopupMenuAccelerator(keypress, unspecCode, 'P', shift, true); grapher.addAccelerator(popupAcc); // select all selAllAcc = new IlvSelectAllAccelerator(keypress, unspecCode, 'a', 0, true); selAllAcc.setTraverse(true); grapher.addAccelerator(selAllAcc); selAllAcc = new IlvSelectAllAccelerator(keypress, unspecCode, 'A', shift, true); selAllAcc.setTraverse(true); grapher.addAccelerator(selAllAcc); selAllAcc = new IlvSelectAllAccelerator(keypress, KeyEvent.VK_A, ctrl, true); selAllAcc.setTraverse(true); selAllAcc.setSelectAll(false); grapher.addAccelerator(selAllAcc); // select selAcc = new IlvCycleSelectAccelerator(keypress, KeyEvent.VK_TAB, 0, true); selAcc.setForward(true); selAcc.setComparator(nestedThenXThenY); grapher.addAccelerator(selAcc); selAcc = new IlvCycleSelectAccelerator(keypress, unspecCode, 'f', 0, true); selAcc.setForward(true); selAcc.setComparator(nestedThenXThenY); grapher.addAccelerator(selAcc); selAcc = new IlvCycleSelectAccelerator(keypress, unspecCode, 'F', shift, true); selAcc.setForward(true); selAcc.setComparator(nestedThenXThenY); grapher.addAccelerator(selAcc); selAcc = new IlvCycleSelectAccelerator(keypress, KeyEvent.VK_TAB, shift, true); selAcc.setForward(false); selAcc.setComparator(nestedThenXThenY); grapher.addAccelerator(selAcc); selAcc = new IlvCycleSelectAccelerator(keypress, unspecCode, 'b', 0, true); selAcc.setForward(false); selAcc.setComparator(nestedThenXThenY); grapher.addAccelerator(selAcc); selAcc = new IlvCycleSelectAccelerator(keypress, unspecCode, 'B', shift, true); selAcc.setForward(false); selAcc.setComparator(nestedThenXThenY); grapher.addAccelerator(selAcc); acc = new IlvDeleteSelectionAccelerator(keypress, KeyEvent.VK_DELETE, 0, true) { Override protected boolean handleEvent(IlvManagerView v) { // super.handleEvents deals only with the graphic objects, but // we also need to delete the model objects if (v instanceof IlvSDMView) { IlvSDMEngine engine = ((IlvSDMView) v).getSDMEngine(); // delete the selected objects engine.delete(); } // in case there are graphics that don't correspond to model objects return super.handleEvent(v); } }; grapher.addAccelerator(acc); acc = new IlvIdentityAccelerator(keypress, KeyEvent.VK_HOME, ctrl, true); grapher.addAccelerator(acc); acc = new IlvIdentityAccelerator(keypress, '0', ctrl, true); grapher.addAccelerator(acc); acc = new IlvIdentityAccelerator(keypress, KeyEvent.VK_NUMPAD0, ctrl, true); grapher.addAccelerator(acc); acc = new IlvIdentityAccelerator(keypress, KeyEvent.VK_INSERT, ctrl, true); grapher.addAccelerator(acc); acc = new IlvZoomOutAccelerator(keypress, KeyEvent.VK_SUBTRACT, ctrl, true); grapher.addAccelerator(acc); acc = new IlvZoomOutAccelerator(keypress, unspecCode, '-', ctrl, true); grapher.addAccelerator(acc); acc = new IlvZoomInAccelerator(keypress, KeyEvent.VK_ADD, ctrl, true); grapher.addAccelerator(acc); acc = new IlvZoomInAccelerator(keypress, unspecCode, '+', ctrl, true); grapher.addAccelerator(acc); acc = new IlvFitToSizeAccelerator(keypress, KeyEvent.VK_NUMPAD5, ctrl, true); grapher.addAccelerator(acc); acc = new IlvFitToSizeAccelerator(keypress, KeyEvent.VK_BEGIN, ctrl, true); grapher.addAccelerator(acc); acc = new IlvFitToSizeAccelerator(keypress, KeyEvent.VK_F, ctrl, true); grapher.addAccelerator(acc); acc = new IlvRotateAccelerator(keypress, KeyEvent.VK_R, ctrl, true); grapher.addAccelerator(acc); // scroll with normal arrows acc = new IlvScrollUpAccelerator(keypress, KeyEvent.VK_UP, 0, true); grapher.addAccelerator(acc); acc = new IlvScrollDownAccelerator(keypress, KeyEvent.VK_DOWN, 0, true); grapher.addAccelerator(acc); acc = new IlvScrollRightAccelerator(keypress, KeyEvent.VK_RIGHT, 0, true); grapher.addAccelerator(acc); acc = new IlvScrollLeftAccelerator(keypress, KeyEvent.VK_LEFT, 0, true); grapher.addAccelerator(acc); // scroll with numpad acc = new IlvScrollUpAccelerator(keypress, KeyEvent.VK_NUMPAD8, ctrl, true); grapher.addAccelerator(acc); acc = new IlvScrollDownAccelerator(keypress, KeyEvent.VK_NUMPAD2, ctrl, true); grapher.addAccelerator(acc); acc = new IlvScrollLeftAccelerator(keypress, KeyEvent.VK_NUMPAD4, ctrl, true); grapher.addAccelerator(acc); acc = new IlvScrollRightAccelerator(keypress, KeyEvent.VK_NUMPAD6, ctrl, true); grapher.addAccelerator(acc); // scroll with arrows on numpad acc = new IlvScrollUpAccelerator(keypress, KeyEvent.VK_KP_UP, ctrl, true); grapher.addAccelerator(acc); acc = new IlvScrollDownAccelerator(keypress, KeyEvent.VK_KP_DOWN, ctrl, true); grapher.addAccelerator(acc); acc = new IlvScrollLeftAccelerator(keypress, KeyEvent.VK_KP_LEFT, ctrl, true); grapher.addAccelerator(acc); acc = new IlvScrollRightAccelerator(keypress, KeyEvent.VK_KP_RIGHT, ctrl, true); grapher.addAccelerator(acc); // move with normal arrows movAcc = new IlvMoveSelectionAccelerator(keypress, KeyEvent.VK_UP, shift, true); movAcc.setMoveVector(0, -10); grapher.addAccelerator(movAcc); movAcc = new IlvMoveSelectionAccelerator(keypress, KeyEvent.VK_DOWN, shift, true); movAcc.setMoveVector(0, 10); grapher.addAccelerator(movAcc); movAcc = new IlvMoveSelectionAccelerator(keypress, KeyEvent.VK_LEFT, shift, true); movAcc.setMoveVector(-10, 0); grapher.addAccelerator(movAcc); movAcc = new IlvMoveSelectionAccelerator(keypress, KeyEvent.VK_RIGHT, shift, true); movAcc.setMoveVector(10, 0); grapher.addAccelerator(movAcc); // move with numpad movAcc = new IlvMoveSelectionAccelerator(keypress, KeyEvent.VK_NUMPAD8, shift, true); movAcc.setMoveVector(0, -5); grapher.addAccelerator(movAcc); movAcc = new IlvMoveSelectionAccelerator(keypress, KeyEvent.VK_NUMPAD2, shift, true); movAcc.setMoveVector(0, 5); grapher.addAccelerator(movAcc); movAcc = new IlvMoveSelectionAccelerator(keypress, KeyEvent.VK_NUMPAD4, shift, true); movAcc.setMoveVector(-5, 0); grapher.addAccelerator(movAcc); movAcc = new IlvMoveSelectionAccelerator(keypress, KeyEvent.VK_NUMPAD6, shift, true); movAcc.setMoveVector(5, 0); grapher.addAccelerator(movAcc); // move with arrows on numpad movAcc = new IlvMoveSelectionAccelerator(keypress, KeyEvent.VK_KP_UP, shift, true); movAcc.setMoveVector(0, -3); grapher.addAccelerator(movAcc); movAcc = new IlvMoveSelectionAccelerator(keypress, KeyEvent.VK_KP_DOWN, shift, true); movAcc.setMoveVector(0, 3); grapher.addAccelerator(movAcc); movAcc = new IlvMoveSelectionAccelerator(keypress, KeyEvent.VK_KP_LEFT, shift, true); movAcc.setMoveVector(-3, 0); grapher.addAccelerator(movAcc); movAcc = new IlvMoveSelectionAccelerator(keypress, KeyEvent.VK_KP_RIGHT, shift, true); movAcc.setMoveVector(3, 0); grapher.addAccelerator(movAcc); // expand selection acc = new IlvExpandSelectionAccelerator(keypress, KeyEvent.VK_E, 0, true); grapher.addAccelerator(acc); acc = new IlvExpandSelectionAccelerator(keypress, KeyEvent.VK_E, shift, true); grapher.addAccelerator(acc); } /** * Returns the indicator of a key event. */ private String getKeyEventLabel(KeyEvent ev) { String digits = "0123456789ABCDEF"; StringBuffer buf = new StringBuffer("Key:0x"); int code = ev.getKeyCode(); code = code & 0xffff; int d = code / 4096; buf.append(digits.charAt(d)); code -= d * 4096; d = code / 256; buf.append(digits.charAt(d)); code -= d * 256; d = code / 16; buf.append(digits.charAt(d)); code -= d * 16; buf.append(digits.charAt(code)); buf.append('('); if (ev.getKeyChar() == KeyEvent.CHAR_UNDEFINED) { // nothing } else if (Character.isISOControl(ev.getKeyChar())) { code = (int) ev.getKeyChar(); code = code & 0xff; d = code / 16; buf.append(digits.charAt(d)); code -= d * 16; buf.append(digits.charAt(code)); } else { buf.append(ev.getKeyChar()); } buf.append(')'); int mod = ev.getModifiersEx(); boolean shift = ((mod & InputEvent.SHIFT_DOWN_MASK) != 0); boolean ctrl = ((mod & InputEvent.CTRL_DOWN_MASK) != 0); boolean alt = ((mod & InputEvent.ALT_DOWN_MASK) != 0); boolean meta = ((mod & InputEvent.META_DOWN_MASK) != 0); boolean altgr = ((mod & InputEvent.ALT_GRAPH_DOWN_MASK) != 0); int count = 0; if (shift) count++; if (ctrl) count++; if (alt) count++; if (meta) count++; if (altgr) count++; if (shift) { if (count > 4) buf.append("S"); else if (count >= 3) buf.append("Sh"); else if (count == 2) buf.append("Shft"); else buf.append("Shift"); } if (ctrl) { if (count > 4) buf.append("C"); else if (count >= 3) buf.append("Ct"); else if (count == 2) buf.append("Ctrl"); else buf.append("Control"); } if (alt) { if (count > 4) buf.append("A"); else if (count >= 3) buf.append("Al"); else buf.append("Alt"); } if (meta) { if (count > 4) buf.append("M"); else if (count >= 3) buf.append("Me"); else buf.append("Meta"); } if (altgr) { if (count > 4) buf.append("a"); else if (count >= 3) buf.append("Ag"); else if (count == 2) buf.append("Algr"); else buf.append("Altgraph"); } if (ev.isConsumed()) buf.append("*"); else buf.append(" "); return buf.toString(); } /** * Creates the popup menu. */ private JPopupMenu createPopupMenu() { // create the action listener for the popup menu ActionListener actionListener = new ActionListener() { Override public void actionPerformed(ActionEvent e) { // retrieve the selected menu item JMenuItem m = (JMenuItem) e.getSource(); // retrieve the graphic that has this popup menu IlvPopupMenuContext context = IlvPopupMenuManager.getPopupMenuContext(m); IlvGraphic graphic = context.getGraphic(); // do the action if (m.getText().equals("Shift left")) { IlvRect bbox = graphic.boundingBox(); bbox.x -= 20; IlvManager manager = (IlvManager) graphic.getGraphicBag(); // this will also notify the model manager.moveObject(graphic, bbox.x, bbox.y, true); } else if (m.getText().equals("Shift right")) { IlvRect bbox = graphic.boundingBox(); bbox.x += 20; IlvManager manager = (IlvManager) graphic.getGraphicBag(); // this will also notify the model manager.moveObject(graphic, bbox.x, bbox.y, true); } } }; // create a simple popup menu with the following items // - Make larger: makes the graphic larger // - Make smaller: makes the graphic smaller IlvSimplePopupMenu menu = new IlvSimplePopupMenu("Menu1", "Shift left | Shift right", null, actionListener); return menu; } /** * Creates a new diagrammer. */ Override protected IlvDiagrammer createDiagrammer() { IlvSDMView view = new IlvSDMView() { Override protected Image createDoubleBufferImage(int width, int height) { return new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); } Override protected void doubleBufferedImageUpToDate(Image doubleBufferImage) { super.doubleBufferedImageUpToDate(doubleBufferImage); adaptBuffer(doubleBufferImage); } }; // enable double buffering to allow the colorMode GRAYSCALE... view.setDoubleBuffering(true); // keep aspect ratio view.setKeepingAspectRatio(true); return new IlvDiagrammer(view); } /** * Adapts the double buffer to the color mode. */ private void adaptBuffer(Image image) { if (colorMode == GRAYSCALE) { BufferedImage buffer = (BufferedImage) image; WritableRaster raster = buffer.copyData(null); int mx = raster.getMinX(); int my = raster.getMinY(); int w = raster.getWidth(); int h = raster.getHeight(); int[] data = null; for (int x = mx; x < mx + w; x++) { for (int y = my; y < my + h; y++) { data = raster.getPixel(x, y, data); if (data[0] == data[1] && data[1] == data[2]) continue; int g = (int) (0.299 * data[0] + 0.587 * data[1] + 0.114 * data[2]); if (g < 0) g = 0; if (g > 255) g = 255; data[0] = data[1] = data[2] = g; raster.setPixel(x, y, data); } } buffer.setData(raster); } else if (colorMode == DEUTAN) { // There are many variants of red green blind. This is just one of them. BufferedImage buffer = (BufferedImage) image; WritableRaster raster = buffer.copyData(null); int mx = raster.getMinX(); int my = raster.getMinY(); int w = raster.getWidth(); int h = raster.getHeight(); int[] data = null; for (int x = mx; x < mx + w; x++) { for (int y = my; y < my + h; y++) { data = raster.getPixel(x, y, data); if (data[0] == data[1]) continue; int g = (int) (0.337 * data[0] + 0.663 * data[1]); if (g < 0) g = 0; if (g > 255) g = 255; data[0] = data[1] = g; raster.setPixel(x, y, data); } } buffer.setData(raster); } } /** * Returns a string from the resource bundle. */ private String getString(String key) { try { return bundle.getString(key); } catch (Exception ex) { return key; } } }