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