/*******************************************************************************
* 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);
}
}