Java Tutorial/SWT/StyledText

Материал из Java эксперт
Перейти к: навигация, поиск

A simple editor

   <source lang="java">

//Code revised from /* The Definitive Guide to SWT and JFace by Robert Harris and Rob Warner Apress 2004

  • /

import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; import java.util.Hashtable; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.MissingResourceException; import java.util.ResourceBundle; import java.util.Stack; import java.util.StringTokenizer; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.ExtendedModifyEvent; import org.eclipse.swt.custom.ExtendedModifyListener; import org.eclipse.swt.custom.LineStyleEvent; import org.eclipse.swt.custom.LineStyleListener; import org.eclipse.swt.custom.ST; import org.eclipse.swt.custom.StyleRange; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.custom.StyledTextPrintOptions; import org.eclipse.swt.events.ArmEvent; import org.eclipse.swt.events.ArmListener; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.printing.Printer; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.widgets.MessageBox; import org.eclipse.swt.widgets.Shell; public class PmpEditor {

 // The number of operations that can be undone
 private static final int UNDO_LIMIT = 500;
 // Contains a reference to this application
 private static PmpEditor app;
 // Contains a reference to the main window
 private Shell shell;
 // Displays the file
 private StyledText st;
 // The full path of the current file
 private String filename;
 // The font for the StyledText
 private Font font;
 // The label to display statistics
 private Label status;
 // The print options and printer
 private StyledTextPrintOptions options;
 private Printer printer;
 // The stack used to store the undo information
 private Stack changes;
 // Flag to set before performaing an undo, so the undo
 // operation doesn"t get stored with the rest of the undo
 // information
 private boolean ignoreUndo = false;
 // Syntax data for the current extension
 private SyntaxData sd;
 // Line style listener
 private PmpeLineStyleListener lineStyleListener;
 /**
  * Gets the reference to this application
  * 
  * @return HexEditor
  */
 public static PmpEditor getApp() {
   return app;
 }
 /**
  * Constructs a PmpEditor
  */
 public PmpEditor() {
   app = this;
   changes = new Stack();
   // Set up the printing options
   options = new StyledTextPrintOptions();
   options.footer = StyledTextPrintOptions.SEPARATOR + StyledTextPrintOptions.PAGE_TAG
       + StyledTextPrintOptions.SEPARATOR + "Confidential";
 }
 /**
  * Runs the application
  */
 public void run() {
   Display display = new Display();
   shell = new Shell(display);
   // Choose a monospaced font
   font = new Font(display, "Terminal", 12, SWT.NONE);
   createContents(shell);
   shell.open();
   while (!shell.isDisposed()) {
     if (!display.readAndDispatch()) {
       display.sleep();
     }
   }
   font.dispose();
   display.dispose();
   if (printer != null)
     printer.dispose();
 }
 /**
  * Creates the main window"s contents
  * 
  * @param shell
  *          the main window
  */
 private void createContents(Shell shell) {
   // Set the layout and the menu bar
   shell.setLayout(new FormLayout());
   shell.setMenuBar(new PmpEditorMenu(shell).getMenu());
   // Create the status bar
   status = new Label(shell, SWT.BORDER);
   FormData data = new FormData();
   data.left = new FormAttachment(0, 0);
   data.right = new FormAttachment(100, 0);
   data.bottom = new FormAttachment(100, 0);
   data.height = status.ruputeSize(SWT.DEFAULT, SWT.DEFAULT).y;
   status.setLayoutData(data);
   // Create the styled text
   st = new StyledText(shell, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
   data = new FormData();
   data.left = new FormAttachment(0);
   data.right = new FormAttachment(100);
   data.top = new FormAttachment(0);
   data.bottom = new FormAttachment(status);
   st.setLayoutData(data);
   // Set the font
   st.setFont(font);
   // Add Brief delete next word
   // Use SWT.MOD1 instead of SWT.CTRL for portability
   st.setKeyBinding("k" | SWT.MOD1, ST.DELETE_NEXT);
   // Add vi end of line (kind of)
   // Use SWT.MOD1 instead of SWT.CTRL for portability
   // Use SWT.MOD2 instead of SWT.SHIFT for portability
   // Shift+4 is $
   st.setKeyBinding("4" | SWT.MOD1 | SWT.MOD2, ST.LINE_END);
   // Handle key presses
   st.addKeyListener(new KeyAdapter() {
     public void keyPressed(KeyEvent event) {
       // Update the status bar
       updateStatus();
     }
   });
   // Handle text modifications
   st.addModifyListener(new ModifyListener() {
     public void modifyText(ModifyEvent event) {
       // Update the status bar
       updateStatus();
       // Update the comments
       if (lineStyleListener != null) {
         lineStyleListener.refreshMultilineComments(st.getText());
         st.redraw();
       }
     }
   });
   // Store undo information
   st.addExtendedModifyListener(new ExtendedModifyListener() {
     public void modifyText(ExtendedModifyEvent event) {
       if (!ignoreUndo) {
         // Push this change onto the changes stack
         changes.push(new TextChange(event.start, event.length, event.replacedText));
         if (changes.size() > UNDO_LIMIT)
           changes.remove(0);
       }
     }
   });
   // Update the title bar and the status bar
   updateTitle();
   updateStatus();
 }
 /**
  * Opens a file
  */
 public void openFile() {
   FileDialog dlg = new FileDialog(shell);
   String temp = dlg.open();
   if (temp != null) {
     try {
       // Get the file"s contents
       String text = PmpeIoManager.getFile(temp);
       // File loaded, so save the file name
       filename = temp;
       // Update the syntax properties to use
       updateSyntaxData();
       // Put the new file"s data in the StyledText
       st.setText(text);
       // Update the title bar
       updateTitle();
       // Delete any undo information
       changes.clear();
     } catch (IOException e) {
       showError(e.getMessage());
     }
   }
 }
 /**
  * Saves a file
  */
 public void saveFile() {
   if (filename == null) {
     saveFileAs();
   } else {
     try {
       // Save the file and update the title bar based on the new file name
       PmpeIoManager.saveFile(filename, st.getText().getBytes());
       updateTitle();
     } catch (IOException e) {
       showError(e.getMessage());
     }
   }
 }
 /**
  * Saves a file under a different name
  */
 public void saveFileAs() {
   FileDialog dlg = new FileDialog(shell);
   if (filename != null) {
     dlg.setFileName(filename);
   }
   String temp = dlg.open();
   if (temp != null) {
     filename = temp;
     // The extension may have changed; update the syntax data accordingly
     updateSyntaxData();
     saveFile();
   }
 }
 /**
  * Prints the document to the default printer
  */
 public void print() {
   if (printer == null)
     printer = new Printer();
   options.header = StyledTextPrintOptions.SEPARATOR + filename + StyledTextPrintOptions.SEPARATOR;
   st.print(printer, options).run();
 }
 /**
  * Cuts the current selection to the clipboard
  */
 public void cut() {
   st.cut();
 }
 /**
  * Copies the current selection to the clipboard
  */
 public void copy() {
   st.copy();
 }
 /**
  * Pastes the clipboard"s contents
  */
 public void paste() {
   st.paste();
 }
 /**
  * Selects all the text
  */
 public void selectAll() {
   st.selectAll();
 }
 /**
  * Undoes the last change
  */
 public void undo() {
   // Make sure undo stack isn"t empty
   if (!changes.empty()) {
     // Get the last change
     TextChange change = (TextChange) changes.pop();
     // Set the flag. Otherwise, the replaceTextRange call will get placed
     // on the undo stack
     ignoreUndo = true;
     // Replace the changed text
     st.replaceTextRange(change.getStart(), change.getLength(), change.getReplacedText());
     // Move the caret
     st.setCaretOffset(change.getStart());
     // Scroll the screen
     st.setTopIndex(st.getLineAtOffset(change.getStart()));
     ignoreUndo = false;
   }
 }
 /**
  * Toggles word wrap
  */
 public void toggleWordWrap() {
   st.setWordWrap(!st.getWordWrap());
 }
 /**
  * Gets the current word wrap settings
  * 
  * @return boolean
  */
 public boolean getWordWrap() {
   return st.getWordWrap();
 }
 /**
  * Shows an about box
  */
 public void about() {
   MessageBox mb = new MessageBox(shell, SWT.ICON_INFORMATION | SWT.OK);
   mb.setMessage("Poor Man"s Programming Editor");
   mb.open();
 }
 /**
  * Updates the title bar
  */
 private void updateTitle() {
   String fn = filename == null ? "Untitled" : filename;
   shell.setText(fn + " -- PmPe");
 }
 /**
  * Updates the status bar
  */
 private void updateStatus() {
   // Show the offset into the file, the total number of characters in the
   // file,
   // the current line number (1-based) and the total number of lines
   StringBuffer buf = new StringBuffer();
   buf.append("Offset: ");
   buf.append(st.getCaretOffset());
   buf.append("\tChars: ");
   buf.append(st.getCharCount());
   buf.append("\tLine: ");
   buf.append(st.getLineAtOffset(st.getCaretOffset()) + 1);
   buf.append(" of ");
   buf.append(st.getLineCount());
   status.setText(buf.toString());
 }
 /**
  * Updates the syntax data based on the filename"s extension
  */
 private void updateSyntaxData() {
   // Determine the extension of the current file
   String extension = "";
   if (filename != null) {
     int pos = filename.lastIndexOf(".");
     if (pos > -1 && pos < filename.length() - 2) {
       extension = filename.substring(pos + 1);
     }
   }
   // Get the syntax data for the extension
   sd = SyntaxManager.getSyntaxData(extension);
   // Reset the line style listener
   if (lineStyleListener != null) {
     st.removeLineStyleListener(lineStyleListener);
   }
   lineStyleListener = new PmpeLineStyleListener(sd);
   st.addLineStyleListener(lineStyleListener);
   // Redraw the contents to reflect the new syntax data
   st.redraw();
 }
 /**
  * Shows an error message
  * 
  * @param error
  *          the text to show
  */
 private void showError(String error) {
   MessageBox mb = new MessageBox(shell, SWT.ICON_ERROR | SWT.OK);
   mb.setMessage(error);
   mb.open();
 }
 /**
  * The application entry point
  * 
  * @param args
  *          the command line arguments
  */
 public static void main(String[] args) {
   new PmpEditor().run();
 }

} class PmpEditorMenu {

 // The underlying menu this class wraps
 Menu menu = null;
 /**
  * Constructs a PmpEditorMenu
  * 
  * @param shell
  *          the parent shell
  */
 public PmpEditorMenu(final Shell shell) {
   // Create the menu
   menu = new Menu(shell, SWT.BAR);
   // Create the File top-level menu
   MenuItem item = new MenuItem(menu, SWT.CASCADE);
   item.setText("File");
   Menu dropMenu = new Menu(shell, SWT.DROP_DOWN);
   item.setMenu(dropMenu);
   // Create File->Open
   item = new MenuItem(dropMenu, SWT.NULL);
   item.setText("Open...\tCtrl+O");
   item.setAccelerator(SWT.CTRL + "O");
   item.addSelectionListener(new SelectionAdapter() {
     public void widgetSelected(SelectionEvent event) {
       PmpEditor.getApp().openFile();
     }
   });
   // Create File->Save
   item = new MenuItem(dropMenu, SWT.NULL);
   item.setText("Save\tCtrl+S");
   item.setAccelerator(SWT.CTRL + "S");
   item.addSelectionListener(new SelectionAdapter() {
     public void widgetSelected(SelectionEvent event) {
       PmpEditor.getApp().saveFile();
     }
   });
   // Create File->Save As
   item = new MenuItem(dropMenu, SWT.NULL);
   item.setText("Save As...");
   item.addSelectionListener(new SelectionAdapter() {
     public void widgetSelected(SelectionEvent event) {
       PmpEditor.getApp().saveFileAs();
     }
   });
   new MenuItem(dropMenu, SWT.SEPARATOR);
   // Create File->Print
   item = new MenuItem(dropMenu, SWT.NULL);
   item.setText("Print\tCtrl+P");
   item.setAccelerator(SWT.CTRL + "P");
   item.addSelectionListener(new SelectionAdapter() {
     public void widgetSelected(SelectionEvent event) {
       PmpEditor.getApp().print();
     }
   });
   new MenuItem(dropMenu, SWT.SEPARATOR);
   // Create File->Exit
   item = new MenuItem(dropMenu, SWT.NULL);
   item.setText("Exit\tAlt+F4");
   item.addSelectionListener(new SelectionAdapter() {
     public void widgetSelected(SelectionEvent event) {
       shell.close();
     }
   });
   // Create Edit
   item = new MenuItem(menu, SWT.CASCADE);
   item.setText("Edit");
   dropMenu = new Menu(shell, SWT.DROP_DOWN);
   item.setMenu(dropMenu);
   // Create Edit->Cut
   item = new MenuItem(dropMenu, SWT.NULL);
   item.setText("Cut\tCtrl+X");
   item.setAccelerator(SWT.CTRL + "X");
   item.addSelectionListener(new SelectionAdapter() {
     public void widgetSelected(SelectionEvent event) {
       PmpEditor.getApp().cut();
     }
   });
   // Create Edit->Copy
   item = new MenuItem(dropMenu, SWT.NULL);
   item.setText("Copy\tCtrl+C");
   item.setAccelerator(SWT.CTRL + "C");
   item.addSelectionListener(new SelectionAdapter() {
     public void widgetSelected(SelectionEvent event) {
       PmpEditor.getApp().copy();
     }
   });
   // Create Edit->Paste
   item = new MenuItem(dropMenu, SWT.NULL);
   item.setText("Paste\tCtrl+V");
   item.setAccelerator(SWT.CTRL + "V");
   item.addSelectionListener(new SelectionAdapter() {
     public void widgetSelected(SelectionEvent event) {
       PmpEditor.getApp().paste();
     }
   });
   new MenuItem(dropMenu, SWT.SEPARATOR);
   // Create Select All
   item = new MenuItem(dropMenu, SWT.NULL);
   item.setText("Select All\tCtrl+A");
   item.setAccelerator(SWT.CTRL + "A");
   item.addSelectionListener(new SelectionAdapter() {
     public void widgetSelected(SelectionEvent event) {
       PmpEditor.getApp().selectAll();
     }
   });
   new MenuItem(dropMenu, SWT.SEPARATOR);
   // Create Undo
   item = new MenuItem(dropMenu, SWT.NULL);
   item.setText("Undo\tCtrl+Z");
   item.setAccelerator(SWT.CTRL + "Z");
   item.addSelectionListener(new SelectionAdapter() {
     public void widgetSelected(SelectionEvent event) {
       PmpEditor.getApp().undo();
     }
   });
   new MenuItem(dropMenu, SWT.SEPARATOR);
   // Create Word Wrap
   final MenuItem wwItem = new MenuItem(dropMenu, SWT.CHECK);
   wwItem.setText("Word Wrap\tCtrl+W");
   wwItem.setAccelerator(SWT.CTRL + "W");
   wwItem.addSelectionListener(new SelectionAdapter() {
     public void widgetSelected(SelectionEvent event) {
       PmpEditor.getApp().toggleWordWrap();
     }
   });
   wwItem.addArmListener(new ArmListener() {
     public void widgetArmed(ArmEvent event) {
       wwItem.setSelection(PmpEditor.getApp().getWordWrap());
     }
   });
   // Create Help
   item = new MenuItem(menu, SWT.CASCADE);
   item.setText("Help");
   dropMenu = new Menu(shell, SWT.DROP_DOWN);
   item.setMenu(dropMenu);
   // Create Help->About
   item = new MenuItem(dropMenu, SWT.NULL);
   item.setText("About\tCtrl+A");
   item.setAccelerator(SWT.CTRL + "A");
   item.addSelectionListener(new SelectionAdapter() {
     public void widgetSelected(SelectionEvent event) {
       PmpEditor.getApp().about();
     }
   });
 }
 /**
  * Gets the underlying menu
  * 
  * @return Menu
  */
 public Menu getMenu() {
   return menu;
 }

} class PmpeIoManager {

 /**
  * Gets a file (loads it) from the filesystem
  * 
  * @param filename
  *          the full path of the file
  * @return String
  * @throws IOException
  *           if file cannot be loaded
  */
 public static String getFile(String filename) throws IOException {
   InputStream in = new BufferedInputStream(new FileInputStream(filename));
   StringBuffer buf = new StringBuffer();
   int c;
   while ((c = in.read()) != -1) {
     buf.append((char) c);
   }
   return buf.toString();
 }
 /**
  * Saves a file
  * 
  * @param filename
  *          the full path of the file to save
  * @param data
  *          the data to save
  * @throws IOException
  *           if file cannot be saved
  */
 public static void saveFile(String filename, byte[] data) throws IOException {
   File outputFile = new File(filename);
   FileOutputStream out = new FileOutputStream(outputFile);
   out.write(data);
   out.close();
 }

} class TextChange {

 // The starting offset of the change
 private int start;
 // The length of the change
 private int length;
 // The replaced text
 String replacedText;
 /**
  * Constructs a TextChange
  * 
  * @param start
  *          the starting offset of the change
  * @param length
  *          the length of the change
  * @param replacedText
  *          the text that was replaced
  */
 public TextChange(int start, int length, String replacedText) {
   this.start = start;
   this.length = length;
   this.replacedText = replacedText;
 }
 /**
  * Returns the start
  * 
  * @return int
  */
 public int getStart() {
   return start;
 }
 /**
  * Returns the length
  * 
  * @return int
  */
 public int getLength() {
   return length;
 }
 /**
  * Returns the replacedText
  * 
  * @return String
  */
 public String getReplacedText() {
   return replacedText;
 }

} /**

* This class contains information for syntax coloring and styling for an
* extension
*/

class SyntaxData {

 private String extension;
 private Collection keywords;
 private String punctuation;
 private String comment;
 private String multiLineCommentStart;
 private String multiLineCommentEnd;
 /**
  * Constructs a SyntaxData
  * 
  * @param extension
  *          the extension
  */
 public SyntaxData(String extension) {
   this.extension = extension;
 }
 /**
  * Gets the extension
  * 
  * @return String
  */
 public String getExtension() {
   return extension;
 }
 /**
  * Gets the comment
  * 
  * @return String
  */
 public String getComment() {
   return comment;
 }
 /**
  * Sets the comment
  * 
  * @param comment
  *          The comment to set.
  */
 public void setComment(String comment) {
   this.rument = comment;
 }
 /**
  * Gets the keywords
  * 
  * @return Collection
  */
 public Collection getKeywords() {
   return keywords;
 }
 /**
  * Sets the keywords
  * 
  * @param keywords
  *          The keywords to set.
  */
 public void setKeywords(Collection keywords) {
   this.keywords = keywords;
 }
 /**
  * Gets the multiline comment end
  * 
  * @return String
  */
 public String getMultiLineCommentEnd() {
   return multiLineCommentEnd;
 }
 /**
  * Sets the multiline comment end
  * 
  * @param multiLineCommentEnd
  *          The multiLineCommentEnd to set.
  */
 public void setMultiLineCommentEnd(String multiLineCommentEnd) {
   this.multiLineCommentEnd = multiLineCommentEnd;
 }
 /**
  * Gets the multiline comment start
  * 
  * @return String
  */
 public String getMultiLineCommentStart() {
   return multiLineCommentStart;
 }
 /**
  * Sets the multiline comment start
  * 
  * @param multiLineCommentStart
  *          The multiLineCommentStart to set.
  */
 public void setMultiLineCommentStart(String multiLineCommentStart) {
   this.multiLineCommentStart = multiLineCommentStart;
 }
 /**
  * Gets the punctuation
  * 
  * @return String
  */
 public String getPunctuation() {
   return punctuation;
 }
 /**
  * Sets the punctuation
  * 
  * @param punctuation
  *          The punctuation to set.
  */
 public void setPunctuation(String punctuation) {
   this.punctuation = punctuation;
 }

} /**

* This class manages the syntax coloring and styling data
*/

class SyntaxManager {

 // Lazy cache of SyntaxData objects
 private static Map data = new Hashtable();
 /**
  * Gets the syntax data for an extension
  */
 public static synchronized SyntaxData getSyntaxData(String extension) {
   // Check in cache
   SyntaxData sd = (SyntaxData) data.get(extension);
   if (sd == null) {
     // Not in cache; load it and put in cache
     sd = loadSyntaxData(extension);
     if (sd != null)
       data.put(sd.getExtension(), sd);
   }
   return sd;
 }
 /**
  * Loads the syntax data for an extension
  * 
  * @param extension
  *          the extension to load
  * @return SyntaxData
  */
 private static SyntaxData loadSyntaxData(String extension) {
   SyntaxData sd = null;
   try {
     ResourceBundle rb = ResourceBundle.getBundle("examples.ch11." + extension);
     sd = new SyntaxData(extension);
     sd.setComment(rb.getString("comment"));
     sd.setMultiLineCommentStart(rb.getString("multilinecommentstart"));
     sd.setMultiLineCommentEnd(rb.getString("multilinecommentend"));
     // Load the keywords
     Collection keywords = new ArrayList();
     for (StringTokenizer st = new StringTokenizer(rb.getString("keywords"), " "); st
         .hasMoreTokens();) {
       keywords.add(st.nextToken());
     }
     sd.setKeywords(keywords);
     // Load the punctuation
     sd.setPunctuation(rb.getString("punctuation"));
   } catch (MissingResourceException e) {
     // Ignore
   }
   return sd;
 }

} /**

* This class performs the syntax highlighting and styling for Pmpe
*/

class PmpeLineStyleListener implements LineStyleListener {

 // Colors
 private static final Color COMMENT_COLOR = Display.getCurrent().getSystemColor(
     SWT.COLOR_DARK_GREEN);
 private static final Color COMMENT_BACKGROUND = Display.getCurrent().getSystemColor(
     SWT.COLOR_GRAY);
 private static final Color PUNCTUATION_COLOR = Display.getCurrent().getSystemColor(
     SWT.COLOR_DARK_CYAN);
 private static final Color KEYWORD_COLOR = Display.getCurrent().getSystemColor(
     SWT.COLOR_DARK_MAGENTA);
 // Holds the syntax data
 private SyntaxData syntaxData;
 // Holds the offsets for all multiline comments
 List commentOffsets;
 /**
  * PmpeLineStyleListener constructor
  * 
  * @param syntaxData
  *          the syntax data to use
  */
 public PmpeLineStyleListener(SyntaxData syntaxData) {
   this.syntaxData = syntaxData;
   commentOffsets = new LinkedList();
 }
 /**
  * Refreshes the offsets for all multiline comments in the parent StyledText.
  * The parent StyledText should call this whenever its text is modified. Note
  * that this code doesn"t ignore comment markers inside strings.
  * 
  * @param text
  *          the text from the StyledText
  */
 public void refreshMultilineComments(String text) {
   // Clear any stored offsets
   commentOffsets.clear();
   if (syntaxData != null) {
     // Go through all the instances of COMMENT_START
     for (int pos = text.indexOf(syntaxData.getMultiLineCommentStart()); pos > -1; pos = text
         .indexOf(syntaxData.getMultiLineCommentStart(), pos)) {
       // offsets[0] holds the COMMENT_START offset
       // and COMMENT_END holds the ending offset
       int[] offsets = new int[2];
       offsets[0] = pos;
       // Find the corresponding end comment.
       pos = text.indexOf(syntaxData.getMultiLineCommentEnd(), pos);
       // If no corresponding end comment, use the end of the text
       offsets[1] = pos == -1 ? text.length() - 1 : pos
           + syntaxData.getMultiLineCommentEnd().length() - 1;
       pos = offsets[1];
       // Add the offsets to the collection
       commentOffsets.add(offsets);
     }
   }
 }
 /**
  * Checks to see if the specified section of text begins inside a multiline
  * comment. Returns the index of the closing comment, or the end of the line
  * if the whole line is inside the comment. Returns -1 if the line doesn"t
  * begin inside a comment.
  * 
  * @param start
  *          the starting offset of the text
  * @param length
  *          the length of the text
  * @return int
  */
 private int getBeginsInsideComment(int start, int length) {
   // Assume section doesn"t being inside a comment
   int index = -1;
   // Go through the multiline comment ranges
   for (int i = 0, n = commentOffsets.size(); i < n; i++) {
     int[] offsets = (int[]) commentOffsets.get(i);
     // If starting offset is past range, quit
     if (offsets[0] > start + length)
       break;
     // Check to see if section begins inside a comment
     if (offsets[0] <= start && offsets[1] >= start) {
       // It does; determine if the closing comment marker is inside
       // this section
       index = offsets[1] > start + length ? start + length : offsets[1]
           + syntaxData.getMultiLineCommentEnd().length() - 1;
     }
   }
   return index;
 }
 /**
  * Called by StyledText to get styles for a line
  */
 public void lineGetStyle(LineStyleEvent event) {
   // Only do styles if syntax data has been loaded
   if (syntaxData != null) {
     // Create collection to hold the StyleRanges
     List styles = new ArrayList();
     int start = 0;
     int length = event.lineText.length();
     // Check if line begins inside a multiline comment
     int mlIndex = getBeginsInsideComment(event.lineOffset, event.lineText.length());
     if (mlIndex > -1) {
       // Line begins inside multiline comment; create the range
       styles.add(new StyleRange(event.lineOffset, mlIndex - event.lineOffset, COMMENT_COLOR,
           COMMENT_BACKGROUND));
       start = mlIndex;
     }
     // Do punctuation, single-line comments, and keywords
     while (start < length) {
       // Check for multiline comments that begin inside this line
       if (event.lineText.indexOf(syntaxData.getMultiLineCommentStart(), start) == start) {
         // Determine where comment ends
         int endComment = event.lineText.indexOf(syntaxData.getMultiLineCommentEnd(), start);
         // If comment doesn"t end on this line, extend range to end of line
         if (endComment == -1)
           endComment = length;
         else
           endComment += syntaxData.getMultiLineCommentEnd().length();
         styles.add(new StyleRange(event.lineOffset + start, endComment - start, COMMENT_COLOR,
             COMMENT_BACKGROUND));
         // Move marker
         start = endComment;
       }
       // Check for single line comments
       else if (event.lineText.indexOf(syntaxData.getComment(), start) == start) {
         // Comment rest of line
         styles.add(new StyleRange(event.lineOffset + start, length - start, COMMENT_COLOR,
             COMMENT_BACKGROUND));
         // Move marker
         start = length;
       }
       // Check for punctuation
       else if (syntaxData.getPunctuation().indexOf(event.lineText.charAt(start)) > -1) {
         // Add range for punctuation
         styles.add(new StyleRange(event.lineOffset + start, 1, PUNCTUATION_COLOR, null));
         ++start;
       } else if (Character.isLetter(event.lineText.charAt(start))) {
         // Get the next word
         StringBuffer buf = new StringBuffer();
         int i = start;
         // Call any consecutive letters a word
         for (; i < length && Character.isLetter(event.lineText.charAt(i)); i++) {
           buf.append(event.lineText.charAt(i));
         }
         // See if the word is a keyword
         if (syntaxData.getKeywords().contains(buf.toString())) {
           // It"s a keyword; create the StyleRange
           styles.add(new StyleRange(event.lineOffset + start, i - start, KEYWORD_COLOR, null,
               SWT.BOLD));
         }
         // Move the marker to the last char (the one that wasn"t a letter)
         // so it can be retested in the next iteration through the loop
         start = i;
       } else
         // It"s nothing we"re interested in; advance the marker
         ++start;
     }
     // Copy the StyleRanges back into the event
     event.styles = (StyleRange[]) styles.toArray(new StyleRange[0]);
   }
 }

}</source>





Create a StyledText that scrolls vertically, wraps text, and displays a border:

   <source lang="java">

import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; public class StyledTextCreate {

 public static void main(String[] args) {
   final Display display = new Display();
   final Shell shell = new Shell(display);
   StyledText text = new StyledText(shell, SWT.V_SCROLL | SWT.WRAP | SWT.BORDER);
   
   text.setBounds(10,10,100,100);
   
   shell.open();
   while (!shell.isDisposed()) {
     if (!display.readAndDispatch()) {
       display.sleep();
     }
   }
   display.dispose();
 }

}</source>





Creating a StyledText Widget

   <source lang="java">

StyledText(Composite parent, int style)</source>



StyledText Styles

ConstantDescriptionSWT.BORDERDraws a border around the StyledText.SWT.SINGLECreates a single-line StyledText.SWT.MULTICreates a multiline StyledText. This is the default.SWT.H_SCROLLEnables horizontal scrolling.SWT.V_SCROLLEnables vertical scrolling.SWT.WRAPTurns on word wrapping, trumping the horizontal scrolling style.SWT.READ_ONLYMakes the StyledText read-only.SWT.FULL_SELECTIONCauses redrawing operations to redraw the full line instead of only the invalidated portion.


Draw a box around text

   <source lang="java">

/*******************************************************************************

* Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     IBM Corporation - initial API and implementation
*******************************************************************************/

//package org.eclipse.swt.snippets; /*

* StyledText snippet: Draw a box around text.
* 
* For a list of all SWT example snippets see
* http://www.eclipse.org/swt/snippets/
*/

import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; public class TextAroundBox {

 static String SEARCH_STRING = "box";
 public static void main(String[] args) {
   final Display display = new Display();
   final Color RED = display.getSystemColor(SWT.COLOR_RED);
   Shell shell = new Shell(display);
   shell.setBounds(10, 10, 250, 250);
   final StyledText text = new StyledText(shell, SWT.NONE);
   text.setBounds(10, 10, 200, 200);
   text.addListener(SWT.Paint, new Listener() {
     public void handleEvent(Event event) {
       String contents = text.getText();
       int stringWidth = event.gc.stringExtent(SEARCH_STRING).x;
       int lineHeight = text.getLineHeight();
       event.gc.setForeground(RED);
       int index = contents.indexOf(SEARCH_STRING);
       while (index != -1) {
         Point topLeft = text.getLocationAtOffset(index);
         event.gc.drawRectangle(topLeft.x - 1, topLeft.y, stringWidth + 1, lineHeight - 1);
         index = contents.indexOf(SEARCH_STRING, index + 1);
       }
     }
   });
   text
       .setText("This demonstrates drawing a box\naround every occurrence of the word\nbox in the StyledText");
   shell.open();
   while (!shell.isDisposed()) {
     if (!display.readAndDispatch())
       display.sleep();
   }
   display.dispose();
 }

}</source>





Getting Statistics: Caret Offset, Total Lines of Text, Total Characters and Current Line

   <source lang="java">

import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; public class StyledTextStatistics {

 public static void main(String[] args) {
   final Display display = new Display();
   final Shell shell = new Shell(display);
   StyledText styledText = new StyledText(shell, SWT.V_SCROLL | SWT.BORDER);
   styledText.setText("12345");
   
   
   System.out.println("Caret Offset: " + styledText.getCaretOffset());
   System.out.println("Total Lines of Text: " + styledText.getLineCount());
   System.out.println("Total Characters: " + styledText.getCharCount());
   System.out.println("Current Line: " + (styledText.getLineAtOffset(styledText.getCaretOffset()) + 1));
   
   styledText.setBounds(10,10,100,100);
   shell.open();
   while (!shell.isDisposed()) {
     if (!display.readAndDispatch()) {
       display.sleep();
     }
   }
   display.dispose();
 }

}</source>





Limit the number of characters that the StyledText accepts

   <source lang="java">

import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; public class StyledTextLimit {

 public static void main(String[] args) {
   final Display display = new Display();
   final Shell shell = new Shell(display);
   StyledText styledText = new StyledText(shell, SWT.V_SCROLL | SWT.BORDER);
   styledText.setText("12345");
   styledText.setTextLimit(10);    
   
   styledText.setBounds(10, 10, 100, 100);
   shell.open();
   while (!shell.isDisposed()) {
     if (!display.readAndDispatch()) {
       display.sleep();
     }
   }
   display.dispose();
 }

}</source>





Make a StyledText read-only

   <source lang="java">

import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; public class StyledTextReadOnly {

 public static void main(String[] args) {
   final Display display = new Display();
   final Shell shell = new Shell(display);
   StyledText styledText = new StyledText(shell, SWT.V_SCROLL | SWT.BORDER);
   styledText.setText("12345");
   styledText.setEditable(false);    
   
   styledText.setBounds(10, 10, 100, 100);
   shell.open();
   while (!shell.isDisposed()) {
     if (!display.readAndDispatch()) {
       display.sleep();
     }
   }
   display.dispose();
 }

}</source>





Print StyledText out

   <source lang="java">

import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; public class StyledTextPrint {

 public static void main(String[] args) {
   final Display display = new Display();
   final Shell shell = new Shell(display);
   StyledText styledText = new StyledText(shell, SWT.V_SCROLL | SWT.BORDER);
   styledText.setText("12345");
   
   styledText.print();
   
   styledText.setBounds(10,10,100,100);
   shell.open();
   while (!shell.isDisposed()) {
     if (!display.readAndDispatch()) {
       display.sleep();
     }
   }
   display.dispose();
 }

}</source>





Print to the default printer in a separate thread

   <source lang="java">

import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.printing.Printer; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; public class StyledTextPrintSeparateThread {

 public static void main(String[] args) {
   final Display display = new Display();
   final Shell shell = new Shell(display);
   StyledText styledText = new StyledText(shell, SWT.V_SCROLL | SWT.BORDER);
   styledText.print(new Printer()).run();
   
   styledText.setBounds(10,10,100,100);
   shell.open();
   while (!shell.isDisposed()) {
     if (!display.readAndDispatch()) {
       display.sleep();
     }
   }
   display.dispose();
 }

}</source>





Replace Text Range

   <source lang="java">

import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; public class StyledTextReplaceTextRange {

 public static void main(String[] args) {
   final Display display = new Display();
   final Shell shell = new Shell(display);
   final StyledText styledText = new StyledText(shell, SWT.V_SCROLL | SWT.BORDER);
   styledText.setText("12345");
   styledText.replaceTextRange(2, 3, "A");
   
   
   styledText.setBounds(10, 10, 100, 100);
   shell.open();
   while (!shell.isDisposed()) {
     if (!display.readAndDispatch()) {
       display.sleep();
     }
   }
   display.dispose();
 }

}</source>





Set page format for printing

  1. print the name of the file on top of each page,
  2. print the page number at the bottom of each page,
  3. print the word "Confidential" in the lower-right corner,
  4. print the text in the appropriate colors and styles



   <source lang="java">

import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.custom.StyledTextPrintOptions; import org.eclipse.swt.printing.Printer; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; public class StyledTextPrintFormat {

 public static void main(String[] args) {
   final Display display = new Display();
   final Shell shell = new Shell(display);
   StyledText styledText = new StyledText(shell, SWT.V_SCROLL | SWT.BORDER);
   styledText.setText("12345");
   StyledTextPrintOptions options = new StyledTextPrintOptions();
   options.header = StyledTextPrintOptions.SEPARATOR + "myfile.txt"
       + StyledTextPrintOptions.SEPARATOR;
   options.footer = StyledTextPrintOptions.SEPARATOR + StyledTextPrintOptions.PAGE_TAG
       + StyledTextPrintOptions.SEPARATOR + "Confidential";
   options.printLineBackground = true;
   options.printTextBackground = true;
   options.printTextFontStyle = true;
   options.printTextForeground = true;
   styledText.print(new Printer(), options).run();
   styledText.setBounds(10, 10, 100, 100);
   shell.open();
   while (!shell.isDisposed()) {
     if (!display.readAndDispatch()) {
       display.sleep();
     }
   }
   display.dispose();
 }

}</source>





StyledText: embed controls

   <source lang="java">

/*******************************************************************************

* Copyright (c) 2000, 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     IBM Corporation - initial API and implementation
*******************************************************************************/

//package org.eclipse.swt.snippets; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.PaintObjectEvent; import org.eclipse.swt.custom.PaintObjectListener; import org.eclipse.swt.custom.StyleRange; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.events.VerifyEvent; import org.eclipse.swt.events.VerifyListener; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.GlyphMetrics; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.rubo; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; /**

* StyledText snippet: embed controls
* 
* For a list of all SWT example snippets see
* http://www.eclipse.org/swt/snippets/
* 
* @since 3.2
*/

public class StyledTextEmbebControls {

 static StyledText styledText;
 static String text = "This snippet shows how to embed widgets in a StyledText.\n"
     + "Here is one: \uFFFC, and here is another: \uFFFC.";
 static int[] offsets;
 static Control[] controls;
 static int MARGIN = 5;
 static void addControl(Control control, int offset) {
   StyleRange style = new StyleRange();
   style.start = offset;
   style.length = 1;
   control.pack();
   Rectangle rect = control.getBounds();
   int ascent = 2 * rect.height / 3;
   int descent = rect.height - ascent;
   style.metrics = new GlyphMetrics(ascent + MARGIN, descent + MARGIN, rect.width + 2 * MARGIN);
   styledText.setStyleRange(style);
 }
 public static void main(String[] args) {
   final Display display = new Display();
   Font font = new Font(display, "Tahoma", 32, SWT.NORMAL);
   final Shell shell = new Shell(display);
   shell.setLayout(new GridLayout());
   styledText = new StyledText(shell, SWT.WRAP | SWT.BORDER);
   styledText.setFont(font);
   styledText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
   styledText.setText(text);
   controls = new Control[2];
   Button button = new Button(styledText, SWT.PUSH);
   button.setText("Button 1");
   controls[0] = button;
   Combo combo = new Combo(styledText, SWT.NONE);
   combo.add("item 1");
   combo.add("another item");
   controls[1] = combo;
   offsets = new int[controls.length];
   int lastOffset = 0;
   for (int i = 0; i < controls.length; i++) {
     int offset = text.indexOf("\uFFFC", lastOffset);
     offsets[i] = offset;
     addControl(controls[i], offsets[i]);
     lastOffset = offset + 1;
   }
   // use a verify listener to keep the offsets up to date
   styledText.addVerifyListener(new VerifyListener() {
     public void verifyText(VerifyEvent e) {
       int start = e.start;
       int replaceCharCount = e.end - e.start;
       int newCharCount = e.text.length();
       for (int i = 0; i < offsets.length; i++) {
         int offset = offsets[i];
         if (start <= offset && offset < start + replaceCharCount) {
           // this widget is being deleted from the text
           if (controls[i] != null && !controls[i].isDisposed()) {
             controls[i].dispose();
             controls[i] = null;
           }
           offset = -1;
         }
         if (offset != -1 && offset >= start)
           offset += newCharCount - replaceCharCount;
         offsets[i] = offset;
       }
     }
   });
   // reposition widgets on paint event
   styledText.addPaintObjectListener(new PaintObjectListener() {
     public void paintObject(PaintObjectEvent event) {
       StyleRange style = event.style;
       int start = style.start;
       for (int i = 0; i < offsets.length; i++) {
         int offset = offsets[i];
         if (start == offset) {
           Point pt = controls[i].getSize();
           int x = event.x + MARGIN;
           int y = event.y + event.ascent - 2 * pt.y / 3;
           controls[i].setLocation(x, y);
           break;
         }
       }
     }
   });
   shell.setSize(400, 400);
   shell.open();
   while (!shell.isDisposed()) {
     if (!display.readAndDispatch())
       display.sleep();
   }
   font.dispose();
   display.dispose();
 }

}</source>





StyledText: embed images

   <source lang="java">

/*******************************************************************************

* Copyright (c) 2000, 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     IBM Corporation - initial API and implementation
*******************************************************************************/

//package org.eclipse.swt.snippets; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.PaintObjectEvent; import org.eclipse.swt.custom.PaintObjectListener; import org.eclipse.swt.custom.StyleRange; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.events.VerifyEvent; import org.eclipse.swt.events.VerifyListener; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.GlyphMetrics; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; /**

* StyledText snippet: embed images
* 
* For a list of all SWT example snippets see
* http://www.eclipse.org/swt/snippets/
* 
* @since 3.2
*/

public class StyledTextEmbedImages {

 static StyledText styledText;
 static String text = "This snippet shows how to embed images in a StyledText.\n"
     + "Here is one: \uFFFC, and here is another: \uFFFC."
     + "Use the add button to add an image from your filesystem to the StyledText at the current caret offset.";
 static Image[] images;
 static int[] offsets;
 static void addImage(Image image, int offset) {
   StyleRange style = new StyleRange();
   style.start = offset;
   style.length = 1;
   Rectangle rect = image.getBounds();
   style.metrics = new GlyphMetrics(rect.height, 0, rect.width);
   styledText.setStyleRange(style);
 }
 public static void main(String[] args) {
   final Display display = new Display();
   final Shell shell = new Shell(display);
   shell.setLayout(new GridLayout());
   styledText = new StyledText(shell, SWT.WRAP | SWT.BORDER);
   styledText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
   styledText.setText(text);
   images = new Image[] { display.getSystemImage(SWT.ICON_QUESTION),
       display.getSystemImage(SWT.ICON_INFORMATION), };
   offsets = new int[images.length];
   int lastOffset = 0;
   for (int i = 0; i < images.length; i++) {
     int offset = text.indexOf("\uFFFC", lastOffset);
     offsets[i] = offset;
     addImage(images[i], offset);
     lastOffset = offset + 1;
   }
   // use a verify listener to keep the offsets up to date
   styledText.addVerifyListener(new VerifyListener() {
     public void verifyText(VerifyEvent e) {
       int start = e.start;
       int replaceCharCount = e.end - e.start;
       int newCharCount = e.text.length();
       for (int i = 0; i < offsets.length; i++) {
         int offset = offsets[i];
         if (start <= offset && offset < start + replaceCharCount) {
           // this image is being deleted from the text
           if (images[i] != null && !images[i].isDisposed()) {
             images[i].dispose();
             images[i] = null;
           }
           offset = -1;
         }
         if (offset != -1 && offset >= start)
           offset += newCharCount - replaceCharCount;
         offsets[i] = offset;
       }
     }
   });
   styledText.addPaintObjectListener(new PaintObjectListener() {
     public void paintObject(PaintObjectEvent event) {
       GC gc = event.gc;
       StyleRange style = event.style;
       int start = style.start;
       for (int i = 0; i < offsets.length; i++) {
         int offset = offsets[i];
         if (start == offset) {
           Image image = images[i];
           int x = event.x;
           int y = event.y + event.ascent - style.metrics.ascent;
           gc.drawImage(image, x, y);
         }
       }
     }
   });
   Button button = new Button(shell, SWT.PUSH);
   button.setText("Add Image");
   button.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false));
   button.addListener(SWT.Selection, new Listener() {
     public void handleEvent(Event event) {
       FileDialog dialog = new FileDialog(shell);
       String filename = dialog.open();
       if (filename != null) {
         try {
           Image image = new Image(display, filename);
           int offset = styledText.getCaretOffset();
           styledText.replaceTextRange(offset, 0, "\uFFFC");
           int index = 0;
           while (index < offsets.length) {
             if (offsets[index] == -1 && images[index] == null)
               break;
             index++;
           }
           if (index == offsets.length) {
             int[] tmpOffsets = new int[index + 1];
             System.arraycopy(offsets, 0, tmpOffsets, 0, offsets.length);
             offsets = tmpOffsets;
             Image[] tmpImages = new Image[index + 1];
             System.arraycopy(images, 0, tmpImages, 0, images.length);
             images = tmpImages;
           }
           offsets[index] = offset;
           images[index] = image;
           addImage(image, offset);
         } catch (Exception e) {
           e.printStackTrace();
         }
       }
     }
   });
   shell.setSize(400, 400);
   shell.open();
   while (!shell.isDisposed()) {
     if (!display.readAndDispatch())
       display.sleep();
   }
   for (int i = 0; i < images.length; i++) {
     Image image = images[i];
     if (image != null && !image.isDisposed()) {
       image.dispose();
     }
   }
   display.dispose();
 }

}</source>





StyledText: use gradient background

   <source lang="java">

/*******************************************************************************

* Copyright (c) 2000, 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     IBM Corporation - initial API and implementation
*******************************************************************************/

//package org.eclipse.swt.snippets; /*

* SWT StyledText snippet: use gradient background.
* 
* For a list of all SWT example snippets see
* http://www.eclipse.org/swt/snippets/
* 
* @since 3.2
*/

import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; public class StyledTextGradientBackground {

 static String text = "Plans do not materialize out of nowhere, nor are they entirely static. To ensure the planning process is "
     + "transparent and open to the entire Eclipse community, we (the Eclipse PMC) post plans in an embryonic "
     + "form and revise them throughout the release cycle. \n"
     + "The first part of the plan deals with the important matters of release deliverables, release milestones, target "
     + "operating environments, and release-to-release compatibility. These are all things that need to be clear for "
     + "any release, even if no features were to change.  \n";
 static Image oldImage;
 public static void main(String[] args) {
   final Display display = new Display();
   final Shell shell = new Shell(display);
   shell.setLayout(new FillLayout());
   final StyledText styledText = new StyledText(shell, SWT.WRAP | SWT.BORDER);
   styledText.setText(text);
   FontData data = display.getSystemFont().getFontData()[0];
   Font font = new Font(display, data.getName(), 16, SWT.BOLD);
   styledText.setFont(font);
   styledText.setForeground(display.getSystemColor(SWT.COLOR_BLUE));
   styledText.addListener(SWT.Resize, new Listener() {
     public void handleEvent(Event event) {
       Rectangle rect = styledText.getClientArea();
       Image newImage = new Image(display, 1, Math.max(1, rect.height));
       GC gc = new GC(newImage);
       gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
       gc.setBackground(display.getSystemColor(SWT.COLOR_YELLOW));
       gc.fillGradientRectangle(rect.x, rect.y, 1, rect.height, true);
       gc.dispose();
       styledText.setBackgroundImage(newImage);
       if (oldImage != null)
         oldImage.dispose();
       oldImage = newImage;
     }
   });
   shell.setSize(700, 400);
   shell.open();
   while (!shell.isDisposed()) {
     if (!display.readAndDispatch())
       display.sleep();
   }
   if (oldImage != null)
     oldImage.dispose();
   font.dispose();
   display.dispose();
 }

}</source>





Understanding the Repercussions

When you use a LineStyleListener , you shouldn"t use the following API calls:

  1. getStyleRangeAtOffset(int offset)
  2. StyleRange[] getStyleRanges()
  3. void replaceStyleRanges(int start, int length, StyleRange[] ranges)
  4. void setStyleRange(StyleRange range)
  5. void setStyleRanges(StyleRange[] ranges)

Mixing these API calls with a LineStyleListener is unsupported. (The Definitive Guide to SWT and JFace by Robert Harris and Rob Warner Apress 2004 )


Using the Clipboard

   <source lang="java">

import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; public class StyledTextClipboard {

 public static void main(String[] args) {
   final Display display = new Display();
   final Shell shell = new Shell(display);
   StyledText text1 = new StyledText(shell, SWT.V_SCROLL | SWT.WRAP | SWT.BORDER);
   StyledText text2 = new StyledText(shell, SWT.V_SCROLL | SWT.WRAP | SWT.BORDER);
   text1.setText("1234567");
   
   text1.setSelectionRange(2,4);
   
   text1.cut();
   text2.paste();
   
   text1.setBounds(10,10,100,100);
   
   text2.setBounds(10,300,100,100);
   
   shell.open();
   while (!shell.isDisposed()) {
     if (!display.readAndDispatch()) {
       display.sleep();
     }
   }
   display.dispose();
 }

}</source>