Mega Code Archive

 
Categories / Java / Swing JFC
 

Accessible Scroll Demo

/* From http://java.sun.com/docs/books/tutorial/index.html */ /*  * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.  *  * Redistribution and use in source and binary forms, with or without  * modification, are permitted provided that the following conditions are met:  *  * -Redistribution of source code must retain the above copyright notice, this  *  list of conditions and the following disclaimer.  *  * -Redistribution in binary form must reproduce the above copyright notice,  *  this list of conditions and the following disclaimer in the documentation  *  and/or other materials provided with the distribution.  *  * Neither the name of Sun Microsystems, Inc. or the names of contributors may  * be used to endorse or promote products derived from this software without  * specific prior written permission.  *  * This software is provided "AS IS," without a warranty of any kind. ALL  * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING  * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE  * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")  * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE  * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS  * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST  * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,  * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY  * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,  * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.  *  * You acknowledge that this software is not designed, licensed or intended  * for use in the design, construction, operation or maintenance of any  * nuclear facility.  */ import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.Insets; import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.Locale; import javax.accessibility.Accessible; import javax.accessibility.AccessibleContext; import javax.accessibility.AccessibleRole; import javax.accessibility.AccessibleState; import javax.accessibility.AccessibleStateSet; import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JToggleButton; import javax.swing.Scrollable; import javax.swing.SwingConstants; public class AccessibleScrollDemo extends JPanel {   private Rule columnView;   private Rule rowView;   private JToggleButton isMetric;   private ScrollablePicture picture;   public AccessibleScrollDemo() {     //Load the photograph into an image icon.     ImageIcon david = new ImageIcon("images/youngdad.jpeg");     david.setDescription("Photograph of David McNabb in his youth.");     //Create the row and column headers     columnView = new Rule(Rule.HORIZONTAL, true);     columnView.setPreferredWidth(david.getIconWidth());     columnView.getAccessibleContext().setAccessibleName("Column Header");     columnView.getAccessibleContext().setAccessibleDescription(         "Displays horizontal ruler for "             + "measuring scroll pane client.");     rowView = new Rule(Rule.VERTICAL, true);     rowView.setPreferredHeight(david.getIconHeight());     rowView.getAccessibleContext().setAccessibleName("Row Header");     rowView.getAccessibleContext().setAccessibleDescription(         "Displays vertical ruler for "             + "measuring scroll pane client.");     //Create the corners     JPanel buttonCorner = new JPanel();     isMetric = new JToggleButton("cm", true);     isMetric.setFont(new Font("SansSerif", Font.PLAIN, 11));     isMetric.setMargin(new Insets(2, 2, 2, 2));     isMetric.addItemListener(new UnitsListener());     isMetric.setToolTipText("Toggles rulers' unit of measure "         + "between inches and centimeters.");     buttonCorner.add(isMetric); //Use the default FlowLayout     buttonCorner.getAccessibleContext().setAccessibleName(         "Upper Left Corner");     String desc = "Fills the corner of a scroll pane "         + "with color for aesthetic reasons.";     Corner lowerLeft = new Corner();     lowerLeft.getAccessibleContext().setAccessibleName("Lower Left Corner");     lowerLeft.getAccessibleContext().setAccessibleDescription(desc);     Corner upperRight = new Corner();     upperRight.getAccessibleContext().setAccessibleName(         "Upper Right Corner");     upperRight.getAccessibleContext().setAccessibleDescription(desc);     //Set up the scroll pane     picture = new ScrollablePicture(david, columnView.getIncrement());     picture.setToolTipText(david.getDescription());     picture.getAccessibleContext().setAccessibleName("Scroll pane client");     JScrollPane pictureScrollPane = new JScrollPane(picture);     pictureScrollPane.setPreferredSize(new Dimension(300, 250));     pictureScrollPane.setViewportBorder(BorderFactory         .createLineBorder(Color.black));     pictureScrollPane.setColumnHeaderView(columnView);     pictureScrollPane.setRowHeaderView(rowView);     pictureScrollPane         .setCorner(JScrollPane.UPPER_LEFT_CORNER, buttonCorner);     pictureScrollPane.setCorner(JScrollPane.LOWER_LEFT_CORNER, lowerLeft);     pictureScrollPane.setCorner(JScrollPane.UPPER_RIGHT_CORNER, upperRight);     //Put it in this panel     setLayout(new BoxLayout(this, BoxLayout.X_AXIS));     add(pictureScrollPane);     setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));   }   class UnitsListener implements ItemListener {     public void itemStateChanged(ItemEvent e) {       if (e.getStateChange() == ItemEvent.SELECTED) {         //turn it to metric         rowView.setIsMetric(true);         columnView.setIsMetric(true);       } else {         //turn it to inches         rowView.setIsMetric(false);         columnView.setIsMetric(false);       }       picture.setMaxUnitIncrement(rowView.getIncrement());     }   }   public static void main(String s[]) {     JFrame frame = new JFrame("AccessibleScrollDemo");     frame.addWindowListener(new WindowAdapter() {       public void windowClosing(WindowEvent e) {         System.exit(0);       }     });     frame.setContentPane(new AccessibleScrollDemo());     frame.pack();     frame.setVisible(true);   } } class Rule extends JComponent implements Accessible {   public static final int INCH = Toolkit.getDefaultToolkit()       .getScreenResolution();   public static final int HORIZONTAL = 0;   public static final int VERTICAL = 1;   public static final int SIZE = 35;   public int orientation;   public boolean isMetric;   private int increment;   private int units;   public Rule(int o, boolean m) {     orientation = o;     isMetric = m;     setIncrementAndUnits();   }   public void setIsMetric(boolean isMetric) {     if (accessibleContext != null && this.isMetric != isMetric) {       if (isMetric) {         accessibleContext.firePropertyChange(             AccessibleContext.ACCESSIBLE_STATE_PROPERTY,             AccessibleRulerState.INCHES,             AccessibleRulerState.CENTIMETERS);       } else {         accessibleContext.firePropertyChange(             AccessibleContext.ACCESSIBLE_STATE_PROPERTY,             AccessibleRulerState.CENTIMETERS,             AccessibleRulerState.INCHES);       }     }     this.isMetric = isMetric;     setIncrementAndUnits();     repaint();   }   private void setIncrementAndUnits() {     if (isMetric) {       units = (int) ((double) INCH / (double) 2.54); // dots per       // centimeter       increment = units;     } else {       units = INCH;       increment = units / 2;     }   }   public boolean isMetric() {     return this.isMetric;   }   public int getIncrement() {     return increment;   }   public void setPreferredHeight(int ph) {     setPreferredSize(new Dimension(SIZE, ph));   }   public void setPreferredWidth(int pw) {     setPreferredSize(new Dimension(pw, SIZE));   }   public void paintComponent(Graphics g) {     Rectangle drawHere = g.getClipBounds();     // Fill clipping area with dirty brown/orange.     g.setColor(new Color(230, 163, 4));     g.fillRect(drawHere.x, drawHere.y, drawHere.width, drawHere.height);     // Do the ruler labels in a small font that's black.     g.setFont(new Font("SansSerif", Font.PLAIN, 10));     g.setColor(Color.black);     // Some vars we need.     int end = 0;     int start = 0;     int tickLength = 0;     String text = null;     // Use clipping bounds to calculate first tick     // and last tick location.     if (orientation == HORIZONTAL) {       start = (drawHere.x / increment) * increment;       end = (((drawHere.x + drawHere.width) / increment) + 1) * increment;     } else {       start = (drawHere.y / increment) * increment;       end = (((drawHere.y + drawHere.height) / increment) + 1)           * increment;     }     // Make a special case of 0 to display the number     // within the rule and draw a units label.     if (start == 0) {       text = Integer.toString(0) + (isMetric ? " cm" : " in");       tickLength = 10;       if (orientation == HORIZONTAL) {         g.drawLine(0, SIZE - 1, 0, SIZE - tickLength - 1);         g.drawString(text, 2, 21);       } else {         g.drawLine(SIZE - 1, 0, SIZE - tickLength - 1, 0);         g.drawString(text, 9, 10);       }       text = null;       start = increment;     }     // ticks and labels     for (int i = start; i < end; i += increment) {       if (i % units == 0) {         tickLength = 10;         text = Integer.toString(i / units);       } else {         tickLength = 7;         text = null;       }       if (tickLength != 0) {         if (orientation == HORIZONTAL) {           g.drawLine(i, SIZE - 1, i, SIZE - tickLength - 1);           if (text != null)             g.drawString(text, i - 3, 21);         } else {           g.drawLine(SIZE - 1, i, SIZE - tickLength - 1, i);           if (text != null)             g.drawString(text, 9, i + 3);         }       }     }   }   public AccessibleContext getAccessibleContext() {     if (accessibleContext == null) {       accessibleContext = new AccessibleRuler();     }     return accessibleContext;   }   protected class AccessibleRuler extends AccessibleJComponent {     public AccessibleRole getAccessibleRole() {       return AccessibleRuleRole.RULER;     }     public AccessibleStateSet getAccessibleStateSet() {       AccessibleStateSet states = super.getAccessibleStateSet();       if (orientation == VERTICAL) {         states.add(AccessibleState.VERTICAL);       } else {         states.add(AccessibleState.HORIZONTAL);       }       if (isMetric) {         states.add(AccessibleRulerState.CENTIMETERS);       } else {         states.add(AccessibleRulerState.INCHES);       }       return states;     }   } } class AccessibleRuleRole extends AccessibleRole {   public static final AccessibleRuleRole RULER = new AccessibleRuleRole(       "ruler");   protected AccessibleRuleRole(String key) {     super(key);   }   //Should really provide localizable versions of these names.   public String toDisplayString(String resourceBundleName, Locale locale) {     return key;   } } class AccessibleRulerState extends AccessibleState {   public static final AccessibleRulerState INCHES = new AccessibleRulerState(       "inches");   public static final AccessibleRulerState CENTIMETERS = new AccessibleRulerState(       "centimeters");   protected AccessibleRulerState(String key) {     super(key);   }   //Should really provide localizable versions of these names.   public String toDisplayString(String resourceBundleName, Locale locale) {     return key;   } } class ScrollablePicture extends JLabel implements Scrollable {   private int maxUnitIncrement = 1;   public ScrollablePicture(ImageIcon i, int m) {     super(i);     maxUnitIncrement = m;   }   public Dimension getPreferredScrollableViewportSize() {     return getPreferredSize();   }   public int getScrollableUnitIncrement(Rectangle visibleRect,       int orientation, int direction) {     int currentPosition = 0;     if (orientation == SwingConstants.HORIZONTAL)       currentPosition = visibleRect.x;     else       currentPosition = visibleRect.y;     if (direction < 0) {       int newPosition = currentPosition           - (currentPosition / maxUnitIncrement) * maxUnitIncrement;       return (newPosition == 0) ? maxUnitIncrement : newPosition;     } else {       return ((currentPosition / maxUnitIncrement) + 1)           * maxUnitIncrement - currentPosition;     }   }   public int getScrollableBlockIncrement(Rectangle visibleRect,       int orientation, int direction) {     if (orientation == SwingConstants.HORIZONTAL)       return visibleRect.width - maxUnitIncrement;     else       return visibleRect.height - maxUnitIncrement;   }   public boolean getScrollableTracksViewportWidth() {     return false;   }   public boolean getScrollableTracksViewportHeight() {     return false;   }   public void setMaxUnitIncrement(int pixels) {     maxUnitIncrement = pixels;   } } class Corner extends JComponent implements Accessible {   public void paintComponent(Graphics g) {     // Fill me with dirty brown/orange.     g.setColor(new Color(230, 163, 4));     g.fillRect(0, 0, getWidth(), getHeight());   }   public AccessibleContext getAccessibleContext() {     if (accessibleContext == null) {       accessibleContext = new AccessibleCorner();     }     return accessibleContext;   }   protected class AccessibleCorner extends AccessibleJComponent {     //Inherit everything, override nothing.   } }