1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 import com.sun.star.accessibility.*;
23 import com.sun.star.uno.UnoRuntime;
24 
25 import javax.swing.tree.*;
26 import javax.swing.event.*;
27 
28 
29 
30 /** listen to tree model changes in order to update XAccessibleText objects
31 */
32 class TextUpdateListener implements TreeModelListener
33 {
treeNodesChanged(TreeModelEvent e)34     public void treeNodesChanged(TreeModelEvent e)
35     {
36         try {
37         // if the change is to the first child of a DefaultMutableTreeNode
38         // with an XAccessibleText child, then we call updateText
39         int[] aIndices = e.getChildIndices();
40         if( (aIndices != null) &&
41             (aIndices.length > 0) )
42         {
43             // we have a parent... lets check for XAccessibleText then
44             DefaultMutableTreeNode aParent = (DefaultMutableTreeNode)
45                 (e.getTreePath().getLastPathComponent());
46             DefaultMutableTreeNode aNode = (DefaultMutableTreeNode)
47                 (aParent.getChildAt(aIndices[0]));
48             if( aParent.getUserObject() instanceof XAccessibleText)
49             {
50                 // aha! we have an xText. So we can now check for
51                 // the various cases we support
52                 XAccessibleText xText =
53                     (XAccessibleText)aParent.getUserObject();
54 
55                 if( aIndices[0] == 0 )
56                 {
57                     // first child! Then we call updateText
58                     updateText( xText, aNode.toString() );
59                 }
60                 else
61                 {
62                     // JDK 1.4:
63                     //                        // check for pattern "Selection:"
64                     //                         Matcher m = Pattern.compile(
65                     //                             "selection: \\[(-?[0-9]+),(-?[0-9]+)\\] \".*" ).
66                     //                             matcher( aNode.toString() );
67                     //                         if( m.matches() )
68                     //                         {
69                     //                             try
70                     //                             {
71                     //                                 // aha! Selection:
72                     //                                 setSelection( xText,
73                     //                                               Integer.parseInt(m.group(1)),
74                     //                                               Integer.parseInt(m.group(2)) );
75                     //                             }
76                     //                             catch( NumberFormatException f )
77                     //                             {
78                     //                                 // ignore
79                     //                             }
80                     //                         }
81                 }
82             }
83         }
84         }
85         catch (com.sun.star.lang.IndexOutOfBoundsException aException)
86         {}
87     }
88 
89     // don't care:
treeNodesInserted(TreeModelEvent e)90     public void treeNodesInserted(TreeModelEvent e) { ; }
treeNodesRemoved(TreeModelEvent e)91     public void treeNodesRemoved(TreeModelEvent e) { ; }
treeStructureChanged(TreeModelEvent e)92     public void treeStructureChanged(TreeModelEvent e) { ; }
93 
94     /** update the text */
updateText( XAccessibleText xText, String sNew )95     boolean updateText( XAccessibleText xText, String sNew )
96         throws com.sun.star.lang.IndexOutOfBoundsException
97     {
98         // is this text editable? if not, fudge you and return
99         XAccessibleEditableText xEdit =
100             (XAccessibleEditableText) UnoRuntime.queryInterface (
101                 XAccessibleEditableText.class, xText);
102         if (xEdit == null)
103             return false;
104 
105         String sOld = xText.getText();
106 
107         // false alarm? Early out if no change was done!
108         if( sOld.equals( sNew ) )
109             return false;
110 
111         // get the minimum length of both strings
112         int nMinLength = sOld.length();
113         if( sNew.length() < nMinLength )
114             nMinLength = sNew.length();
115 
116         // count equal characters from front and end
117         int nFront = 0;
118         while( (nFront < nMinLength) &&
119             (sNew.charAt(nFront) == sOld.charAt(nFront)) )
120             nFront++;
121         int nBack = 0;
122         while( (nBack < nMinLength) &&
123             ( sNew.charAt(sNew.length()-nBack-1) ==
124                 sOld.charAt(sOld.length()-nBack-1)    ) )
125             nBack++;
126         if( nFront + nBack > nMinLength )
127             nBack = nMinLength - nFront;
128 
129         // so... the first nFront and the last nBack characters
130         // are the same. Change the others!
131         String sDel = sOld.substring( nFront, sOld.length() - nBack );
132         String sIns = sNew.substring( nFront, sNew.length() - nBack );
133 
134         System.out.println("edit text: " +
135             sOld.substring(0, nFront) +
136             " [ " + sDel + " -> " + sIns + " ] " +
137             sOld.substring(sOld.length() - nBack) );
138 
139         boolean bRet = false;
140         try
141         {
142             // edit the text, and use
143             // (set|insert|delete|replace)Text as needed
144             if( nFront+nBack == 0 )
145                 bRet = xEdit.setText( sIns );
146             else if( sDel.length() == 0 )
147                 bRet = xEdit.insertText( sIns, nFront );
148             else if( sIns.length() == 0 )
149                 bRet = xEdit.deleteText( nFront, sOld.length()-nBack );
150             else
151                 bRet = xEdit.replaceText(nFront, sOld.length()-nBack,sIns);
152         }
153         catch( IndexOutOfBoundsException e )
154         {
155             bRet = false;
156         }
157 
158         return bRet;
159     }
160 
setSelection( XAccessibleText xText, int p1, int p2 )161     boolean setSelection( XAccessibleText xText, int p1, int p2 )
162     {
163         try
164         {
165             return xText.setSelection( p1, p2 );
166         }
167         catch( com.sun.star.lang.IndexOutOfBoundsException f )
168         {
169             return false;
170         }
171     }
172 
173     //         /** replace the given node with a new xText node */
174     //         void updateNode( XAccessibleText xText,
175     //                          DefaultMutableTreeNode aNode )
176     //         {
177     //             // create a new node
178     //             DefaultMutableTreeNode aNew = newTextTreeNode( xText );
179     //
180     //             // get parent (must be DefaultMutableTreeNode)
181     //             DefaultMutableTreeNode aParent =
182     //                 (DefaultMutableTreeNode)aNode.getParent();
183     //             if( aParent != null )
184     //             {
185     //                 // remove old sub-tree, and insert new one
186     //                 int nIndex = aParent.getIndex( aNode );
187     //                 aParent.remove( nIndex );
188     //                 aParent.insert( aNew, nIndex );
189     //             }
190     //         }
191 }
192