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 23 import com.sun.star.accessibility.AccessibleTextType; 24 import com.sun.star.accessibility.TextSegment; 25 import com.sun.star.accessibility.XAccessibleContext; 26 import com.sun.star.accessibility.XAccessibleText; 27 import com.sun.star.accessibility.XAccessibleEditableText; 28 29 import com.sun.star.awt.Rectangle; 30 import com.sun.star.awt.Point; 31 import com.sun.star.uno.UnoRuntime; 32 import com.sun.star.lang.IndexOutOfBoundsException; 33 import com.sun.star.beans.PropertyValue; 34 35 import java.awt.Container; 36 import java.awt.FlowLayout; 37 import java.awt.BorderLayout; 38 import java.awt.Color; 39 import java.awt.Component; 40 import java.awt.Graphics; 41 import java.awt.event.ActionListener; 42 import java.awt.event.ActionEvent; 43 import javax.swing.JDialog; 44 import javax.swing.JButton; 45 import javax.swing.JPanel; 46 import javax.swing.JLabel; 47 import javax.swing.Icon; 48 import javax.swing.JTextArea; 49 import javax.swing.JOptionPane; 50 import javax.swing.JCheckBox; 51 import javax.swing.JColorChooser; 52 import javax.swing.BoxLayout; 53 import javax.swing.text.JTextComponent; 54 55 56 class AccessibleTextHandler extends NodeHandler 57 { createHandler(XAccessibleContext xContext)58 public NodeHandler createHandler (XAccessibleContext xContext) 59 { 60 XAccessibleText xText = UnoRuntime.queryInterface ( 61 XAccessibleText.class, xContext); 62 if (xText != null) 63 return new AccessibleTextHandler (xText); 64 else 65 return null; 66 } 67 AccessibleTextHandler()68 public AccessibleTextHandler () 69 { 70 } 71 AccessibleTextHandler(XAccessibleText xText)72 public AccessibleTextHandler (XAccessibleText xText) 73 { 74 if (xText != null) 75 maChildList.setSize (8); 76 } 77 createChild(AccessibleTreeNode aParent, int nIndex)78 public AccessibleTreeNode createChild (AccessibleTreeNode aParent, int nIndex) 79 { 80 AccessibleTreeNode aChild = null; 81 XAccessibleText xText = null; 82 if (aParent instanceof AccTreeNode) 83 xText = ((AccTreeNode)aParent).getText(); 84 85 try 86 { 87 if( xText != null ) 88 { 89 switch( nIndex ) 90 { 91 case 0: 92 aChild = new StringNode (xText.getText(), aParent); 93 break; 94 case 1: 95 aChild = new StringNode ("# chars: " + xText.getCharacterCount(), aParent); 96 break; 97 case 2: 98 aChild = new StringNode (characters( xText ), aParent); 99 break; 100 case 3: 101 aChild = new StringNode ("selection: " 102 + "[" + xText.getSelectionStart() 103 + "," + xText.getSelectionEnd() 104 + "] \"" + xText.getSelectedText() + "\"", 105 aParent); 106 break; 107 case 4: 108 aChild = new StringNode ("getCaretPosition: " + xText.getCaretPosition(), aParent); 109 break; 110 case 5: 111 { 112 VectorNode aVec = new VectorNode("portions", aParent); 113 aChild = aVec; 114 aVec.addChild( 115 textAtIndexNode( xText, "Character", 116 AccessibleTextType.CHARACTER, 117 aParent ) ); 118 aVec.addChild( 119 textAtIndexNode( xText, "Word", 120 AccessibleTextType.WORD, 121 aParent ) ); 122 aVec.addChild( 123 textAtIndexNode( xText, "Sentence", 124 AccessibleTextType.SENTENCE, 125 aParent ) ); 126 aVec.addChild( 127 textAtIndexNode( xText, "Paragraph", 128 AccessibleTextType.PARAGRAPH, 129 aParent ) ); 130 aVec.addChild( 131 textAtIndexNode( xText, "Line", 132 AccessibleTextType.LINE, 133 aParent ) ); 134 aVec.addChild( 135 textAtIndexNode( xText, "Attribute", 136 AccessibleTextType.ATTRIBUTE_RUN, 137 aParent ) ); 138 aVec.addChild( 139 textAtIndexNode( xText, "Glyph", 140 AccessibleTextType.GLYPH, 141 aParent ) ); 142 } 143 break; 144 case 6: 145 aChild = new StringNode (bounds( xText ), aParent); 146 break; 147 case 7: 148 aChild = getAttributes( xText, aParent ); 149 break; 150 default: 151 aChild = new StringNode ("unknown child index " + nIndex, aParent); 152 } 153 } 154 } 155 catch (Exception e) 156 { 157 // Return empty child. 158 } 159 160 return aChild; 161 } 162 163 textAtIndexNodeString( int nStart, int nEnd, String sWord, String sBefore, String sBehind)164 private String textAtIndexNodeString( 165 int nStart, int nEnd, 166 String sWord, String sBefore, String sBehind) 167 { 168 return "[" + nStart + "," + nEnd + "] " 169 + "\"" + sWord + "\" \t" 170 + "(" + sBefore + "," 171 + "" + sBehind + ")"; 172 } 173 174 /** Create a text node that lists all strings of a particular text type 175 */ textAtIndexNode( XAccessibleText xText, String sName, short nTextType, AccessibleTreeNode aParent)176 private AccessibleTreeNode textAtIndexNode( 177 XAccessibleText xText, 178 String sName, 179 short nTextType, 180 AccessibleTreeNode aParent) 181 { 182 VectorNode aNode = new VectorNode (sName, aParent); 183 184 // get word at all positions; 185 // for nicer display, compare current word to previous one and 186 // make a new node for every interval, not for every word 187 int nLength = xText.getCharacterCount(); 188 if( nLength > 0 ) 189 { 190 try 191 { 192 // sWord + nStart mark the current word 193 // make a node as soon as a new one is found; close the last 194 // one at the end 195 TextSegment sWord = xText.getTextAtIndex(0, nTextType); 196 TextSegment sBefore = xText.getTextBeforeIndex(0, nTextType); 197 TextSegment sBehind = xText.getTextBehindIndex(0, nTextType); 198 int nStart = 0; 199 for(int i = 1; i < nLength; i++) 200 { 201 TextSegment sTmp = xText.getTextAtIndex(i, nTextType); 202 TextSegment sTBef = xText.getTextBeforeIndex(i, nTextType); 203 TextSegment sTBeh = xText.getTextBehindIndex(i, nTextType); 204 if( ! ( sTmp.equals( sWord ) && sTBef.equals( sBefore ) && 205 sTBeh.equals( sBehind ) ) ) 206 { 207 aNode.addChild (new StringNode (textAtIndexNodeString( 208 nStart, i, 209 sWord.SegmentText, sBefore.SegmentText, sBehind.SegmentText), aNode)); 210 sWord = sTmp; 211 sBefore = sTBef; 212 sBehind = sTBeh; 213 nStart = i; 214 } 215 216 // don't generate more than 50 children. 217 if (aNode.getChildCount() > 50) 218 { 219 sWord.SegmentText = "..."; 220 break; 221 } 222 } 223 aNode.addChild (new StringNode (textAtIndexNodeString( 224 nStart, nLength, 225 sWord.SegmentText, sBefore.SegmentText, sBehind.SegmentText), aNode)); 226 } 227 catch( IndexOutOfBoundsException e ) 228 { 229 aNode.addChild (new StringNode (e.toString(), aNode)); 230 } 231 catch (com.sun.star.lang.IllegalArgumentException e) 232 { 233 aNode.addChild (new StringNode (e.toString(), aNode)); 234 } 235 } 236 237 return aNode; 238 } 239 240 241 242 /** getCharacter (display as array string) */ characters(XAccessibleText xText)243 private String characters(XAccessibleText xText) 244 { 245 // get count (max. 30) 246 int nChars = xText.getCharacterCount(); 247 if( nChars > 30 ) 248 nChars = 30; 249 250 // build up string 251 StringBuilder aChars = new StringBuilder(); 252 try 253 { 254 aChars.append( "[" ); 255 for( int i = 0; i < nChars; i++) 256 { 257 aChars.append( xText.getCharacter(i) ); 258 aChars.append( "," ); 259 } 260 if( nChars > 0) 261 { 262 if( nChars == xText.getCharacterCount() ) 263 aChars.deleteCharAt( aChars.length() - 1 ); 264 else 265 aChars.append( "..." ); 266 } 267 aChars.append( "]" ); 268 } 269 catch( IndexOutOfBoundsException e ) 270 { 271 aChars.append( " ERROR " ); 272 } 273 274 // return result 275 return "getCharacters: " + aChars; 276 } 277 278 279 /** iterate over characters, and translate their positions 280 * back and forth */ bounds( XAccessibleText xText )281 private String bounds( XAccessibleText xText ) 282 { 283 StringBuilder aBuffer = new StringBuilder( "bounds: " ); 284 try 285 { 286 // iterate over characters 287 int nCount = xText.getCharacterCount(); 288 for(int i = 0; i < nCount; i++ ) 289 { 290 // get bounds for this character 291 Rectangle aRect = xText.getCharacterBounds( i ); 292 293 // get the character by 'clicking' into the middle of 294 // the bounds 295 Point aMiddle = new Point(); 296 aMiddle.X = aRect.X + (aRect.Width / 2) - 1; 297 aMiddle.Y = aRect.Y + (aRect.Height / 2 ) - 1; 298 int nIndex = xText.getIndexAtPoint( aMiddle ); 299 300 // get the character, or a '#' for an illegal index 301 if( (nIndex >= 0) && (nIndex < xText.getCharacter(i)) ) 302 aBuffer.append( xText.getCharacter(nIndex) ); 303 else 304 aBuffer.append( '#' ); 305 } 306 } 307 catch( IndexOutOfBoundsException e ) 308 { ; } // ignore errors 309 310 return aBuffer.toString(); 311 } 312 313 getAttributes( XAccessibleText xText, AccessibleTreeNode aParent)314 private AccessibleTreeNode getAttributes( XAccessibleText xText, 315 AccessibleTreeNode aParent) 316 { 317 String[] aAttributeList = new String[] { 318 "CharBackColor", 319 "CharColor", 320 "CharEscapement", 321 "CharHeight", 322 "CharPosture", 323 "CharStrikeout", 324 "CharUnderline", 325 "CharWeight", 326 "ParaAdjust", 327 "ParaBottomMargin", 328 "ParaFirstLineIndent", 329 "ParaLeftMargin", 330 "ParaLineSpacing", 331 "ParaRightMargin", 332 "ParaTabStops"}; 333 334 AccessibleTreeNode aRet; 335 336 try 337 { 338 VectorNode aPortions = new VectorNode ("getAttributes", aParent); 339 340 int nIndex = 0; 341 int nLength = xText.getCharacterCount(); 342 while( nIndex < nLength ) 343 { 344 // get attribute run 345 String aPortion = null; 346 try 347 { 348 aPortion = xText.getTextAtIndex( 349 nIndex, AccessibleTextType.ATTRIBUTE_RUN).SegmentText; 350 } 351 catch(com.sun.star.lang.IllegalArgumentException e) 352 { 353 aPortion = new String (""); 354 } 355 356 // get attributes and make node with attribute children 357 PropertyValue[] aValues = xText.getCharacterAttributes(nIndex, aAttributeList); 358 VectorNode aAttrs = new VectorNode (aPortion, aPortions); 359 for( int i = 0; i < aValues.length; i++ ) 360 { 361 new StringNode( aValues[i].Name + ": " + aValues[i].Value, 362 aAttrs ); 363 } 364 365 // get next portion, but advance at least one 366 nIndex += (aPortion.length() > 0) ? aPortion.length() : 1; 367 } 368 369 aRet = aPortions; 370 } 371 catch( IndexOutOfBoundsException e ) 372 { 373 aRet = new StringNode( "Exception caught:" + e, aParent ); 374 } 375 376 return aRet; 377 } 378 379 380 static String[] aTextActions = 381 new String[] { "select...", "copy..." }; 382 static String[] aEditableTextActions = 383 new String[] { "select...", "copy...", 384 "cut...", "paste...", "edit...", "format..." }; 385 getActions(AccessibleTreeNode aNode)386 public String[] getActions (AccessibleTreeNode aNode) 387 { 388 XAccessibleEditableText xEText = null; 389 if (aNode instanceof AccTreeNode) 390 xEText = ((AccTreeNode)aNode).getEditText (); 391 392 return (xEText == null) ? aTextActions : aEditableTextActions; 393 } 394 performAction(AccessibleTreeNode aNode, int nIndex)395 public void performAction (AccessibleTreeNode aNode, int nIndex) 396 { 397 if ( ! (aNode instanceof AccTreeNode)) 398 return; 399 400 AccTreeNode aATNode = (AccTreeNode)aNode; 401 TextActionDialog aDialog = null; 402 403 // create proper dialog 404 switch( nIndex ) 405 { 406 case 0: 407 aDialog = new TextActionDialog( aATNode, 408 "Select range:", 409 "select" ) 410 { 411 boolean action( 412 JTextComponent aText, AccTreeNode aNode ) 413 throws IndexOutOfBoundsException 414 { 415 return aNode.getText().setSelection( 416 getSelectionStart(), 417 getSelectionEnd() ); 418 } 419 }; 420 break; 421 case 1: 422 aDialog = new TextActionDialog( aATNode, 423 "Select range and copy:", 424 "copy" ) 425 { 426 boolean action( 427 JTextComponent aText, AccTreeNode aNode ) 428 throws IndexOutOfBoundsException 429 { 430 return aNode.getText().copyText( 431 getSelectionStart(), 432 getSelectionEnd() ); 433 } 434 }; 435 break; 436 case 2: 437 aDialog = new TextActionDialog( aATNode, 438 "Select range and cut:", 439 "cut" ) 440 { 441 boolean action( 442 JTextComponent aText, AccTreeNode aNode ) 443 throws IndexOutOfBoundsException 444 { 445 return aNode.getEditText().cutText( 446 getSelectionStart(), 447 getSelectionEnd() ); 448 } 449 }; 450 break; 451 case 3: 452 aDialog = new TextActionDialog( aATNode, 453 "Place Caret and paste:", 454 "paste" ) 455 { 456 boolean action( 457 JTextComponent aText, AccTreeNode aNode ) 458 throws IndexOutOfBoundsException 459 { 460 return aNode.getEditText().pasteText( 461 aText.getCaretPosition() ); 462 } 463 }; 464 break; 465 case 4: 466 aDialog = new TextEditDialog( aATNode, "Edit text:", 467 "edit" ); 468 break; 469 case 5: 470 aDialog = new TextAttributeDialog( aATNode ); 471 break; 472 } 473 474 if( aDialog != null ) 475 aDialog.show(); 476 } 477 478 } 479 480 /** 481 * Display a dialog with a text field and a pair of cancel/do-it buttons 482 */ 483 class TextActionDialog extends JDialog 484 implements ActionListener 485 { 486 AccTreeNode aNode; 487 JTextArea aText; 488 String sName; 489 JCheckBox aIndexToggle; 490 TextActionDialog( AccTreeNode aNd, String sExplanation, String sButtonText )491 public TextActionDialog( AccTreeNode aNd, 492 String sExplanation, 493 String sButtonText ) 494 { 495 super( AccessibilityWorkBench.Instance() ); 496 497 aNode = aNd; 498 sName = sButtonText; 499 init( sExplanation, aNode.getText().getText(), sButtonText ); 500 // setSize( getPreferredSize() ); 501 setSize( 350, 225 ); 502 } 503 504 /** build dialog */ init( String sExplanation, String sText, String sButtonText )505 protected void init( String sExplanation, 506 String sText, 507 String sButtonText ) 508 { 509 setTitle( sName ); 510 511 // vertical stacking of the elements 512 Container aContent = getContentPane(); 513 // aContent.setLayout( new BorderLayout() ); 514 515 // label with explanation 516 if( sExplanation.length() > 0 ) 517 aContent.add( new JLabel( sExplanation ), BorderLayout.NORTH ); 518 519 // the text field 520 aText = new JTextArea(); 521 aText.setText( sText ); 522 aText.setColumns( Math.min( Math.max( 40, sText.length() ), 20 ) ); 523 aText.setRows( sText.length() / 40 + 1 ); 524 aText.setLineWrap( true ); 525 aText.setEditable( false ); 526 aContent.add( aText, BorderLayout.CENTER ); 527 528 JPanel aButtons = new JPanel(); 529 aButtons.setLayout( new FlowLayout() ); 530 aIndexToggle = new JCheckBox( "reverse selection" ); 531 aButtons.add( aIndexToggle ); 532 JButton aActionButton = new JButton( sButtonText ); 533 aActionButton.setActionCommand( "Action" ); 534 aActionButton.addActionListener( this ); 535 aButtons.add( aActionButton ); 536 JButton aCancelButton = new JButton( "cancel" ); 537 aCancelButton.setActionCommand( "Cancel" ); 538 aCancelButton.addActionListener( this ); 539 aButtons.add( aCancelButton ); 540 541 // add Panel with buttons 542 aContent.add( aButtons, BorderLayout.SOUTH ); 543 } 544 cancel()545 void cancel() 546 { 547 hide(); 548 dispose(); 549 } 550 action()551 void action() 552 { 553 String sError = null; 554 try 555 { 556 boolean bSuccess = action( aText, aNode ); 557 if( !bSuccess ) 558 sError = "Can't execute"; 559 } 560 catch( IndexOutOfBoundsException e ) 561 { 562 sError = "Index out of bounds"; 563 } 564 565 if( sError != null ) 566 JOptionPane.showMessageDialog( AccessibilityWorkBench.Instance(), 567 sError, sName, 568 JOptionPane.ERROR_MESSAGE); 569 570 cancel(); 571 } 572 actionPerformed(ActionEvent e)573 public void actionPerformed(ActionEvent e) 574 { 575 String sCommand = e.getActionCommand(); 576 577 if( "Cancel".equals( sCommand ) ) 578 cancel(); 579 else if( "Action".equals( sCommand ) ) 580 action(); 581 } 582 583 getSelectionStart()584 int getSelectionStart() { return getSelection(true); } getSelectionEnd()585 int getSelectionEnd() { return getSelection(false); } getSelection(boolean bStart)586 int getSelection(boolean bStart) 587 { 588 return ( bStart ^ aIndexToggle.isSelected() ) 589 ? aText.getSelectionStart() : aText.getSelectionEnd(); 590 } 591 592 593 594 /** override this for dialog-specific action */ action( JTextComponent aText, AccTreeNode aNode )595 boolean action( JTextComponent aText, AccTreeNode aNode ) 596 throws IndexOutOfBoundsException 597 { 598 return false; 599 } 600 } 601 602 603 class TextEditDialog extends TextActionDialog 604 { TextEditDialog( AccTreeNode aNode, String sExplanation, String sButtonText )605 public TextEditDialog( AccTreeNode aNode, 606 String sExplanation, 607 String sButtonText ) 608 { 609 super( aNode, sExplanation, sButtonText ); 610 } 611 init( String sExplanation, String sText, String sButtonText )612 protected void init( String sExplanation, 613 String sText, 614 String sButtonText ) 615 { 616 super.init( sExplanation, sText, sButtonText ); 617 aText.setEditable( true ); 618 } 619 620 621 /** edit the text */ action( JTextComponent aText, AccTreeNode aNode )622 boolean action( JTextComponent aText, AccTreeNode aNode ) 623 { 624 // is this text editable? if not, fudge you and return 625 XAccessibleEditableText xEdit = aNode.getEditText(); 626 return ( xEdit == null ) ? false : 627 updateText( xEdit, aText.getText() ); 628 } 629 630 631 /** update the text */ updateText( XAccessibleEditableText xEdit, String sNew )632 boolean updateText( XAccessibleEditableText xEdit, String sNew ) 633 { 634 String sOld = xEdit.getText(); 635 636 // false alarm? Early out if no change was done! 637 if( sOld.equals( sNew ) ) 638 return false; 639 640 // get the minimum length of both strings 641 int nMinLength = sOld.length(); 642 if( sNew.length() < nMinLength ) 643 nMinLength = sNew.length(); 644 645 // count equal characters from front and end 646 int nFront = 0; 647 while( (nFront < nMinLength) && 648 (sNew.charAt(nFront) == sOld.charAt(nFront)) ) 649 nFront++; 650 int nBack = 0; 651 while( (nBack < nMinLength) && 652 ( sNew.charAt(sNew.length()-nBack-1) == 653 sOld.charAt(sOld.length()-nBack-1) ) ) 654 nBack++; 655 if( nFront + nBack > nMinLength ) 656 nBack = nMinLength - nFront; 657 658 // so... the first nFront and the last nBack characters 659 // are the same. Change the others! 660 String sDel = sOld.substring( nFront, sOld.length() - nBack ); 661 String sIns = sNew.substring( nFront, sNew.length() - nBack ); 662 663 System.out.println("edit text: " + 664 sOld.substring(0, nFront) + 665 " [ " + sDel + " -> " + sIns + " ] " + 666 sOld.substring(sOld.length() - nBack) ); 667 668 boolean bRet = false; 669 try 670 { 671 // edit the text, and use 672 // (set|insert|delete|replace)Text as needed 673 if( nFront+nBack == 0 ) 674 bRet = xEdit.setText( sIns ); 675 else if( sDel.length() == 0 ) 676 bRet = xEdit.insertText( sIns, nFront ); 677 else if( sIns.length() == 0 ) 678 bRet = xEdit.deleteText( nFront, sOld.length()-nBack ); 679 else 680 bRet = xEdit.replaceText(nFront, sOld.length()-nBack,sIns); 681 } 682 catch( IndexOutOfBoundsException e ) 683 { 684 bRet = false; 685 } 686 687 return bRet; 688 } 689 } 690 691 692 class TextAttributeDialog extends TextActionDialog 693 { TextAttributeDialog( AccTreeNode aNode )694 public TextAttributeDialog( 695 AccTreeNode aNode ) 696 { 697 super( aNode, "Choose attributes, select text, and press 'Set':", 698 "set" ); 699 } 700 701 private JCheckBox aBold, aUnderline, aItalics; 702 private Color aForeground, aBackground; 703 init( String sExplanation, String sText, String sButtonText )704 protected void init( String sExplanation, 705 String sText, 706 String sButtonText ) 707 { 708 super.init( sExplanation, sText, sButtonText ); 709 710 aForeground = Color.black; 711 aBackground = Color.white; 712 713 JPanel aAttr = new JPanel(); 714 aAttr.setLayout( new BoxLayout( aAttr, BoxLayout.Y_AXIS ) ); 715 716 aBold = new JCheckBox( "bold" ); 717 aUnderline = new JCheckBox( "underline" ); 718 aItalics = new JCheckBox( "italics" ); 719 720 JButton aForeButton = new JButton("Foreground", new ColorIcon(true)); 721 aForeButton.addActionListener( new ActionListener() { 722 public void actionPerformed(ActionEvent e) 723 { 724 aForeground = JColorChooser.showDialog( 725 TextAttributeDialog.this, 726 "Select Foreground Color", 727 aForeground); 728 } 729 } ); 730 731 JButton aBackButton = new JButton("Background", new ColorIcon(false)); 732 aBackButton.addActionListener( new ActionListener() { 733 public void actionPerformed(ActionEvent e) 734 { 735 aBackground = JColorChooser.showDialog( 736 TextAttributeDialog.this, 737 "Select Background Color", 738 aBackground); 739 } 740 } ); 741 742 aAttr.add( aBold ); 743 aAttr.add( aUnderline ); 744 aAttr.add( aItalics ); 745 aAttr.add( aForeButton ); 746 aAttr.add( aBackButton ); 747 748 getContentPane().add( aAttr, BorderLayout.WEST ); 749 } 750 751 752 class ColorIcon implements Icon 753 { 754 boolean bForeground; 755 static final int nHeight = 16; 756 static final int nWidth = 16; 757 ColorIcon(boolean bWhich)758 public ColorIcon(boolean bWhich) { bForeground = bWhich; } getIconHeight()759 public int getIconHeight() { return nHeight; } getIconWidth()760 public int getIconWidth() { return nWidth; } paintIcon(Component c, Graphics g, int x, int y)761 public void paintIcon(Component c, Graphics g, int x, int y) 762 { 763 g.setColor( getColor() ); 764 g.fillRect( x, y, nHeight, nWidth ); 765 g.setColor( c.getForeground() ); 766 g.drawRect( x, y, nHeight, nWidth ); 767 } getColor()768 Color getColor() 769 { 770 return bForeground ? aForeground : aBackground; 771 } 772 } 773 774 775 776 /** edit the text */ action( JTextComponent aText, AccTreeNode aNode )777 boolean action( JTextComponent aText, AccTreeNode aNode ) 778 throws IndexOutOfBoundsException 779 { 780 // is this text editable? if not, fudge you and return 781 XAccessibleEditableText xEdit = aNode.getEditText(); 782 boolean bSuccess = false; 783 if( xEdit != null ) 784 { 785 PropertyValue[] aSequence = new PropertyValue[6]; 786 aSequence[0] = new PropertyValue(); 787 aSequence[0].Name = "CharWeight"; 788 aSequence[0].Value = new Integer( aBold.isSelected() ? 150 : 100 ); 789 aSequence[1] = new PropertyValue(); 790 aSequence[1].Name = "CharUnderline"; 791 aSequence[1].Value = new Integer( aUnderline.isSelected() ? 1 : 0 ); 792 aSequence[2] = new PropertyValue(); 793 aSequence[2].Name = "CharBackColor"; 794 aSequence[2].Value = new Integer( aBackground.getRGB() ); 795 aSequence[3] = new PropertyValue(); 796 aSequence[3].Name = "CharColor"; 797 aSequence[3].Value = new Integer( aForeground.getRGB() ); 798 aSequence[4] = new PropertyValue(); 799 aSequence[4].Name = "CharPosture"; 800 aSequence[4].Value = new Integer( aItalics.isSelected() ? 1 : 0 ); 801 aSequence[5] = new PropertyValue(); 802 aSequence[5].Name = "CharBackTransparent"; 803 aSequence[5].Value = new Boolean( false ); 804 805 bSuccess = xEdit.setAttributes( getSelectionStart(), 806 getSelectionEnd(), 807 aSequence ); 808 } 809 return bSuccess; 810 } 811 812 } 813