Change AutoScroll Bounds in JTextPane

I cannot figure this out for the life of me. I would like to CHANGE the bounds for the autoscroll on a JTextPane that resides inside a JScrollPane when the user selects text and moves the mouse outside of the "autoscroll bounds".
The normal bounds for scrolling down a JTextPane (when inside a JScrollPane) are usually the bounds of the JTextPane itself. (You can verify this with my example by selecting some text with the mouse button held down, and moving your cursor outside the bottom of the window). I would like to move the bottom bounds up higher into the window (indicated by the black line that resides on the glasspane).
I have provided this example to use as a starting point. It doesn't do anything of use right now. I have tried about 20 things, but things have gotten so messed up, and the level of internal code that I started to mess around with got way over my head... so I'm just going to post this with a clean start, and hopefully we can move in a positive direction. I will relay my findings about a paticular route if we start moving down one i've already failed at.
Thanks for you time.
-Js
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.StyledDocument;
public class AutoScrollTest extends JFrame
     //DATA
     private static final int Y_SCROLL_THRESHOLD = 150;
     //GUI
     private JPanel glassPanel;
     private JScrollPane scrollPane;
          private JTextPane textPane;
     public AutoScrollTest()
          this.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
          this.setGlassPane(getGlassPanel());
          this.setContentPane(getScrollPane());
          getGlassPanel().setVisible(true);
          this.pack();
          this.setVisible(true);
     private JPanel getGlassPanel()
          if(glassPanel == null)
               glassPanel = new JPanel()
                    public void paintComponent(Graphics g)
                         super.paintComponent(g);
                         g.setColor(Color.BLACK);
                         g.drawLine(0, Y_SCROLL_THRESHOLD, 300, Y_SCROLL_THRESHOLD);
               glassPanel.setOpaque(false);
          return glassPanel;
     private JScrollPane getScrollPane()
          if(scrollPane == null)
               scrollPane = new JScrollPane(getTextPane());
               scrollPane.setPreferredSize(new Dimension(300,300));
          return scrollPane;
     private JTextPane getTextPane()
          if(textPane == null)
               textPane = new JTextPane();
               try
                    StyledDocument sd = textPane.getStyledDocument();
                    for(int i=1; i<1000; i++)
                         sd.insertString(sd.getLength(),"This is line: " + i + "\n", null);
               catch(BadLocationException ble)
                    ble.printStackTrace();
          return textPane;
     public static void main(String args[])
          new AutoScrollTest();
}

camickr & StanislavL:
Great work guys. I have used both of your ideas... and it works GREAT! I'll split the dukes between you.
Please take a look at the finished code, its very cool. Again, thanks.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
public class AutoScrollTest extends JFrame
     //DATA
     private static final int Y_SCROLL_THRESHOLD = 150;
     private Timer scrollTimer;
     //GUI
     private JPanel glassPanel;
     private JScrollPane scrollPane;
          private JTextPane textPane;
     public AutoScrollTest()
          this.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
          this.setGlassPane(getGlassPanel());
          this.setContentPane(getScrollPane());
          getGlassPanel().setVisible(true);
          this.pack();
          this.setVisible(true);
     private JPanel getGlassPanel()
          if(glassPanel == null)
               glassPanel = new JPanel()
                    public void paintComponent(Graphics g)
                         super.paintComponent(g);
                         g.setColor(Color.BLACK);
                         g.drawLine(0, Y_SCROLL_THRESHOLD, 300, Y_SCROLL_THRESHOLD);
               glassPanel.setOpaque(false);
          return glassPanel;
     private JScrollPane getScrollPane()
          if(scrollPane == null)
               scrollPane = new JScrollPane(getTextPane());
               scrollPane.setPreferredSize(new Dimension(300,300));
          return scrollPane;
     private JTextPane getTextPane()
          if(textPane == null)
               textPane = new JTextPane();
               MouseInputAdapter mia = new MouseInputAdapter()
                    public void mouseDragged(MouseEvent e)
                         Point viewPortPoint = getScrollPane().getViewport().getViewPosition();
                         if(e.getY()-viewPortPoint.getY() > Y_SCROLL_THRESHOLD)
                              getScrollTimer().start();
                         else
                              getScrollTimer().stop();
                    public void mouseReleased(MouseEvent e)
                         getScrollTimer().stop();
               textPane.addMouseListener(mia);
               textPane.addMouseMotionListener(mia);
               try
                    StyledDocument sd = textPane.getStyledDocument();
                    for(int i=1; i<1000; i++)
                         sd.insertString(sd.getLength(),"This is line: " + i + "\n", null);
               catch(BadLocationException ble)
                    ble.printStackTrace();
          return textPane;
     private Timer getScrollTimer()
          if(scrollTimer == null)
               scrollTimer = new Timer(60,new MyScrollListener(getTextPane(),getScrollPane().getVerticalScrollBar()));
          return scrollTimer;
     public static void main(String args[])
          new AutoScrollTest();
class MyScrollListener implements ActionListener
     private JTextPane textPane;
     private JScrollBar scrollBar;
     public MyScrollListener(JTextPane textPane, JScrollBar scrollBar)
          this.scrollBar = scrollBar;
          this.textPane = textPane;
     public void actionPerformed(ActionEvent e)
          //Move down the scrollbar
          scrollBar.setValue(scrollBar.getValue()+scrollBar.getBlockIncrement());
          //Update the mouse highlight
          PointerInfo mousePointerInfo = MouseInfo.getPointerInfo();
          Point convertedPoint = SwingUtilities.convertPoint(null,mousePointerInfo.getLocation(),textPane);
          Position.Bias[] bias = new Position.Bias[1];
          int mouseOffset = textPane.getUI().viewToModel(textPane,convertedPoint, bias);
          if (bias[0] == Position.Bias.Backward && mouseOffset != 0)
               --mouseOffset;
          textPane.setSelectionEnd(mouseOffset);
}

Similar Messages

  • Can we change the bound location of an operator using OMB?

    Hi,
    I'm trying to change the location of an table operator using the following code:
    OMBALTER MAPPING 'MAP_NAME' MODIFY OPERATOR 'TABLE_TEST' SET PROPERTIES (database_link) VALUES ('PROJECT1/SOURCE1/TEMP_TABLE3')
    OMBCOMMIT
    OMBPlus tells me that the command ran successfully. But if i take a look on the design center, the change didn't occur. The old location for the operator remains.
    Am i using the right property type? database_link?
    Thank You!
    Filipe

    What you've run only change the link location. It doesn't change the bound location.
    I've write an OMB scripts to automate the changing of bound location within different project .
    set OMBPROMPT ON
    OMBDCC
    OMBCC '/'
    set projects [OMBLIST PROJECTS]
    puts -nonewline "Please enter the Project Name ($projects): "
    gets stdin projectName
    set path [lindex [OMBDCC] 1]
    OMBCC '$projectName'
    set modules [OMBLIST ORACLE_MODULES]
    puts -nonewline "Please enter the Module Name ($modules): "
    gets stdin moduleName
    puts "================"
    puts "Finding on Module $moduleName"
    set path [lindex [OMBDCC] 1]
    set no_mod 1
    OMBCC '$path/$moduleName'
    set no_map 1
    puts "Find $moduleName"
    foreach mapname [OMBLIST MAPPINGS] {
    foreach klname [OMBRETRIEVE MAPPING '$mapname' GET OPERATORS] {
    set bname [lindex [OMBRETRIEVE MAPPING '$mapname' OPERATOR '$klname' GET BOUND_OBJECT] 1]
    set oname [lindex [OMBRETRIEVE MAPPING '$mapname' OPERATOR '$klname' GET BOUND_OBJECT] 0]
    # PTI_DW_TST is the name of project orig bound
    # PTI_DW is the name of project destination bound
    set result [regexp {^(/PTI_DW_TST)+} $bname match]
    if { $result == 1 } {
    set myresult [regsub {^(/PTI_DW_TST)+} $bname "/PTI_DW" new_bname]
    #puts "$klname ($oname) : $bname => $new_bname"
    OMBRECONCILE $oname '$new_bname' TO MAPPING '$mapname' OPERATOR '$klname' USE (RECONCILE_STRATEGY 'REPLACE', MATCHING_STRATEGY 'MATCH_BY_OBJECT_NAME')
    puts "Reconcile Mapping $mapname change $bname to $new_bname for operator $klname with type $oname"
    incr no_map
    OMBCC '/'

  • Changing the bounding box size

    When I go to print an image in Photoshop CC, a dialogue box appears and on the left-hand side is the image to be printed. Bordering the image are small diagonal lines which I'm assuming are the bounding box. The distance between the edge of the page varies from side to side and I want to center the photo. I can't see how to do that.
    Thanks.

    The print dialog preview area show basically three areas.  The Paper size the printer is set to and the sizes are displayed with numeric unites. If you see small diagonal lines these are showing the areas the printer can not print on with the current settings.  With different printer setting this area may change for example if the printer support borderless the side non printable may go way but there still be some top and bottom non printable area. The Bottom non printable area may go away if you switch from sheet feed to roll paper feed. Inside the diagonal line is the printable area and inside that a bounding box of the image. If You check scale for media the image will be scaled to fit within the print area.

  • Change Mouse Cursor Inside JTextPane

    Hello Everyone,
    I am trying to change the mouse cursor of a specific text of a JTextPane to:
    setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));This specific text is a hyperlink which its color is blue and it is underlined, so I want to have the mouse cursor changed to make clearer that you can click on it.
    I thought about trying to track the mouse position inside the JTextPane until it reachs the text position but I am not aware of any class that provides this feature. Does anyone know or have another ideia?
    Any help is appreciated,
    Thanks in advance
    Edited by: ZeroTodd on Aug 10, 2010 6:26 AM

    This specific text is a hyperlink which its color is blue and it is underlined, so I want to have the mouse cursor changed to make clearer that you can click on it.That's the default behavior (in the default Metal LaF, at least) when you setEditable(false). And IMO it doesn't make much sense to change the cursor or allow hyperlink navigation when the text pane is editable.
    db

  • Changing the bounds....

    i am have problems changing the size of my java applet, could anyone please help
    cheers
    sinky

    If you mean applet size as displayed on a web page, simply change the HTML invoking the applet.
    - Saish
    "My karma ran over your dogma." - Anon

  • Is changing from JTextArea to JTextPane a big deal???

    hi, me again,
    I was just wondering if anybody could tell me if it is a big deal to change from a TextArea to a TextPane! I have only realised what I can and can't do in a textarea and was wondering if I have a lot of work ahead with documents and attribute sets!?
    anyone have any comforting or reassuring word for me before I go a mess up my program!!

    If you use version control or make a snapshot of your source code, you can try to explore and learn from it (if and only if there is no time constraint)

  • How to change Tab size in JTextPane?

    When I press Tab key in JTextPane, it push too much for tab.
    I want to put 4 blank space size tab when user press tab key.
    How can I do this?

    1) For a JTextArea use:
    textArea.setTabSize( 4 );
    2) If you can use a JEditorPane instead of a JTextPane (this only works on a PlainDocument not a StyledDocument):
    editorPane.getDocument().putProperty( PlainDocument.tabSizeAttribute, 4 );
    3) For a JTextPane you must play with attributes. (Works best when using a monospaced font)
    import java.awt.*;
    import javax.swing.*;
    import javax.swing.text.*;
    public class TextPaneTabs extends JFrame
         public TextPaneTabs()
              JTextPane textPane = new JTextPane();
              textPane.setFont( new Font("monospaced", Font.PLAIN, 12) );
              JScrollPane scrollPane = new JScrollPane( textPane );
              scrollPane.setPreferredSize( new Dimension( 200, 200 ) );
              getContentPane().add( scrollPane );
              setTabs( textPane, 4 );
         public void setTabs( JTextPane textPane, int charactersPerTab)
              FontMetrics fm = textPane.getFontMetrics( textPane.getFont() );
              int charWidth = fm.charWidth( 'w' );
              int tabWidth = charWidth * charactersPerTab;
              TabStop[] tabs = new TabStop[10];
              for (int j = 0; j < tabs.length; j++)
                   int tab = j + 1;
                   tabs[j] = new TabStop( tab * tabWidth );
              TabSet tabSet = new TabSet(tabs);
              SimpleAttributeSet attributes = new SimpleAttributeSet();
              StyleConstants.setTabSet(attributes, tabSet);
              int length = textPane.getDocument().getLength();
              textPane.getStyledDocument().setParagraphAttributes(0, length, attributes, true);
         public static void main(String[] args)
              TextPaneTabs frame = new TextPaneTabs();
              frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
              frame.pack();
              frame.setVisible(true);
    }For more information, here is an article from The Swing Connection titled "Tabbing in Text Documents"
    http://java.sun.com/products/jfc/tsc/articles/text/tabs/

  • Is it possible to change the bounds of a progressBar? (to a different shape

    I want to draw the shape of a battery, and use it as a progress bar. Now I know I can do this from scratch, and I have done a test case, but it simply doesn't look as good as the JProgressBar does.
    I have tried reading the JProgressBar class, to see where it draws the rect, and copy the class, only make it fill a <code>Shape</code> but I haven't had any luck.
    anyone have any ideas?

    I'm not sure I completely understand your response...what do you mean by aspect? also don't or cant?

  • How to listen and obtain caret positions of changed text in JTextPane?

    Hi,
    I have a JTextPane that displays text with some styles on particular words in the text. For example, I highlight words with red color if they are in my dictionary file. I use regular expression to find matches, replace them with their corresponded definitions, and call setCharacterAttributes to add styles to the definitions. I store all start and end caret positions of the matched words/definitions in a vector. So, I can redisplay styles of all previous matches.
    The problem is that I'd like to be able to edit the text of some previous matches. So, with those changes all caret positions that I already store in the vector need to be updated.
    How can I obtain caret positions of changed text in JTextPane?
    How can I know that a user is currently changing text in the JTextPane?
    How can I get style of text such as color that is being changed?
    Thank you very much.

    Thank you very much, camickr, for your reply.
    I think that I might not know the right way to handle JTextPane and Document object.
    What I have done are:
    - Add style to JTextPane using, for example,
    Style targetCurrentMatchStyle = this.targetWindowTextPane.addStyle("Red", null);
    StyleConstants.setForeground(targetCurrentMatchStyle, Color.red);//For highlight - Then, I use regular expression (Pattern and Matcher) to find a match in text. For each match, I get start and end position from matcher.start() and matcher.end().
    if(matcher.find(start)){
    String term=matcher.group();
    int start=matcher.start();
    int end = matcher.end();
    //find definition for the matched term.
    String definition=mydictionaryHash.get(term);
    //Store caret positions in lists
    startPositionList.add(start);
    matchedLength=lengthList.add(definition.length());
    //Add changed to text in textpane
    StringBuffer sb=new StringBuffer();
    matcher.appendReplacement(sb, definition);
    matcher.appendTail(sb);
    //Get translated text from StringBuffer after replacement
    String translatedText=sb.toString();
    targetWindoTextPane.setText(translatedText);
    //Update start position for next search
    start=start+definition.length();
    //Add style to matched regions below.
    }- From the lists of start positions and matched lengths, I use the following code to add "Red" color to the matched text regions including all previously matched.
    for(int i=0;i<startPositionList.size();i++){
    this.targetWindowTextPane.getStyledDocument().setCharacterAttributes(
    startPositionList.get(i),
    lengthList.get(i),
    this.targetWindowTextPane.getStyle("Red"),
    true);
    }My issue is that I'd like to be able edit previously matched regions and update all positions of the matched regions stored in the lists.

  • Hyperlink panel disabled - So how do I change the appearance of a hyperlink?

    I am at the final stages of layout and the only thing preventing me from publishing electronically is that the hyperlinks have bounding boxes around them. I have previously been able to use the hyperlink options to change the appearance of a hyperlink but my panel is completely greyed out > see below. I can only change the destination and that does not give any link options. The panel doesn't even register any hyperlinks although you can see many in my screen grab alone. I have modified the character style but since these are active links (which should remain active), the style does not change the bounding box. I even tried retyping links and linking them to their URL with InDesign but I cannot control any options after a link has been made. I also cannot afford to do this +100 times. Anyone have any tips? I'm using CS6 on a MacBook Pro. I've already rebooted the computer and InDesign to no avail. Am I doing something wrong? Is there a script I can use?
    Thanks to anyone who can help!

    This is the sort of problem that is typically casued by damaged prefs. See Replace Your Preferences

  • How to change page orientation in Pages?

    Hi,
    I would like to change page orientation for Just one page inside a document.
    Say I have page 3 that I want to be landscape and not vertical, how can I do it?
    I haven't been able to find this in Pages, I found it in Word though.
    Any idea?

    The rotation in Preview is just a simple command in the .pdf. It all seems to sort itself out in printing, Acrobat has the occasional odd moment where pages are rotated from their real orientation. It is like the "cropping" in .pdf files which really doesn't cut anything off it just changes the bounding box so what you see appears to be cropped.

  • JTextPane

    How can I disable the word wrap in a JTextPane?

    hmm i don't know if thats possible...
    i was looking on the web actually and i ran across this:
    http://skunkdav.sourceforge.net/doc/org/skunk/swing/text/TextEditorPane.html
    i think someone recognized this problem and created a new package which you can download, which will do this.
    other than that i can't think of anything.....i read somewhere that you can only do it by changing the JScrollPane the JTextPane is inside of, like minimizing the vertical scrollpane.
    --good luck!                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               

  • [JS IDCS5] changing geometricBounds

    When I change the geometricBounds of a frame (myFrame.geometricBounds = [0, 0, 100, 100]), the graphic within that frame is moving. I want to change these bounds, but the graphic inside has to stay at his position (x = 0, y = 0).
    Regards, Sjoerd

    Solution:
    save the geometricBounds of the frame
    resize Frame
    declare values of the saved geometricBounds
    move the inline graphic backwards with the declared values
    Example:
    var myBounds = mySelection[i].geometricBounds;
    mySelection[i].geometricBounds = ["0mm", "0mm", "130mm", "130mm"];
    var myX = myBounds[0];
    var myY = myBounds[1];
    mySelection[i].graphics[0].move(undefined, [-myY, -myX]);
    Sjoerd

  • Different color for JTextPane rows

    Hi!
    Do you know if it's possible to write rows in different colors in a JTextPane or it writes in ForeGround color every row ...
    Thanks!

    You can change colors in a JTextPane by getting the underlying Document and make modifications to it. Here is an example of how to change the current print color:   Document doc = textPane.getDocument();
       MutableAttributeSet attr = new SimpleAttributeSet();
       StyleConstants.setForeground(attr, newColor);
       doc.setCharacterAttributes(attr);

  • Help, experiencing minor bugs in program

    this is supposed to use rectangles and you should be able to load and save and they have colors and do a few more things with them, the loading is where it doesn't work.
    *-------------------------------------------------------------- 80 columns ---|
    * This is the main class for the application. It is built along the same
    * lines as the Editor class of project 1. It has a constructor, two instance
    * methods, and a static main()  that kicks the whole thing off.
    * The two instance methods are a menu creation method, and a menuItems
    * initialisation method.  The constructor instantiates the window
    * and sets up its internals by creating and installing the drawing canvas,
    * toolbar, and menus. All of the code works correctly as is and should
    * require no changes.
    * @version      1.1 15/04/01
    * @author       Julie Zelenski
    * @author       Restructured by Ian A. Mason
    * @see       javax.swing.JFrame
    * @see       javax.swing.JMenuBar
    * @see       javax.swing.JMenuItem
    * @see       javax.swing.JMenu
    import java.awt.*;
    import javax.swing.*;
    import java.awt.event.*;
    public class JavaDraw extends JFrame {
        final Toolbar toolbar = new Toolbar();
        final DrawingCanvas canvas = new DrawingCanvas(toolbar, 350, 350);
        final int menuMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
        final JMenuBar mb = new JMenuBar();
        final String[]
             fileMenuItems = {"Clear all", "Load file", "Save to file", "Quit"};
        final int[] fileKeyCodes = {KeyEvent.VK_N, KeyEvent.VK_O, KeyEvent.VK_S, KeyEvent.VK_Q};
        final ActionListener[] fileActionListeners = {
         new ActionListener() {
              public void actionPerformed(ActionEvent e) {
                  canvas.clearAll();}},
         new ActionListener() {
              public void actionPerformed(ActionEvent e) {
                  canvas.loadFile();}},
         new ActionListener() {
              public void actionPerformed(ActionEvent e) {
                  canvas.saveToFile();}},
         new ActionListener() {
              public void actionPerformed(ActionEvent e) {
                  System.exit(0);}}
        final String[] editMenuItems = {"Cut", "Copy", "Paste", "Delete"};
        final int[] editKeyCodes = {KeyEvent.VK_X, KeyEvent.VK_C, KeyEvent.VK_V, KeyEvent.VK_BACK_SPACE};
        final int[] editMenuMasks = {menuMask, menuMask, menuMask, 0};
        final ActionListener[] editActionListeners = {
         new ActionListener() {
              public void actionPerformed(ActionEvent e) { canvas.cut();}},
         new ActionListener() {
              public void actionPerformed(ActionEvent e) { canvas.copy();}},
         new ActionListener() {
              public void actionPerformed(ActionEvent e) { canvas.paste();}},
         new ActionListener() {
              public void actionPerformed(ActionEvent e) { canvas.delete();}}
        final String[] layeringMenuItems = {"Bring to front", "Send to back"};
        final int[]    layeringKeyCodes = {KeyEvent.VK_F, KeyEvent.VK_B};
        final ActionListener[] layeringActionListeners = {
         new ActionListener() {
              public void actionPerformed(ActionEvent e) {
                  canvas.bringToFront();}},
         new ActionListener() {
              public void actionPerformed(ActionEvent e) {
                  canvas.sendToBack();}}
        private JavaDraw(){
         super("JavaDraw!");
         toolbar.setCanvas(canvas);
         getContentPane().add(toolbar, BorderLayout.SOUTH);
         getContentPane().add(canvas, BorderLayout.CENTER);
         createMenus();
         setJMenuBar(mb);
         setLocation(100, 20);
         pack();
         setVisible(true);
        static public void main(String[] args){
         JavaDraw javaDraw = new JavaDraw();
        private void initMenus(JMenu m,
                      String  miLabel,
                      int keyCode,
                      int menuMask,
                      ActionListener al){
         JMenuItem mi = new JMenuItem(miLabel);
         m.add(mi);
         mi.addActionListener(al);
         mi.setAccelerator(KeyStroke.getKeyStroke(keyCode, menuMask));
        private void createMenus(){
         JMenu m;
         m = new JMenu("File");
         for(int i = 0; i < fileMenuItems.length; i++)
             initMenus(m,
                    fileMenuItems,
              fileKeyCodes[i],
              menuMask,
              fileActionListeners[i]);
         mb.add(m);
         m = new JMenu("Edit");
         for(int i = 0; i < editMenuItems.length; i++)
         initMenus(m,
              editMenuItems[i],
              editKeyCodes[i],
              editMenuMasks[i],
              editActionListeners[i]);
         mb.add(m);
         m = new JMenu("Layering");
         for(int i = 0; i < layeringMenuItems.length; i++)
         initMenus(m,
              layeringMenuItems[i],
              layeringKeyCodes[i],
              menuMask,
              layeringActionListeners[i]);
         mb.add(m);
    *-------------------------------------------------------------- 80 columns ---|
    * The DrawingCanvas class a small extension of JComponent
    * @version 1.1 15/04/01
    * @author Julie Zelenski
    * @author (touched up by Ian A. Mason)
    * @see javax.swing.JComponent
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.event.*;
    import java.util.*;
    public class DrawingCanvas extends JComponent{
    static final int DRAG_NONE = 0;
    static final int DRAG_CREATE = 1;
    static final int DRAG_RESIZE = 2;
    static final int DRAG_MOVE = 3;
    // list of all shapes on canvas
    protected Vector allShapes;          
    // currently selected shape (can be null at times)
    protected Rect selectedShape;
    // reference to toolbar to message for tool&color settings
    protected Toolbar toolbar;
    protected Rect clipboard=null;          
    /* These are the unimplemented menu commands. The menus are already
    * set up to send the correct messages to the canvas, but the
    * method bodies themselves are currently completely empty. It will
    * be your job to fill them in!
    public void cut() {
         copy();
         delete();
    public void copy() {
         int x=(int)selectedShape.getBounds().getX();
         int y=(int)selectedShape.getBounds().getY();
         Point p=new Point(x,y);
         clipboard=new Rect(p,this);
         clipboard.setBounds(selectedShape.getBounds());
    public void paste() {
         if(clipboard==null)
              return;
         allShapes.add(clipboard);
         setSelectedShape(clipboard);
         copy();
         this.repaint();
    public void delete() {
         if(selectedShape==null)
              return;
         else{
         int num=allShapes.indexOf(selectedShape);
         allShapes.remove(num);
         selectedShape=null;
         this.repaint();
    public void clearAll() {
         allShapes.removeAllElements();
         this.repaint();
    public void loadFile() {
         Load load=new Load(this);
         load.setSize(250,200);
         load.validate();
         load.setVisible(true);
    public void done(Vector vect){
         allShapes.removeAllElements();
         for(int i=0;i<vect.size();i++){
              allShapes.add(vect.elementAt(i));
         this.repaint();
    public void saveToFile() {
         Save save=new Save(allShapes);
         save.setSize(250,200);
         save.validate();
         save.setVisible(true);
    public void bringToFront() {
         if(selectedShape==null)
              return;
         int size=allShapes.size();
         int index=allShapes.indexOf(selectedShape);
         for(int i=index+1;i<=size-1;i++){
              allShapes.set(i-1,allShapes.elementAt(i));
         allShapes.set(size-1,selectedShape);
         this.repaint();
    public void sendToBack() {
         if(selectedShape==null)
              return;
         int index=allShapes.indexOf(selectedShape);
         for(int i=index-1;i>=0;i--){
              allShapes.remove(allShapes.elementAt(i+1));
              allShapes.add(i+1,allShapes.elementAt(i));
         allShapes.remove(allShapes.elementAt(0));
         allShapes.add(0,selectedShape);
         this.repaint();
    * Constructor for creating a new empty DrawingCanvas. We set up
    * our size and background colors, instantiate an empty vector of shapes,
    * and install a listener for mouse events using our inner class
    * CanvasMouseHandler
    public DrawingCanvas(Toolbar tb, int width, int height){
         setPreferredSize(new Dimension(width, height));
         setBackground(Color.white);
         toolbar = tb;
         allShapes = new Vector();
         selectedShape = null;
         CanvasMouseHandler handler = new CanvasMouseHandler();
         addMouseListener(handler);
         addMouseMotionListener(handler);
    * All components are responsible for drawing themselves in
    * response to repaint() requests. The standard method a component
    * overrides is paint(Graphics g), but for Swing components, the default
    * paint() handler calls paintBorder(), paintComponent() and paintChildren()
    * For a Swing component, you override paintComponent and do your
    * drawing in that method. For the drawing canvas, we want to
    * clear the background, then iterate through our shapes asking each
    * to draw. The Graphics object is clipped to the region to update
    * and we use to that avoid needlessly redrawing shapes outside the
    * update region.
    public void paintComponent(Graphics g){
         Rectangle regionToRedraw = g.getClipBounds();
         g.setColor(getBackground());
         g.fillRect(regionToRedraw.x, regionToRedraw.y,
              regionToRedraw.width, regionToRedraw.height);
         Iterator iter = allShapes.iterator();
         while (iter.hasNext())
         ((Rect)iter.next()).draw(g, regionToRedraw);
    * Changes the currently selected shape. There is at most
    * one shape selected at a time on the canvas. It is possible
    * for the selected shape to be null. Messages the shape to
    * change its selected state which will in turn refresh the
    * shape with the knobs active.
    protected void setSelectedShape(Rect shapeToSelect) {
         // if change in selection
         if (selectedShape != shapeToSelect) {
         // deselect previous selection
         if (selectedShape != null)
              selectedShape.setSelected(false);
         // set selection to new shape
         selectedShape = shapeToSelect;
         if (selectedShape != null) {
              shapeToSelect.setSelected(true);
    * A hit-test routine which finds the topmost shape underneath a
    * given point.We search Vector of shapes in back-to-front order
    * since shapes created later are added to end and drawn last, thus
    * appearing to be "on top" of the earlier ones. When a click comes
    * in, we want to select the top-most shape.
    protected Rect shapeContainingPoint(Point pt){
         for (int i = allShapes.size()-1; i >= 0; i--) {
         Rect r = (Rect)allShapes.elementAt(i);
         if (r.inside(pt)) return r;
         return null;
    * The inner class CanvasMouseHandler is the object that handles the
    * mouse actions (press, drag, release) over the canvas. Since there is
    * a bit of state to drag during the various operations (which shape,
    * where we started from, etc.) it is convenient to encapsulate all that
    * state with this little convenience object and register it as the
    * handler for mouse events on the canvas.
    protected class CanvasMouseHandler
         extends MouseAdapter implements MouseMotionListener {
         Point dragAnchor;          
         // variables using to track state during drag operations
         int dragStatus;
         /** When the mouse is pressed we need to figure out what
         * action to take. If the tool mode is arrow, the click might
         * be a select, move or reisze. If the tool mode is one of the
         * shapes, the click initiates creation of a new shape.
         public void mousePressed(MouseEvent event){
         Rect clicked = null;
         Point curPt = event.getPoint();
         // first, determine if click was on resize knob of selected shape
         if (toolbar.getCurrentTool() == Toolbar.SELECT) {
              if (selectedShape != null &&
              (dragAnchor = selectedShape.getAnchorForResize(curPt))
              != null) {
              // drag will resize this shape
              dragStatus = DRAG_RESIZE;     
              } else if ((clicked = shapeContainingPoint(curPt)) != null) {
              // if not, check if any shape was clicked
              setSelectedShape(clicked);
              // drag will move this shape      
              dragStatus = DRAG_MOVE;
              dragAnchor = curPt;
              } else {     
              // else this was a click in empty area,
              // deselect selected shape,
              setSelectedShape(null);
              // drag does nothing in this case
              dragStatus = DRAG_NONE;
         } else {
              Rect newShape = new Rect(curPt, DrawingCanvas.this);
              // create rect here
              allShapes.add(newShape);
              setSelectedShape(newShape);
              dragStatus = DRAG_CREATE;          
              // drag will create (resize) this shape
              dragAnchor = curPt;
         /** As the mouse is dragged, our listener will receive periodic
         * updates as mouseDragged events. When we get an update position,
         * we update the move/resize event that is in progress.
         public void mouseDragged(MouseEvent event){
         Point curPt = event.getPoint();
         switch (dragStatus) {
         case DRAG_MOVE:
              selectedShape.translate(curPt.x - dragAnchor.x,
                             curPt.y - dragAnchor.y);
              // update for next dragged event
              dragAnchor = curPt;
              break;
         case DRAG_CREATE: case DRAG_RESIZE:
              selectedShape.resize(dragAnchor, curPt);
              break;
         public void mouseMoved(MouseEvent e) {}
    /** A little helper routine that will be useful for the load & save
    * operations. It brings up the standard JFileChooser dialog and
    * allows the user to specify a file to open or save. The return
    * value is the full path to the chosen file or null if no file was
    * selected.
    protected String filenameChosenByUser(boolean forOpen){
         JFileChooser fc = new JFileChooser(System.getProperty("user.dir") +
                             java.io.File.separator + "Documents");
         int result = (forOpen? (fc.showOpenDialog(this)) :
              fc.showSaveDialog(this));
         java.io.File chosenFile = fc.getSelectedFile();
         if (result == JFileChooser.APPROVE_OPTION && chosenFile != null)
         return chosenFile.getPath();
         return null;
         // return null if no file chosen or dialog cancelled
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;
    import java.util.Vector;
    import java.io.*;
    class Load extends JFrame implements ActionListener, Serializable{
         Container contentPane;
         JTextField jtf;
         JButton jb;
         Object obj=null;
         Load load;
         Thread thread;
         DrawingCanvas draw;
         public Load(DrawingCanvas dc){
              draw=dc;
              contentPane=getContentPane();
              contentPane.setLayout(new FlowLayout());
              jtf=new JTextField(20);
              jb=new JButton("Load");
              jb.addActionListener(this);
              contentPane.add(jtf);
              contentPane.add(jb);
         public void actionPerformed(ActionEvent e){
              String text=jtf.getText();
              SimpleObjectReader reader=SimpleObjectReader.openFileForReading(text+".shp");
              if(reader==null){
                   System.out.println("Couldn't open file!");
                   return;
              obj=reader.readObject();
              reader.close();
              draw.done((Vector)obj);
              this.setVisible(false);
    import javax.swing.*;
    import java.awt.event.*;
    import java.awt.*;
    import java.util.Vector;
    import java.io.*;
    class Save extends JFrame implements ActionListener, Serializable{
         Container contentPane;
         JTextField jtf;
         Vector shapes;
         JButton jb;
         public Save(Vector shapeVector){
              shapes=shapeVector;
              contentPane=getContentPane();
              contentPane.setLayout(new FlowLayout());
              jtf=new JTextField(20);
              jb=new JButton("Save");
              jb.addActionListener(this);
              contentPane.add(jtf);
              contentPane.add(jb);
         public void actionPerformed(ActionEvent e){
              String text=jtf.getText();
              SimpleObjectWriter writer=SimpleObjectWriter.openFileForWriting(text+".shp");
              if(writer==null){
                   System.out.println("Couldn't open file!");
                   return;
              writer.writeObject(shapes);
              writer.close();
              this.setVisible(false);
    *-------------------------------------------------------------- 80 columns ---|
    * The RectShape class defines a simple rectangular shape object.
    * It tracks its bounding box, selected state, and the canvas it is being
    * drawn in. It has some basic methods to select, move, and resize the
    * rectangle. It has methods that draw the shape in the selected or unselected
    * states and updates the canvas whenever the state or bounds of the rectangle
    * change. The code that is there works properly, but you will need to extend
    * and change the code to support additional features.
    * @version 1.1 15/04/01
    * @author Julie Zelenski
    * @author (touched up by Ian A. Mason)
    import java.awt.*;
    import java.io.*;
    public class Rect implements Serializable{     
    protected Rectangle bounds;
    protected boolean isSelected;
    public Color color;
    public DrawingCanvas canvas;
    protected static final int KNOB_SIZE = 6;
    protected static final int NONE = -1;
    protected static final int NW = 0;
    protected static final int SW = 1;
    protected static final int SE = 2;
    protected static final int NE = 3;
    /** The constructor that creates a new zero width and height rectangle
    * at the given position in the canvas.
    public Rect(Point start, DrawingCanvas dcanvas){
         canvas = dcanvas;
         bounds = new Rectangle(start);
         color=canvas.toolbar.getCurrentColor();
    /** The "primitive" for all resizing/moving/creating operations that
    * affect the rect bounding box. The current implementation just resets
    * the bounds variable and triggers a re-draw of the union of the old &
    * new rectangles. This will redraw the shape in new size and place and
    * also "erase" if bounds are now smaller than before. It is a good
    * design to have all changes to a critical variable bottleneck through
    * one method so that you can be sure that all the updating that goes
    * with it only needs to be implemented in this one place. If any of your
    * subclasses have additional work to do when the bounds change, this is
    * the method to override. Make sure that any methods that change the
    * bounds call this method instead of directly manipulating the variable.
    protected void setBounds(Rectangle newBounds){
         Rectangle oldBounds = bounds;
         bounds = newBounds;
         updateCanvas(oldBounds.union(bounds));
    /** The resize operation is called when first creating a rect, as well as
    * when later resizing by dragging one of its knobs. The two parameters
    * are the points that define the new bounding box. The anchor point
    * is the location of the mouse-down event during a creation operation
    * or the opposite corner of the knob being dragged during a resize
    * operation. The end is the current location of the mouse. If you
    * create the smallest rectangle which encloses these two points, you
    * will have the new bounding box. Use the setBounds() primitive which
    * is the bottleneck we are using for all geometry changes, it handles
    * updating and redrawing.
    public void resize(Point anchor, Point end){
         Rectangle newRect = new Rectangle(anchor);
         // creates smallest rectange which
         // includes both anchor & end
         newRect.add(end);
         // reset bounds & redraw affected areas
         setBounds(newRect);      
    public Rectangle getBounds(){
         return bounds;
    /** The translate operation is called when moving a shape by dragging in
    * the canvas. The two parameters are the delta-x and delta-y to move
    * by. Note that either or both can be negative. Create a new rectangle
    * from our bounds and translate and then go through the setBounds()
    * primitive to change it.
    public void translate(int dx, int dy){
         Rectangle newRect = new Rectangle(bounds);
         newRect.translate(dx, dy);
         setBounds(newRect);
    /** Used to change the selected state of the shape which will require
    * updating the affected area of the canvas to add/remove knobs.
    public void setSelected(boolean newState){
         isSelected = newState;
         // need to erase/add knobs
         // including extent of extended bounds
         updateCanvas(bounds, true);
    /** The updateCanvas() methods are used when the state has changed
    * in such a way that it needs to be refreshed in the canvas to properly
    * reflect the new settings. The shape should take responsibility for
    * messaging the canvas to properly update itself. The appropriate AWT/JFC
    * way to re-draw a component is to send it the repaint() method with the
    * rectangle that needs refreshing. This will cause an update() event to
    * be sent to the component which in turn will call paint(), where the
    * real drawing implementation goes. See the paint() method in
    * DrawingCanvas to see how it is implemented.
    protected void updateCanvas(Rectangle areaOfChange, boolean enlargeForKnobs){
         Rectangle toRedraw = new Rectangle(areaOfChange);
         if (enlargeForKnobs)
         toRedraw.grow(KNOB_SIZE/2, KNOB_SIZE/2);
         canvas.repaint(toRedraw);
    protected void updateCanvas(Rectangle areaOfChange){
         updateCanvas(areaOfChange, isSelected);
    /** When the DrawingCanvas needs a shape to draw itself, it sends a draw
    * message, passing the graphics context and the current region being
    * redrawn. If the shape intersects with that region, it must draw itself
    * doing whatever it takes to properly represent itself in the canvas
    * (colors, location, size, knobs, etc.) by messaging the Graphics object.
    public void draw(Graphics g, Rectangle regionToDraw){
         if (!bounds.intersects(regionToDraw))
         return;
         g.setColor(color);
         g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
         if (isSelected) { // if selected, draw the resizing knobs
         // along the 4 corners
         Rectangle[] knobs = getKnobRects();
         for (int i = 0; i < knobs.length; i++)
              g.fillRect(knobs[i].x, knobs[i].y,
                   knobs[i].width, knobs[i].height);
    /** When the DrawingCanvas needs to determine which shape is under
    * the mouse, it asks the shape to determine if a point is "inside".
    * This method should returns true if the given point is inside the
    * region for this shape. For a rectangle, any point within the
    * bounding box is inside the shape.
    public boolean inside(Point pt){
         return bounds.contains(pt);
    /** When needed, we create the array of knob rectangles on demand. This
    * does mean we create and discard the array and rectangles repeatedly.
    * These are small objects, so perhaps it is not a big deal, but
    * a valid alternative would be to store the array of knobs as an
    * instance variable of the Shape and and update the knobs as the bounds
    * change. This means a little more memory overhead for each Shape
    * (since it is always storing the knobs, even when not being used) and
    * having that redundant data opens up the possibility of bugs from
    * getting out of synch (bounds move but knobs didn't, etc.) but you may
    * find that a more appealing way to go. Either way is fine with us.
    * Note this method provides a nice unified place for one override from
    * a shape subclass to substitute fewer or different knobs.
    protected Rectangle[] getKnobRects(){
         Rectangle[] knobs = new Rectangle[4];
         knobs[NW] = new Rectangle(bounds.x - KNOB_SIZE/2,
                        bounds.y - KNOB_SIZE/2, KNOB_SIZE, KNOB_SIZE);
         knobs[SW] = new Rectangle(bounds.x - KNOB_SIZE/2,
                        bounds.y + bounds.height - KNOB_SIZE/2,
                        KNOB_SIZE, KNOB_SIZE);
         knobs[SE] = new Rectangle(bounds.x + bounds.width - KNOB_SIZE/2,
                        bounds.y + bounds.height - KNOB_SIZE/2,
                        KNOB_SIZE, KNOB_SIZE);
         knobs[NE] = new Rectangle(bounds.x + bounds.width - KNOB_SIZE/2,
                        bounds.y - KNOB_SIZE/2,
                        KNOB_SIZE, KNOB_SIZE);
         return knobs;
    /** Helper method to determine if a point is within one of the resize
    * corner knobs. If not selected, we have no resize knobs, so it can't
    * have been a click on one. Otherwise, we calculate the knob rects and
    * then check whether the point falls in one of them. The return value
    * is one of NW, NE, SW, SE constants depending on which knob is found,
    * or NONE if the click doesn't fall within any knob.
    protected int getKnobContainingPoint(Point pt){
         // if we aren't selected, the knobs
         // aren't showing and thus there are no knobs to check
         if (!isSelected) return NONE;
         Rectangle[] knobs = getKnobRects();
         for (int i = 0; i < knobs.length; i++)
         if (knobs[i].contains(pt))
              return i;
         return NONE;
    /** Method used by DrawingCanvas to determine if a mouse click is starting
    * a resize event. In order for it to be a resize, the click must have
    * been within one of the knob rects (checked by the helper method
    * getKnobContainingPoint) and if so, we return the "anchor" ie the knob
    * opposite this corner that will remain fixed as the user drags the
    * resizing knob of the other corner around. During the drag actions of a
    * resize, that fixed anchor point and the current mouse point will be
    * passed to the resize method, which will reset the bounds in response
    * to the movement. If the mouseLocation wasn't a click in a knob and
    * thus not the beginning of a resize event, null is returned.
    public Point getAnchorForResize(Point mouseLocation){
         int whichKnob = getKnobContainingPoint(mouseLocation);
         // no resize knob is at this location
         if (whichKnob == NONE)
         return null;
         switch (whichKnob) {
         case NW: return new Point(bounds.x + bounds.width,
                        bounds.y + bounds.height);
         case NE: return new Point(bounds.x, bounds.y + bounds.height);
         case SW: return new Point(bounds.x + bounds.width, bounds.y);
         case SE: return new Point(bounds.x, bounds.y);
         return null;
    import java.io.*;
    * SimpleObjectReader is a small class to wrap around the usual ObjectStream
    * to shield you from the exception handling which we haven't yet gotten
    * to in class.
    * <P>It has just three methods of note: one to open a new file for reading,
    * one to read an object from an open file, and one to close the file when done.
    * <P>Any object that you attempt to read must properly implement the Serializable
    * interface. Here is a simple example that shows using the SimpleFileReader to
    * to rehydrate objects from a file and print them:
    * <PRE>
    * SimpleObjectReader reader = SimpleObjectReader.openFileForReading("shapes");
    * if (reader == null) {
    * System.out.println("Couldn't open file!");
    * return;
    * Object obj;
    * while ((obj = reader.readObject()) != null)
    * System.out.println(obj);
    * reader.close();
    * </PRE>
    * <P>You are free to edit or extend this class, but we don't expect that
    * you should need to make any changes.
    * @version 1.1 15/04/01
    * @author Julie Zelenski
    * @author (touched up by Ian A. Mason)
    public class SimpleObjectReader {
    private ObjectInputStream ois;
    * Opens a new file for reading. The filename can either be a relative
    * path, which will be relative to the working directory of the program
    * when started, or an absolute path. If the file exists and can be
    * opened, a new SimpleObjectReader is returned. If the file cannot be
    * opened (for any reason: wrong name, wrong path, lack of permissions, etc.)
    * null is returned.
    public static SimpleObjectReader openFileForReading(String filename){
         try {
         return new SimpleObjectReader(new ObjectInputStream(new FileInputStream(filename)));
         } catch(IOException e) {     
         return null;
    * Reads a single object from the file and returns it. If there are
    * no more objects in the file (i.e, we have reached the end of file),
    * null is returned null is returned. null is also
    * returned on any I/O error.
    public Object readObject (){
         try {
         return ois.readObject();
         } catch (IOException e) {
         e.printStackTrace();
         return null;
         } catch (ClassNotFoundException e) {
         e.printStackTrace();
         return null;
    * Closes the file when done reading. You should close a reader when
    * you are finished to release the OS resources for use by others.
    public void close (){
         try {
         ois.close();
         catch (IOException e) {}
    * Constructor is private so that only means to create a new reader
    * is through the static method which does error checking.
    private SimpleObjectReader(ObjectInputStream ois){
         this.ois = ois;
    import java.io.*;
    * SimpleObjectWriter is a small class to wrap around the usual
    * ObjectOutputStream to shield you from the exception handling
    * which we haven't yet gotten to in class.
    * <P>It has just three methods of note: one to open a new file for writing,
    * one to write an object to the file, and one to close the
    * the file when done.
    * <P>Here is a simple example that shows using the SimpleObjectWriter
    * to create a new file and write some objects into it:
    * <PRE>
    * SimpleObjectWriter writer =
    * SimpleObjectWriter.openFileForWriting("objects");
    * if (writer == null) {
    * System.out.println("Couldn't open file!");
    * return;
    * writer.writeObject("Here is a string");
    * writer.writeObject("And another one.");
    * writer.writeObject(new Date());
    * writer.close();
    * </PRE>
    * <P>You are free to edit or extend this class, but we don't expect that
    * you should need to make any changes.
    * @version 1.1 15/04/01
    * @author Julie Zelenski
    * @author (touched up by Ian A. Mason)
    public class SimpleObjectWriter {
    private ObjectOutputStream oos;
    * Opens a new file for writing. The filename can either be a relative
    * path, which will be relative to the working directory of the program
    * when started, or an absolute path. If the file can be created, a
    * new SimpleObjectWriter is returned. If the file already exists, this
    * will overwrite its content

    I'm not reading that either, but to help you for next time:
    - use more than 1 sentence to describe your problem
    - only post the RELEVANT code, or a small test program with the same problem if possible.
    At least you formatted it, I'll give you that.
    Cheers,
    Radish21
    PS. I think in this case, posting another (better worded) thread might be a good idea, because no one is going to read this one. In general though, don't :)

Maybe you are looking for