United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-6787890 : caret position in right-to-left oriented jtextpane corruptable

Details
Type:
Bug
Submit Date:
2008-12-21
Status:
Open
Updated Date:
2011-04-28
Project Name:
JDK
Resolved Date:
Component:
client-libs
OS:
windows_xp
Sub-Component:
javax.swing
CPU:
x86
Priority:
P3
Resolution:
Unresolved
Affected Versions:
6u10
Targeted Versions:

Related Reports

Sub Tasks

Description
FULL PRODUCT VERSION :
java version "1.6.0_10"
Java(TM) SE Runtime Environment (build 1.6.0_10-b33)
Java HotSpto(TM) Client VM (build 11.0-b15, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
MS Windows XP + SP3

A DESCRIPTION OF THE PROBLEM :
I am writing an editor using my own keyboard layout to type in Arabic. To do so, I use jTextPane, and my own implementation of DocumentFilter (where I map English keys to Arabic letters). I start by i) setting the component orientation of jTextPane to be from RIGHT_TO_LEFT, and ii) attaching a caretListener to trace the caret's position.

The problem (I think it is a bug just like what is recorded here: http://bugs.adobe.com/jira/browse/SDK-16315):
Initially as I type text in Arabic, there is one-to-one correspondence between where I point my mouse and where the caret displays, basically, the same place. However, a problem occurs (and can always be re-produced) when I type a word towards the end of the line, follow it by a space character, and that space character causes the word to descend to the next line as a result of a wrap-around. Now, as I point my mouse to that first line again, the location where I click the mouse and the location where the caret flashes are no longer coincident! Also, the caret progression counter is reversed! That is, if there are 5 characters on Line 1, then whereas initially the caret starts from Position 0 on the right-hand side and increases as more text is added from right to left, it is now reversed where the the caret now increases from left to right for the first line, but correctly increases from right to left in the second line!

This problem only (and only) occurs when the last word input on the line descends to the next line when a space is input after it.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
So, here is an example to reproduce the problem. I wrote the code below (JDK1.6_u10, on Netbeans 6.5 RC2) to make it easy to reproduce the problem. In the example, I have replaced the keys A, S, D, F and G with their Arabic corresponding letters alif, seen, daal, faa and jeem. Now, type these letters inside the double quotes (without the double quotes) including the two spaces please and watch out for the output: "asdfg asdfg ". Up until you type the last g and before you type space, all is perfect, and you should notice that the caret position correctly moves from 0 upwards in the printlines I provided. When you type that last space, the second word descends as a result of the wrap-around, and hell breaks loose! Notice that whereas the mouse and caret position are coincident on the second line, there is no way to fine-control the mouse position on the first line any more. Further, whereas adding text on the second line is intuitive (i.e., you can insert more text wherever you point your mouse, which is also where the caret would show up), for the first line, if you point the mouse any place over the written string, the caret displays in a different place, the any added text is added in the wrong place! All this because the caret counter is now reversed, which should never occur.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Simple: for the first line:
i) the cursor should appear where the mouse is pointed,
ii) highlighting as based on selection should start where the mouse is first placed and pressed, and ends where the mouse is released,
iii) caret counter should still be increasing as user moves from right to left (I have provided output for you to trace such affects)
ACTUAL -
In correspondence to the above items i) to iii) for the first line, this is what is recorded:
i) the cursor appears in a different place from where the mouse is pressed,
ii) highlighting is incorrect as it does not follow user's mouse activities' locations
iii) caret counter is now reversed as if component orientation is left to right (and this is only for the first line ... focusing on this should lead to solving the problem)

ERROR MESSAGES/STACK TRACES THAT OCCUR :
None! This is a logical error.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------

package workshop.onframes;

import java.awt.ComponentOrientation;
import java.awt.Rectangle;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.text.BadLocationException;

public class NewJFrame1 extends javax.swing.JFrame {

   /** Creates new form NewJFrame1 */
   public NewJFrame1() {
      initComponents();
      jTextPane1.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);

      CaretListener caretListener = new CaretListener() {

         public void caretUpdate(CaretEvent e) {
            int dot = e.getDot();
            int mark = e.getMark();

            if (dot == mark) {
               try {
                  Rectangle cc = jTextPane1.modelToView(dot);
                  System.out.println("Caret text position: " + dot +
                          ", view location (x, y): (" + cc.x + ", " + cc.y + ")");
               } catch (BadLocationException ble) {
                  System.err.println("CTP: " + dot);
               }
            } else if (dot < mark) {
               System.out.println("Selection from " + dot + " to " + mark);
            } else {
               System.out.println("Selection from " + mark + " to " + dot);
            }
         }
      };

      jTextPane1.addCaretListener(caretListener);
   }

   /** This method is called from within the constructor to
    * initialize the form.
    * WARNING: Do NOT modify this code. The content of this method is
    * always regenerated by the Form Editor.
    */
   @SuppressWarnings("unchecked")
   // <editor-fold defaultstate="collapsed" desc="Generated Code">
   private void initComponents() {

      jScrollPane3 = new javax.swing.JScrollPane();
      jTextPane1 = new javax.swing.JTextPane();

      setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

      jTextPane1.setFont(new java.awt.Font("Tahoma", 0, 24)); // NOI18N
      jTextPane1.setAutoscrolls(false);
      jTextPane1.addKeyListener(new java.awt.event.KeyAdapter() {
         public void keyTyped(java.awt.event.KeyEvent evt) {
            jTextPane1KeyTyped(evt);
         }
      });
      jScrollPane3.setViewportView(jTextPane1);

      javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
      getContentPane().setLayout(layout);
      layout.setHorizontalGroup(
         layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
         .addGroup(layout.createSequentialGroup()
            .addContainerGap()
            .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 159, Short.MAX_VALUE)
            .addContainerGap())
      );
      layout.setVerticalGroup(
         layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
         .addGroup(layout.createSequentialGroup()
            .addContainerGap()
            .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 85, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
      );

      pack();
   }// </editor-fold>

    private void jTextPane1KeyTyped(java.awt.event.KeyEvent evt) {
       if (evt.getKeyChar() == 'a') {
          evt.setKeyChar('\u0627');
       } else if (evt.getKeyChar() == 's') {
          evt.setKeyChar('\u0633');
       } else if (evt.getKeyChar() == 'd') {
          evt.setKeyChar('\u062f');
       } else if (evt.getKeyChar() == 'f') {
          evt.setKeyChar('\u0641');
       } else if (evt.getKeyChar() == 'g') {
          evt.setKeyChar('\u062c');
       }
    }

      /**
       * @param args the command line arguments
       */
    public

   static void main(String args[]) {
      java.awt.EventQueue.invokeLater(new Runnable() {

         public void run() {
            new NewJFrame1().setVisible(true);
         }
      });
   }

   // Variables declaration - do not modify
   private javax.swing.JScrollPane jScrollPane3;
   private javax.swing.JTextPane jTextPane1;
   // End of variables declaration
}

---------- END SOURCE ----------

                                    

Comments



Hardware and Software, Engineered to Work Together