/** * Convert mouse screen coordinates to a <code>StyledText</code> offset. * * @param x screen X-coordinate * @param y screen Y-coordinate * @param absolute if <code>true</code>, coordinates are expected to be absolute screen * coordinates * @return text offset * @see StyledText#getOffsetAtLocation() */ private int getOffsetAtLocation(int x, int y, boolean absolute) { StyledText textWidget = fViewer.getTextWidget(); StyledTextContent content = textWidget.getContent(); Point location; if (absolute) { location = textWidget.toControl(x, y); } else { location = new Point(x, y); } int line = (textWidget.getTopPixel() + location.y) / textWidget.getLineHeight(); if (line >= content.getLineCount()) { return content.getCharCount(); } int lineOffset = content.getOffsetAtLine(line); String lineText = content.getLine(line); Point endOfLine = textWidget.getLocationAtOffset(lineOffset + lineText.length()); if (location.x >= endOfLine.x) { return lineOffset + lineText.length(); } try { return textWidget.getOffsetAtLocation(location); } catch (IllegalArgumentException iae) { // we are expecting this return -1; } }
/** * Installs this highlighter into the specified StyledText object. Client can manually call * detach() method, then wants to destroy this object. */ public void attach(StyledText parent) { detach(); text = parent; text.addDisposeListener(ml); text.addLineStyleListener(ml); text.addLineBackgroundListener(ml); text.addPaintListener(ml); text.addVerifyListener(ml); text.addExtendedModifyListener(ml); text.addControlListener(ml); text.addKeyListener(ml); text.addTraverseListener(ml); text.addMouseListener(ml); text.addSelectionListener(ml); text.getContent().addTextChangeListener(ml); ScrollBar sb = text.getVerticalBar(); if (sb != null) sb.addSelectionListener(ml); updateViewport(); new Thread() { public void run() { // setPriority(Thread.NORM_PRIORITY-1); while (true) { try { sleep(300); } catch (InterruptedException e) { } if (baseEditor == null || text == null) break; if (backParserDelay) { backParserDelay = false; try { sleep(1500); } catch (InterruptedException e) { } continue; } ; Display.getDefault() .syncExec( new Runnable() { public void run() { if (baseEditor == null || text == null) return; if (text.isDisposed()) return; // System.out.println(System.currentTimeMillis()); baseEditor.idleJob(80); // redrawFrom(text.getLineAtOffset(text.getCaretOffset())); } }); } ; }; }.start(); }
/* * @see org.eclipse.jface.text.source.AnnotationPainter.IDrawingStrategy#draw(org.eclipse.swt.graphics.GC, org.eclipse.swt.custom.StyledText, int, int, org.eclipse.swt.graphics.Color) */ public void draw( Annotation annotation, GC gc, StyledText textWidget, int offset, int length, Color color) { if (annotation instanceof ProjectionAnnotation) { ProjectionAnnotation projectionAnnotation = (ProjectionAnnotation) annotation; if (projectionAnnotation.isCollapsed()) { if (gc != null) { StyledTextContent content = textWidget.getContent(); int line = content.getLineAtOffset(offset); int lineStart = content.getOffsetAtLine(line); String text = content.getLine(line); int lineLength = text == null ? 0 : text.length(); int lineEnd = lineStart + lineLength; Point p = textWidget.getLocationAtOffset(lineEnd); Color c = gc.getForeground(); gc.setForeground(color); FontMetrics metrics = gc.getFontMetrics(); // baseline: where the dots are drawn int baseline = textWidget.getBaseline(offset); // descent: number of pixels that the box extends over baseline int descent = Math.min(2, textWidget.getLineHeight(offset) - baseline); // ascent: so much does the box stand up from baseline int ascent = metrics.getAscent(); // leading: free space from line top to box upper line int leading = baseline - ascent; // height: height of the box int height = ascent + descent; int width = metrics.getAverageCharWidth(); gc.drawRectangle(p.x, p.y + leading, width, height); int third = width / 3; int dotsVertical = p.y + baseline - 1; gc.drawPoint(p.x + third, dotsVertical); gc.drawPoint(p.x + width - third, dotsVertical); gc.setForeground(c); } else { textWidget.redrawRange(offset, length, true); } } } }
/** DOC amaumont Comment method "addListeners". */ private void addListeners() { styledText.addFocusListener( new FocusListener() { public void focusGained(FocusEvent e) { refreshProposalSize(); } public void focusLost(FocusEvent e) {} }); styledText.addControlListener( new ControlListener() { public void controlMoved(ControlEvent e) {} public void controlResized(ControlEvent e) { refreshProposalSize(); } }); styledText.addExtendedModifyListener( new ExtendedModifyListener() { public void modifyText(ExtendedModifyEvent event) { updateCellExpression(); // System.out.println("ExtendedModifyListener modify text"); } }); styledText .getContent() .addTextChangeListener( new TextChangeListener() { public void textChanged(TextChangedEvent event) { highlightLineOfCursorPosition(styledText.getSelection()); } public void textChanging(TextChangingEvent event) { // System.out.println("textChanging"); } public void textSet(TextChangedEvent event) { // System.out.println("textSet"); } }); styledText.addModifyListener( new ModifyListener() { public void modifyText(ModifyEvent e) { highlightLineOfCursorPosition(styledText.getSelection()); } }); styledText.addKeyListener( new KeyListener() { public void keyPressed(KeyEvent e) { highlightLineOfCursorPosition(styledText.getSelection()); } public void keyReleased(KeyEvent e) { // TODO Auto-generated method stub } }); styledText.addVerifyKeyListener( new VerifyKeyListener() { public void verifyKey(VerifyEvent verifyEvent) { if (verifyEvent.character == '\r' && contentProposalAdapter != null && contentProposalAdapter.isProposalOpened()) { verifyEvent.doit = false; } else { verifyEvent.doit = true; } } }); styledText.addMouseListener( new MouseListener() { public void mouseDoubleClick(MouseEvent e) { highlightLineOfCursorPosition(styledText.getSelection()); } public void mouseDown(MouseEvent e) { highlightLineOfCursorPosition(styledText.getSelection()); } public void mouseUp(MouseEvent e) {} }); }
/** * Creates a new <code>BZStyledText</code> for parentShell <code>parentShell</code>. * * @param parentShell parentShell of the new instance (cannot be null) */ public BZStyledText(Shell parentShell) { this.parentShell = parentShell; // version from jar manifest String version = getClass().getPackage().getImplementationVersion(); // version from build file if (version == null) version = System.getProperty("braillezephyr.version"); // no version if (version == null) { logWriter.println("WARNING: unable to determine version, using 0.0"); version = "0.0"; } versionString = version; String[] versionStrings = versionString.split("\\."); versionMajor = Integer.parseInt(versionStrings[0]); if (versionStrings.length > 1) versionMinor = Integer.parseInt(versionStrings[1]); else versionMinor = 0; if (versionStrings.length > 2) versionPatch = Integer.parseInt(versionStrings[2]); else versionPatch = 0; color = parentShell.getDisplay().getSystemColor(SWT.COLOR_BLACK); composite = new Composite(parentShell, 0); composite.setLayout(new GridLayout(2, true)); // load fonts loadFont("BrailleZephyr_6.otf"); loadFont("BrailleZephyr_6b.otf"); loadFont("BrailleZephyr_6s.otf"); loadFont("BrailleZephyr_6sb.otf"); loadFont("BrailleZephyr_8.otf"); loadFont("BrailleZephyr_8b.otf"); loadFont("BrailleZephyr_8s.otf"); loadFont("BrailleZephyr_8sb.otf"); loadFont("BrailleZephyr_8w.otf"); loadFont("BrailleZephyr_8wb.otf"); loadFont("BrailleZephyr_8ws.otf"); loadFont("BrailleZephyr_8wsb.otf"); // load line margin bell try { InputStream inputStreamBellMargin = new BufferedInputStream(getClass().getResourceAsStream("/sounds/line_margin_bell.wav")); AudioInputStream audioInputStreamMargin = AudioSystem.getAudioInputStream(inputStreamBellMargin); DataLine.Info dataLineInfoMargin = new DataLine.Info(Clip.class, audioInputStreamMargin.getFormat()); lineMarginClip = (Clip) AudioSystem.getLine(dataLineInfoMargin); lineMarginClip.open(audioInputStreamMargin); } catch (IOException exception) { logWriter.println( "ERROR: Unable to read default line margin bell file: " + exception.getMessage()); lineMarginClip = null; } catch (UnsupportedAudioFileException exception) { logWriter.println( "ERROR: Sound file unsupported for default line margin bell: " + exception.getMessage()); lineMarginClip = null; } catch (LineUnavailableException exception) { logWriter.println( "ERROR: Line unavailable for default line margin bell: " + exception.getMessage()); lineMarginClip = null; } // load page margin bell try { InputStream inputStreamBellPage = new BufferedInputStream(getClass().getResourceAsStream("/sounds/page_margin_bell.wav")); AudioInputStream audioInputStreamPage = AudioSystem.getAudioInputStream(inputStreamBellPage); DataLine.Info dataLineInfoPage = new DataLine.Info(Clip.class, audioInputStreamPage.getFormat()); pageMarginClip = (Clip) AudioSystem.getLine(dataLineInfoPage); pageMarginClip.open(audioInputStreamPage); } catch (IOException exception) { logWriter.println( "ERROR: Unable to read default page margin bell file: " + exception.getMessage()); pageMarginClip = null; } catch (UnsupportedAudioFileException exception) { logWriter.println( "ERROR: Sound file unsupported for default page margin bell: " + exception.getMessage()); pageMarginClip = null; } catch (LineUnavailableException exception) { logWriter.println( "ERROR: Line unavailable for default page margin bell: " + exception.getMessage()); pageMarginClip = null; } // load line end bell try { InputStream inputStreamBellPage = new BufferedInputStream(getClass().getResourceAsStream("/sounds/line_end_bell.wav")); AudioInputStream audioInputStreamPage = AudioSystem.getAudioInputStream(inputStreamBellPage); DataLine.Info dataLineInfoPage = new DataLine.Info(Clip.class, audioInputStreamPage.getFormat()); lineEndClip = (Clip) AudioSystem.getLine(dataLineInfoPage); lineEndClip.open(audioInputStreamPage); } catch (IOException exception) { logWriter.println( "ERROR: Unable to read default line end bell file: " + exception.getMessage()); lineEndClip = null; } catch (UnsupportedAudioFileException exception) { logWriter.println( "ERROR: Sound file unsupported for default line end bell: " + exception.getMessage()); lineEndClip = null; } catch (LineUnavailableException exception) { logWriter.println( "ERROR: Line unavailable for default line end bell: " + exception.getMessage()); lineEndClip = null; } brailleText = new StyledText(composite, SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); brailleText.setLayoutData(new GridData(GridData.FILL_BOTH)); brailleText.setFont(new Font(parentShell.getDisplay(), "BrailleZephyr_6s", 18, SWT.NORMAL)); brailleText.addFocusListener(new FocusHandler(brailleText)); brailleText.addPaintListener(new PaintHandler(brailleText)); BrailleKeyHandler brailleKeyHandler = new BrailleKeyHandler(true); brailleText.addKeyListener(brailleKeyHandler); brailleText.addVerifyKeyListener(brailleKeyHandler); brailleText.addExtendedModifyListener(new ExtendedModifyHandler(brailleText)); content = brailleText.getContent(); asciiText = new StyledText(composite, SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); asciiText.setContent(content); asciiText.setLayoutData(new GridData(GridData.FILL_BOTH)); asciiText.setFont(new Font(parentShell.getDisplay(), "Monospace", 18, SWT.NORMAL)); asciiText.addFocusListener(new FocusHandler(asciiText)); asciiText.addPaintListener(new PaintHandler(asciiText)); asciiText.addVerifyKeyListener(new BrailleKeyHandler(false)); asciiText.addExtendedModifyListener(new ExtendedModifyHandler(asciiText)); brailleText.addCaretListener(new CaretHandler(brailleText, asciiText)); asciiText.addCaretListener(new CaretHandler(asciiText, brailleText)); currentText = brailleText; }
/** * Draw characters of content range. * * @param gc the GC * @param startOffset inclusive start index * @param endOffset exclusive end index */ private void drawCharRange(GC gc, int startOffset, int endOffset) { StyledTextContent content = fTextWidget.getContent(); int length = endOffset - startOffset; String text = content.getTextRange(startOffset, length); StyleRange styleRange = null; Color fg = null; Point selection = fTextWidget.getSelection(); StringBuffer visibleChar = new StringBuffer(10); for (int textOffset = 0; textOffset <= length; ++textOffset) { int delta = 0; boolean eol = false; if (textOffset < length) { delta = 1; char c = text.charAt(textOffset); switch (c) { case ' ': visibleChar.append(SPACE_SIGN); // 'continue' would improve performance but may produce // drawing errors // for long runs of space if width of space and dot differ break; case '\u3000': // ideographic whitespace visibleChar.append(IDEOGRAPHIC_SPACE_SIGN); // 'continue' would improve performance but may produce // drawing errors // for long runs of space if width of space and dot differ break; case '\t': visibleChar.append(TAB_SIGN); break; case '\r': visibleChar.append(CARRIAGE_RETURN_SIGN); if (textOffset >= length - 1 || text.charAt(textOffset + 1) != '\n') { eol = true; break; } continue; case '\n': visibleChar.append(LINE_FEED_SIGN); eol = true; break; default: delta = 0; break; } } if (visibleChar.length() > 0) { int widgetOffset = startOffset + textOffset - visibleChar.length() + delta; if (!eol || !isFoldedLine(content.getLineAtOffset(widgetOffset))) { if (widgetOffset >= selection.x && widgetOffset < selection.y) { fg = fTextWidget.getSelectionForeground(); } else if (styleRange == null || styleRange.start + styleRange.length <= widgetOffset) { styleRange = fTextWidget.getStyleRangeAtOffset(widgetOffset); if (styleRange == null || styleRange.foreground == null) { fg = fTextWidget.getForeground(); } else { fg = styleRange.foreground; } } draw(gc, widgetOffset, visibleChar.toString(), fg); } visibleChar.delete(0, visibleChar.length()); } } }