/**
* Copyright (c) 20015 by Brainwy Software Ltda. All Rights Reserved.
* Licensed under the terms of the Eclipse Public License (EPL).
* Please see the license.txt included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
package org.python.pydev.shared_ui.swt;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.forms.widgets.AbstractHyperlink;
import org.eclipse.ui.forms.widgets.Hyperlink;
import org.python.pydev.shared_core.structure.LinkedListWarningOnSlowOperations;
import org.python.pydev.shared_ui.utils.ColorParse;
/**
* A custom link which has the color bound to the HYPERLINK_COLOR in the org.eclipse.ui.workbench preferences.
*/
public class StyledLink extends Hyperlink {
private static final RGB DEFAULT_COLOR = new RGB(0, 51, 153);
private static Color fgColor;
private static List<WeakReference<StyledLink>> weakLinks = new ArrayList<>();
private static void syncLinksFgColor(StyledLink styledLink) {
// Remove old ones before adding a new one.
for (Iterator<WeakReference<StyledLink>> iterator = weakLinks.iterator(); iterator.hasNext();) {
WeakReference<StyledLink> weak = iterator.next();
StyledLink link = weak.get();
if (link == null || link.isDisposed()) {
iterator.remove();
}
}
// Add new
weakLinks.add(new WeakReference<>(styledLink));
if (fgColor == null) {
// Color hasn't been initialized (first creation) let's do it now.
IEclipsePreferences node = InstanceScope.INSTANCE.getNode("org.eclipse.ui.workbench");
String string = node.get("HYPERLINK_COLOR", "");
if (string != null && string.length() > 0) {
fgColor = new Color(Display.getCurrent(), ColorParse.parseRGB(string, DEFAULT_COLOR));
} else {
// Is this even possible?
fgColor = new Color(Display.getCurrent(), DEFAULT_COLOR);
}
// On first initialization, start hearing changes.
node.addPreferenceChangeListener(new IPreferenceChangeListener() {
@Override
public void preferenceChange(PreferenceChangeEvent event) {
if ("HYPERLINK_COLOR".equals(event.getKey())) {
Color old = fgColor;
final Object newValue = event.getNewValue();
if (newValue != null && newValue.toString().length() != 0) {
fgColor = new Color(Display.getCurrent(),
ColorParse.parseRGB(newValue.toString(), DEFAULT_COLOR));
} else {
// Is this even possible?
fgColor = new Color(Display.getCurrent(), DEFAULT_COLOR);
}
// Update active links
for (Iterator<WeakReference<StyledLink>> iterator = weakLinks.iterator(); iterator.hasNext();) {
WeakReference<StyledLink> weak = iterator.next();
StyledLink link = weak.get();
if (link == null || link.isDisposed()) {
iterator.remove();
} else {
link.setForeground(fgColor);
}
}
old.dispose();
}
}
});
}
styledLink.setForeground(fgColor);
}
public StyledLink(Composite parent, int style) {
super(parent, style);
this.setUnderlined(true);
syncLinksFgColor(this);
}
public static class MultiStyledLink extends Composite {
LinkedList<Control> created = new LinkedListWarningOnSlowOperations<>();
public MultiStyledLink(Composite parent, int style) {
super(parent, style);
final RowLayout layout = new RowLayout();
layout.wrap = false;
this.setLayout(layout);
}
public void setText(String text) {
if (this.created.size() > 0) {
for (Control c : this.created) {
c.dispose();
}
this.created.clear();
}
Composite container = this;
int start = text.indexOf("<a>");
int curr = 0;
while (start != -1) {
int end = text.indexOf("</a>", start);
if (start > curr) {
Label label = new Label(container, SWT.NONE);
label.setText(text.substring(curr, start));
created.add(label);
}
StyledLink link = new StyledLink(container, SWT.NONE);
link.setText(text.substring(start + 3, end));
created.add(link);
curr = end + 4;
start = text.indexOf("<a>", curr);
}
if (curr < text.length()) {
Label label = new Label(container, SWT.NONE);
label.setText(text.substring(curr, text.length()));
created.add(label);
}
}
/**
* Get the nTh link created (one is created for each <a> </a>).
*/
public AbstractHyperlink getLink(int i) {
int j = 0;
for (Control c : created) {
if (c instanceof StyledLink) {
if (j == i) {
return (AbstractHyperlink) c;
}
j++;
}
}
return null;
}
}
}