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