/******************************************************************************* * Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc. * Distributed under license by Red Hat, Inc. All rights reserved. * This program is 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: * Exadel, Inc. and Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.jboss.tools.common.editor; import java.util.*; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.ScrolledComposite; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; import org.jboss.tools.common.model.XModelObject; import org.jboss.tools.common.model.ui.ModelUIPlugin; public class ErrorMode { private ScrolledComposite errors = null; Composite c = null; private ArrayList<Lbl> labels = new ArrayList<Lbl>(); String es = ""; //$NON-NLS-1$ ErrorSelectionListener listener; boolean visible = true; public void addErrorSelectionListener(ErrorSelectionListener listener) { this.listener = listener; for (int i = 0; i < labels.size(); i++) { Lbl l = (Lbl)labels.get(i); l.listener = listener; } } public void setEnabled(boolean b) { if(visible == b) return; visible = b; if(errors != null && !errors.isDisposed()) errors.setVisible(b); } public boolean isVisible() { return visible; } public boolean isEnabled() { return (errors != null && errors.isVisible()); } public boolean isDisposed() { return errors == null || errors.isDisposed(); } public void dispose() { if(errors != null) { if(!errors.isDisposed()) errors.dispose(); errors = null; labels.clear(); es = ""; //$NON-NLS-1$ } listener = null; c = null; } public Control createControl(Composite composite) { errors = new ScrolledComposite(composite, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); errors.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_WHITE)); return errors; } public Control getControl() { return errors; } private void createC() { if(c != null && !c.isDisposed()) c.dispose(); c = new Composite(errors, SWT.NONE); errors.setContent(c); GridLayout l = new GridLayout(); l.verticalSpacing = 0; l.marginWidth = 0; c.setLayout(l); c.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_WHITE)); } public void update(XModelObject o) { update(o.get("errors")); //$NON-NLS-1$ } public void update(String err) { String s = err; if(s == null) s = ""; //$NON-NLS-1$ if(es.equals(s)) return; createC(); labels.clear(); String[] el = getErrors(s); for (int i = 0; i < el.length; i++) { Lbl lb = null; if(i < labels.size()) { lb = (Lbl)labels.get(i); } else { lb = new Lbl(); lb.listener = listener; labels.add(lb); } lb.update(el[i], c); } for (int i = labels.size() - 1; i >= el.length; i--) { Lbl lb = (Lbl)labels.get(i); lb.dispose(); labels.remove(i); } errors.getParent().update(); errors.getParent().layout(); c.setSize(c.computeSize(SWT.DEFAULT, SWT.DEFAULT)); c.update(); c.layout(); } String[] getErrors(String s) { if(s == null) s = ""; //$NON-NLS-1$ StringTokenizer st = new StringTokenizer(s, "\n"); //$NON-NLS-1$ String[] rs = new String[st.countTokens()]; for (int i = 0; i < rs.length; i++) rs[i] = st.nextToken(); return rs; } public void go() { if(labels.size() == 0) return; Lbl lb = (Lbl)labels.get(0); lb.go(); } } class Lbl { private L label = null; private String error = ""; //$NON-NLS-1$ private String[] messages = new String[]{"", "", ""}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ private int line = 1; private int position = 1; ErrorSelectionListener listener; public void update(String s, Composite parent) { if(label == null || label.isDisposed()) { Composite c = new Composite(parent, SWT.NONE); c.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); GridLayout l = new GridLayout(); l.marginWidth = 0; c.setLayout(l); c.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_WHITE)); label = new L(c, SWT.NONE); label.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_WHITE)); label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); label.addMouseListener(new SL()); label.setData(messages); } if(s == null) s = ""; //$NON-NLS-1$ if(!error.equals(s)) parse(s); } private void parse(String s) { error = s; line = 1; position = 1; int i = s.indexOf('@'); int j = s.indexOf('@', i + 1); int k = s.indexOf('@', j + 1); if(k > j) { String q = s.substring(j + 1, k); messages[0] = s.substring(0, i); messages[1] = q; messages[2] = s.substring(k + 1); int qi = q.indexOf(':'); if(qi > 0) { line = getInt(q.substring(0, qi), line); position = getInt(q.substring(qi + 1), position); } } else { messages[0] = "ERROR"; messages[1] = "0:0"; //$NON-NLS-1$ messages[2] = s; } if(messages[1] == null || "0:0".equals(messages[1])) { //$NON-NLS-1$ messages[1] = ""; //$NON-NLS-1$ } } int getInt(String s, int def) { if(s == null || s.length() == 0) return def; try { return Integer.parseInt(s); } catch (NumberFormatException e) { ModelUIPlugin.getPluginLog().logError(e); return def; } } public void go() { if(listener != null) listener.errorSelected(line, position); } class SL extends MouseAdapter { public void mouseUp(MouseEvent e) { if(label.isLink(e.x, e.y)) go(); } } public void dispose() { if(label != null && !label.isDisposed()) label.dispose(); } } class L extends Canvas implements PaintListener, MouseMoveListener { Cursor DEF_CURSOR; Cursor HAND_CURSOR; private String[] messages = new String[]{"", "", ""}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ public L(Composite parent, int style) { super (parent, style); addPaintListener(this); addMouseMoveListener(this); DEF_CURSOR = getShell().getDisplay().getSystemCursor(SWT.CURSOR_ARROW); HAND_CURSOR = getShell().getDisplay().getSystemCursor(SWT.CURSOR_HAND); } public void setData(String[] messages) { this.messages = messages; } public Point computeSize (int wHint, int hHint, boolean changed) { int w0 = getStringWidth(getFont(), messages[0]); int w1 = getStringWidth(getFont(), messages[1]); int w2 = getStringWidth(getFont(), messages[2]); return new Point(2 + w0 + 10 + w1 + 10 + w2 + 10, getLineHeight() + 6); } public int getStringWidth(Font font, String str){ int size = 0; GC g = new GC(this); g.setFont(font); for(int i = 0; i < str.length(); i++) { size += g.getCharWidth(str.charAt(i)) + 1; } g.dispose(); return size; } public int getLineHeight() { return getFont().getFontData()[0].getHeight() + 2; } public void paintControl(PaintEvent ev) { GC g = ev.gc; Font f = getFont(); g.setFont(f); int w0 = getStringWidth(f, messages[0]); int w1 = getStringWidth(f, messages[1]); // int w2 = getStringWidth(f, messages[2]); int x = 2; g.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_RED)); g.drawString(messages[0], x, 2); x += w0 + 10; g.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLUE)); g.drawString(messages[1], x, 2); int h = getLineHeight() + 4; g.drawLine(x, h, x + w1 + 2, h); x += w1 + 10; g.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK)); g.drawString(messages[2], x, 2); } public boolean isLink(int x, int y) { Font f = getFont(); int w0 = getStringWidth(f, messages[0]); int w1 = getStringWidth(f, messages[1]); int x1 = 2 + w0 + 10, x2 = x1 + w1; return (x > x1 && x < x2); } public void mouseMove(MouseEvent e) { boolean l = isLink(e.x, e.y); Cursor c = (l) ? HAND_CURSOR : DEF_CURSOR; setCursor(c); } }