Add second icon for tag

This commit is contained in:
Manfred Karrer 2016-06-18 02:28:22 +02:00
parent ca9eee895f
commit 70b0874599
6 changed files with 147 additions and 124 deletions

View file

@ -7,6 +7,6 @@ public class DevFlags {
private static final Logger log = LoggerFactory.getLogger(DevFlags.class); private static final Logger log = LoggerFactory.getLogger(DevFlags.class);
public static final boolean STRESS_TEST_MODE = false; public static final boolean STRESS_TEST_MODE = false;
public static final boolean DEV_MODE = STRESS_TEST_MODE || true; public static final boolean DEV_MODE = STRESS_TEST_MODE || false;
public static final boolean IS_RELEASE_VERSION = !DEV_MODE && true; public static final boolean IS_RELEASE_VERSION = !DEV_MODE && true;
} }

View file

@ -0,0 +1,135 @@
package io.bitsquare.gui.components;
import io.bitsquare.gui.main.overlays.editor.PeerInfoWithTagEditor;
import io.bitsquare.user.Preferences;
import javafx.geometry.Point2D;
import javafx.scene.Group;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Label;
import javafx.scene.control.Tooltip;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
public class PeerInfoIcon extends Group {
private static final Logger log = LoggerFactory.getLogger(PeerInfoIcon.class);
private final String hostName;
private final String tooltipText;
private final int numTrades;
private final Map<String, String> peerTagMap;
private final Label numTradesLabel;
private final double SIZE = 26;
private final ImageView numTradesCircle;
private final ImageView tagCircle;
private final Label tagLabel;
private final Pane tagPane;
private final Pane numTradesPane;
public PeerInfoIcon(String hostName, String tooltipText, int numTrades) {
this.hostName = hostName;
this.tooltipText = tooltipText;
this.numTrades = numTrades;
peerTagMap = Preferences.INSTANCE.getPeerTagMap();
int maxIndices = 15;
int intValue = 0;
try {
MessageDigest md = MessageDigest.getInstance("SHA1");
byte[] bytes = md.digest(hostName.getBytes());
intValue = Math.abs(((bytes[0] & 0xFF) << 24) | ((bytes[1] & 0xFF) << 16)
| ((bytes[2] & 0xFF) << 8) | (bytes[3] & 0xFF));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
log.error(e.toString());
}
int index = (intValue % maxIndices) + 1;
double saturation = (intValue % 1000) / 1000d;
int red = (intValue >> 8) % 256;
int green = (intValue >> 16) % 256;
int blue = (intValue >> 24) % 256;
Color color = Color.rgb(red, green, blue);
color = color.deriveColor(1, saturation, 1, 1); // reduce saturation
Canvas background = new Canvas(SIZE, SIZE);
GraphicsContext gc = background.getGraphicsContext2D();
gc.setFill(color);
gc.fillOval(0, 0, SIZE, SIZE);
background.setLayoutY(1);
ImageView avatarImageView = new ImageView();
avatarImageView.setId("avatar_" + index);
avatarImageView.setScaleX(intValue % 2 == 0 ? 1d : -1d);
numTradesPane = new Pane();
numTradesPane.relocate(18, 14);
numTradesPane.setMouseTransparent(true);
numTradesCircle = new ImageView();
numTradesCircle.setId("image-green_circle");
numTradesLabel = new Label();
numTradesLabel.relocate(5, 0);
numTradesLabel.setId("ident-num-label");
numTradesCircle.setLayoutX(0.5);
numTradesPane.getChildren().addAll(numTradesCircle, numTradesLabel);
tagPane = new Pane();
tagPane.relocate(18, -2);
tagPane.setMouseTransparent(true);
tagCircle = new ImageView();
tagCircle.setId("image-blue_circle");
tagLabel = new Label();
tagLabel.relocate(4, 0);
tagLabel.setId("ident-num-label");
tagCircle.setLayoutX(0.5);
tagPane.getChildren().addAll(tagCircle, tagLabel);
updatePeerInfoIcon();
getChildren().addAll(background, avatarImageView, tagPane, numTradesPane);
setOnMouseClicked(e -> new PeerInfoWithTagEditor()
.hostName(hostName)
.numTrades(numTrades)
.position(localToScene(new Point2D(0, 0)))
.onSave(newTag -> {
Preferences.INSTANCE.setTagForPeer(hostName, newTag);
updatePeerInfoIcon();
})
.show());
}
private void updatePeerInfoIcon() {
String tag;
if (peerTagMap.containsKey(hostName)) {
tag = peerTagMap.get(hostName);
Tooltip.install(this, new Tooltip(tooltipText + "\nTag: " + tag));
} else {
tag = "";
Tooltip.install(this, new Tooltip(tooltipText));
}
if (!tag.isEmpty())
tagLabel.setText(tag.substring(0, 1));
if (numTrades < 10)
numTradesLabel.setText(String.valueOf(numTrades));
else
numTradesLabel.setText("");
numTradesPane.setVisible(numTrades > 0);
tagPane.setVisible(!tag.isEmpty());
}
}

View file

@ -21,6 +21,7 @@ import io.bitsquare.gui.Navigation;
import io.bitsquare.gui.common.view.ActivatableViewAndModel; import io.bitsquare.gui.common.view.ActivatableViewAndModel;
import io.bitsquare.gui.common.view.FxmlView; import io.bitsquare.gui.common.view.FxmlView;
import io.bitsquare.gui.components.HyperlinkWithIcon; import io.bitsquare.gui.components.HyperlinkWithIcon;
import io.bitsquare.gui.components.PeerInfoIcon;
import io.bitsquare.gui.components.TitledGroupBg; import io.bitsquare.gui.components.TitledGroupBg;
import io.bitsquare.gui.main.MainView; import io.bitsquare.gui.main.MainView;
import io.bitsquare.gui.main.account.AccountView; import io.bitsquare.gui.main.account.AccountView;
@ -32,7 +33,6 @@ import io.bitsquare.gui.main.funds.withdrawal.WithdrawalView;
import io.bitsquare.gui.main.offer.OfferView; import io.bitsquare.gui.main.offer.OfferView;
import io.bitsquare.gui.main.overlays.popups.Popup; import io.bitsquare.gui.main.overlays.popups.Popup;
import io.bitsquare.gui.main.overlays.windows.OfferDetailsWindow; import io.bitsquare.gui.main.overlays.windows.OfferDetailsWindow;
import io.bitsquare.gui.util.ImageUtil;
import io.bitsquare.gui.util.Layout; import io.bitsquare.gui.util.Layout;
import io.bitsquare.locale.BSResources; import io.bitsquare.locale.BSResources;
import io.bitsquare.locale.CryptoCurrency; import io.bitsquare.locale.CryptoCurrency;
@ -689,7 +689,8 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
boolean hasTraded = numPastTrades > 0; boolean hasTraded = numPastTrades > 0;
String tooltipText = hasTraded ? "Offerers onion address: " + hostName + "\n" + String tooltipText = hasTraded ? "Offerers onion address: " + hostName + "\n" +
"You have already traded " + numPastTrades + " times with that offerer." : "Offerers onion address: " + hostName; "You have already traded " + numPastTrades + " times with that offerer." : "Offerers onion address: " + hostName;
Node identIcon = ImageUtil.getIdentIcon(hostName, tooltipText, numPastTrades); Node identIcon = new PeerInfoIcon(hostName, tooltipText, numPastTrades);
setPadding(new Insets(-2, 0, -2, 0));
if (identIcon != null) if (identIcon != null)
setGraphic(identIcon); setGraphic(identIcon);
} else { } else {

View file

@ -20,10 +20,10 @@ package io.bitsquare.gui.main.portfolio.closedtrades;
import io.bitsquare.gui.common.view.ActivatableViewAndModel; import io.bitsquare.gui.common.view.ActivatableViewAndModel;
import io.bitsquare.gui.common.view.FxmlView; import io.bitsquare.gui.common.view.FxmlView;
import io.bitsquare.gui.components.HyperlinkWithIcon; import io.bitsquare.gui.components.HyperlinkWithIcon;
import io.bitsquare.gui.components.PeerInfoIcon;
import io.bitsquare.gui.main.overlays.windows.OfferDetailsWindow; import io.bitsquare.gui.main.overlays.windows.OfferDetailsWindow;
import io.bitsquare.gui.main.overlays.windows.TradeDetailsWindow; import io.bitsquare.gui.main.overlays.windows.TradeDetailsWindow;
import io.bitsquare.gui.util.BSFormatter; import io.bitsquare.gui.util.BSFormatter;
import io.bitsquare.gui.util.ImageUtil;
import io.bitsquare.p2p.NodeAddress; import io.bitsquare.p2p.NodeAddress;
import io.bitsquare.trade.Tradable; import io.bitsquare.trade.Tradable;
import io.bitsquare.trade.Trade; import io.bitsquare.trade.Trade;
@ -31,6 +31,7 @@ import io.bitsquare.trade.offer.OpenOffer;
import javafx.beans.property.ReadOnlyObjectWrapper; import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.collections.transformation.SortedList; import javafx.collections.transformation.SortedList;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.geometry.Insets;
import javafx.scene.Node; import javafx.scene.Node;
import javafx.scene.control.*; import javafx.scene.control.*;
import javafx.scene.layout.VBox; import javafx.scene.layout.VBox;
@ -234,7 +235,8 @@ public class ClosedTradesView extends ActivatableViewAndModel<VBox, ClosedTrades
int numPastTrades = model.getNumPastTrades(newItem.getTradable()); int numPastTrades = model.getNumPastTrades(newItem.getTradable());
String hostName = ((Trade) newItem.getTradable()).getTradingPeerNodeAddress().hostName; String hostName = ((Trade) newItem.getTradable()).getTradingPeerNodeAddress().hostName;
Node identIcon = ImageUtil.getIdentIcon(hostName, "Trading peers onion address: " + hostName, numPastTrades); Node identIcon = new PeerInfoIcon(hostName, "Trading peers onion address: " + hostName, numPastTrades);
setPadding(new Insets(-2, 0, -2, 0));
if (identIcon != null) if (identIcon != null)
setGraphic(identIcon); setGraphic(identIcon);
} else { } else {

View file

@ -21,14 +21,15 @@ import io.bitsquare.common.UserThread;
import io.bitsquare.gui.common.view.ActivatableViewAndModel; import io.bitsquare.gui.common.view.ActivatableViewAndModel;
import io.bitsquare.gui.common.view.FxmlView; import io.bitsquare.gui.common.view.FxmlView;
import io.bitsquare.gui.components.HyperlinkWithIcon; import io.bitsquare.gui.components.HyperlinkWithIcon;
import io.bitsquare.gui.components.PeerInfoIcon;
import io.bitsquare.gui.main.overlays.popups.Popup; import io.bitsquare.gui.main.overlays.popups.Popup;
import io.bitsquare.gui.main.overlays.windows.TradeDetailsWindow; import io.bitsquare.gui.main.overlays.windows.TradeDetailsWindow;
import io.bitsquare.gui.util.BSFormatter; import io.bitsquare.gui.util.BSFormatter;
import io.bitsquare.gui.util.ImageUtil;
import javafx.beans.property.ReadOnlyObjectWrapper; import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.collections.transformation.SortedList; import javafx.collections.transformation.SortedList;
import javafx.event.EventHandler; import javafx.event.EventHandler;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.geometry.Insets;
import javafx.scene.Node; import javafx.scene.Node;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.scene.control.*; import javafx.scene.control.*;
@ -453,7 +454,8 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
boolean hasTraded = numPastTrades > 0; boolean hasTraded = numPastTrades > 0;
String tooltipText = hasTraded ? "Trading peers onion address: " + hostName + "\n" + String tooltipText = hasTraded ? "Trading peers onion address: " + hostName + "\n" +
"You have already traded " + numPastTrades + " times with that peer." : "Trading peers onion address: " + hostName; "You have already traded " + numPastTrades + " times with that peer." : "Trading peers onion address: " + hostName;
Node identIcon = ImageUtil.getIdentIcon(hostName, tooltipText, numPastTrades); Node identIcon = new PeerInfoIcon(hostName, tooltipText, numPastTrades);
setPadding(new Insets(-2, 0, -2, 0));
if (identIcon != null) if (identIcon != null)
setGraphic(identIcon); setGraphic(identIcon);
} else { } else {

View file

@ -18,28 +18,12 @@
package io.bitsquare.gui.util; package io.bitsquare.gui.util;
import com.sun.javafx.tk.quantum.QuantumToolkit; import com.sun.javafx.tk.quantum.QuantumToolkit;
import io.bitsquare.gui.main.overlays.editor.PeerInfoWithTagEditor;
import io.bitsquare.locale.Country; import io.bitsquare.locale.Country;
import io.bitsquare.user.Preferences;
import javafx.geometry.Point2D;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Label;
import javafx.scene.control.Tooltip;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import javafx.scene.image.ImageView; import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
import java.util.UUID;
public class ImageUtil { public class ImageUtil {
private static final Logger log = LoggerFactory.getLogger(ImageUtil.class); private static final Logger log = LoggerFactory.getLogger(ImageUtil.class);
@ -76,105 +60,4 @@ public class ImageUtil {
log.info("isRetina=" + isRetina + " / maxRenderScale=" + maxRenderScale); log.info("isRetina=" + isRetina + " / maxRenderScale=" + maxRenderScale);
return isRetina; return isRetina;
} }
public static Node getIdentIcon(String hostName, String tooltipText, int numTrades) {
if (!hostName.isEmpty()) {
// for testing locally we use a random hostname to get dif. colors
if (hostName.startsWith("localhost"))
hostName = UUID.randomUUID().toString().replace("-", "").substring(0, 16);
int maxIndices = 15;
try {
MessageDigest md = MessageDigest.getInstance("SHA1");
byte[] bytes = md.digest(hostName.getBytes());
int intValue = Math.abs(((bytes[0] & 0xFF) << 24) | ((bytes[1] & 0xFF) << 16)
| ((bytes[2] & 0xFF) << 8) | (bytes[3] & 0xFF));
int index = (intValue % maxIndices) + 1;
double saturation = (intValue % 1000) / 1000d;
int red = (intValue >> 8) % 256;
int green = (intValue >> 16) % 256;
int blue = (intValue >> 24) % 256;
ImageView iconView = new ImageView();
iconView.setId("avatar_" + index);
iconView.setScaleX(intValue % 2 == 0 ? 1d : -1d);
double size = 26;
Group group = new Group();
Map<String, String> peerTagMap = Preferences.INSTANCE.getPeerTagMap();
String tag;
if (peerTagMap.containsKey(hostName)) {
tag = peerTagMap.get(hostName);
Tooltip.install(group, new Tooltip(tooltipText + "\nTag: " + tag));
} else {
tag = "";
Tooltip.install(group, new Tooltip(tooltipText));
}
Pane numTradesPane = new Pane();
numTradesPane.relocate(16, 16);
numTradesPane.setMouseTransparent(true);
ImageView icon = new ImageView();
Label label = new Label();
label.relocate(5, 1);
label.setId("ident-num-label");
icon.setLayoutX(0.5);
numTradesPane.getChildren().addAll(icon, label);
updatePeerInfoIcon(numTrades, tag, numTradesPane, label, icon);
Canvas bg = new Canvas(size, size);
GraphicsContext gc = bg.getGraphicsContext2D();
Color color = Color.rgb(red, green, blue);
color = color.deriveColor(1, saturation, 1, 1); // reduce saturation
gc.setFill(color);
gc.fillOval(0, 0, size, size);
bg.setLayoutY(1);
group.getChildren().addAll(bg, iconView, numTradesPane);
final String finalHostName = hostName;
group.setOnMouseClicked(e -> {
new PeerInfoWithTagEditor()
.hostName(finalHostName)
.numTrades(numTrades)
.position(group.localToScene(new Point2D(0, 0)))
.onSave(newTag -> {
Preferences.INSTANCE.setTagForPeer(finalHostName, newTag);
if (!newTag.isEmpty())
Tooltip.install(group, new Tooltip(tooltipText + "\nTag: " + newTag));
else
Tooltip.install(group, new Tooltip(tooltipText));
updatePeerInfoIcon(numTrades, newTag, numTradesPane, label, icon);
})
.show();
});
return group;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
log.error(e.toString());
return null;
}
} else {
return null;
}
}
private static void updatePeerInfoIcon(int numTrades, String tag, Pane numTradesPane, Label label, ImageView icon) {
if (numTrades == 0 && tag.isEmpty())
label.setText("");
else if (numTrades == 0)
label.setText(tag.substring(0, 1));
else if (numTrades > 9)
label.setText("");
else
label.setText(String.valueOf(numTrades));
numTradesPane.setVisible(!label.getText().isEmpty());
numTradesPane.setManaged(numTradesPane.isVisible());
icon.setId(numTrades > 0 ? "image-green_circle" : "image-blue_circle");
}
} }