/** * Sets the receiver's text. * * <p>The string can contain both regular text and hyperlinks. A hyperlink is delimited by an * anchor tag, <A> and </A>. Within an anchor, a single HREF attribute is supported. * When a hyperlink is selected, the text field of the selection event contains either the text of * the hyperlink or the value of its HREF, if one was specified. In the rare case of identical * hyperlinks within the same string, the HREF attribute can be used to distinguish between them. * The string may include the mnemonic character and line delimiters. The only delimiter the HREF * attribute supports is the quotation mark ("). * * <p>Mnemonics are indicated by an '&' that causes the next character to be the mnemonic. The * receiver can have a mnemonic in the text preceding each link. When the user presses a key * sequence that matches the mnemonic, focus is assigned to the link that follows the text. * Mnemonics in links and in the trailing text are ignored. On most platforms, the mnemonic * appears underlined but may be emphasised in a platform specific manner. The mnemonic indicator * character '&' can be escaped by doubling it in the string, causing a single '&' to be * displayed. * * @param string the new text * @exception IllegalArgumentException * <ul> * <li>ERROR_NULL_ARGUMENT - if the text is null * </ul> * * @exception SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver * </ul> */ public void setText(String string) { checkWidget(); if (string == null) error(SWT.ERROR_NULL_ARGUMENT); if (string.equals(text)) return; text = string; layout.setText(parse(string)); focusIndex = offsets.length > 0 ? 0 : -1; selection.x = selection.y = -1; boolean enabled = (state & DISABLED) == 0; TextStyle linkStyle = new TextStyle(null, enabled ? linkColor : disabledColor, null); linkStyle.underline = true; int[] bidiSegments = new int[offsets.length * 2]; for (int i = 0; i < offsets.length; i++) { Point point = offsets[i]; layout.setStyle(linkStyle, point.x, point.y); bidiSegments[i * 2] = point.x; bidiSegments[i * 2 + 1] = point.y + 1; } layout.setSegments(bidiSegments); TextStyle mnemonicStyle = new TextStyle(null, null, null); mnemonicStyle.underline = true; for (int i = 0; i < mnemonics.length; i++) { int mnemonic = mnemonics[i]; if (mnemonic != -1) { layout.setStyle(mnemonicStyle, mnemonic, mnemonic); } } redraw(); }
@Override void createWidget(int index) { super.createWidget(index); layout.setFont(getFont()); text = ""; initAccessible(); }
@Override int setBounds(int x, int y, int width, int height, boolean move, boolean resize) { int result = super.setBounds(x, y, width, height, move, resize); if ((result & RESIZED) != 0) { layout.setWidth(width > 0 ? width : -1); redraw(); } return result; }
@Override void enableWidget(boolean enabled) { super.enableWidget(enabled); if (isDisposed()) return; TextStyle linkStyle = new TextStyle(null, enabled ? linkColor : disabledColor, null); linkStyle.underline = true; for (int i = 0; i < offsets.length; i++) { Point point = offsets[i]; layout.setStyle(linkStyle, point.x, point.y); } redraw(); }
Rectangle[] getRectangles(int linkIndex) { int lineCount = layout.getLineCount(); Rectangle[] rects = new Rectangle[lineCount]; int[] lineOffsets = layout.getLineOffsets(); Point point = offsets[linkIndex]; int lineStart = 1; while (point.x > lineOffsets[lineStart]) lineStart++; int lineEnd = 1; while (point.y > lineOffsets[lineEnd]) lineEnd++; int index = 0; if (lineStart == lineEnd) { rects[index++] = layout.getBounds(point.x, point.y); } else { rects[index++] = layout.getBounds(point.x, lineOffsets[lineStart] - 1); rects[index++] = layout.getBounds(lineOffsets[lineEnd - 1], point.y); if (lineEnd - lineStart > 1) { for (int i = lineStart; i < lineEnd - 1; i++) { rects[index++] = layout.getLineBounds(i); } } } if (rects.length != index) { Rectangle[] tmp = new Rectangle[index]; System.arraycopy(rects, 0, tmp, 0, index); rects = tmp; } return rects; }
@Override public Point computeSize(int wHint, int hHint, boolean changed) { checkWidget(); if (wHint != SWT.DEFAULT && wHint < 0) wHint = 0; if (hHint != SWT.DEFAULT && hHint < 0) hHint = 0; int width, height; int layoutWidth = layout.getWidth(); // TEMPORARY CODE if (wHint == 0) { layout.setWidth(1); Rectangle rect = layout.getBounds(); width = 0; height = rect.height; } else { layout.setWidth(wHint); Rectangle rect = layout.getBounds(); width = rect.width; height = rect.height; } layout.setWidth(layoutWidth); if (wHint != SWT.DEFAULT) width = wHint; if (hHint != SWT.DEFAULT) height = hHint; int border = getBorderWidth(); width += border * 2; height += border * 2; return new Point(width, height); }
@Override void releaseWidget() { super.releaseWidget(); if (layout != null) layout.dispose(); layout = null; linkColor = null; if (disabledColor != null) disabledColor.dispose(); disabledColor = null; offsets = null; ids = null; mnemonics = null; text = null; }
@Override long /*int*/ gtk_button_press_event(long /*int*/ widget, long /*int*/ event) { long /*int*/ result = super.gtk_button_press_event(widget, event); if (result != 0) return result; GdkEventButton gdkEvent = new GdkEventButton(); OS.memmove(gdkEvent, event, GdkEventButton.sizeof); if (gdkEvent.button == 1 && gdkEvent.type == OS.GDK_BUTTON_PRESS) { if (focusIndex != -1) setFocus(); int x = (int) gdkEvent.x; int y = (int) gdkEvent.y; if ((style & SWT.MIRRORED) != 0) x = getClientWidth() - x; int offset = layout.getOffset(x, y, null); int oldSelectionX = selection.x; int oldSelectionY = selection.y; selection.x = offset; selection.y = -1; if (oldSelectionX != -1 && oldSelectionY != -1) { if (oldSelectionX > oldSelectionY) { int temp = oldSelectionX; oldSelectionX = oldSelectionY; oldSelectionY = temp; } Rectangle rect = layout.getBounds(oldSelectionX, oldSelectionY); redraw(rect.x, rect.y, rect.width, rect.height, false); } for (int j = 0; j < offsets.length; j++) { Rectangle[] rects = getRectangles(j); for (int i = 0; i < rects.length; i++) { Rectangle rect = rects[i]; if (rect.contains(x, y)) { focusIndex = j; redraw(); return result; } } } } return result; }
@Override boolean mnemonicMatch(char key) { char uckey = Character.toUpperCase(key); String parsedText = layout.getText(); for (int i = 0; i < mnemonics.length - 1; i++) { if (mnemonics[i] != -1) { char mnemonic = parsedText.charAt(mnemonics[i]); if (uckey == Character.toUpperCase(mnemonic)) { return true; } } } return false; }
@Override long /*int*/ gtk_motion_notify_event(long /*int*/ widget, long /*int*/ event) { long /*int*/ result = super.gtk_motion_notify_event(widget, event); if (result != 0) return result; GdkEventMotion gdkEvent = new GdkEventMotion(); OS.memmove(gdkEvent, event, GdkEventMotion.sizeof); int x = (int) gdkEvent.x; int y = (int) gdkEvent.y; if ((style & SWT.MIRRORED) != 0) x = getClientWidth() - x; if ((gdkEvent.state & OS.GDK_BUTTON1_MASK) != 0) { int oldSelection = selection.y; selection.y = layout.getOffset(x, y, null); if (selection.y != oldSelection) { int newSelection = selection.y; if (oldSelection > newSelection) { int temp = oldSelection; oldSelection = newSelection; newSelection = temp; } Rectangle rect = layout.getBounds(oldSelection, newSelection); redraw(rect.x, rect.y, rect.width, rect.height, false); } } else { for (int j = 0; j < offsets.length; j++) { Rectangle[] rects = getRectangles(j); for (int i = 0; i < rects.length; i++) { Rectangle rect = rects[i]; if (rect.contains(x, y)) { setCursor(display.getSystemCursor(SWT.CURSOR_HAND)); return result; } } } setCursor(null); } return result; }
@Override boolean mnemonicHit(char key) { char uckey = Character.toUpperCase(key); String parsedText = layout.getText(); for (int i = 0; i < mnemonics.length - 1; i++) { if (mnemonics[i] != -1) { char mnemonic = parsedText.charAt(mnemonics[i]); if (uckey == Character.toUpperCase(mnemonic)) { if (!setFocus()) return false; focusIndex = i; redraw(); return true; } } } return false; }
@Override void drawWidget(GC gc) { int selStart = selection.x; int selEnd = selection.y; if (selStart > selEnd) { selStart = selection.y; selEnd = selection.x; } // temporary code to disable text selection selStart = selEnd = -1; if ((state & DISABLED) != 0) gc.setForeground(disabledColor); layout.draw(gc, 0, 0, selStart, selEnd, null, null); if (hasFocus() && focusIndex != -1) { Rectangle[] rects = getRectangles(focusIndex); for (int i = 0; i < rects.length; i++) { Rectangle rect = rects[i]; gc.drawFocus(rect.x, rect.y, rect.width, rect.height); } } }
@Override void setOrientation(boolean create) { super.setOrientation(create); layout.setOrientation(style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT)); if (!create) redraw(true); }
@Override void setFontDescription(long /*int*/ font) { super.setFontDescription(font); layout.setFont(Font.gtk_new(display, font)); }