Skip to content

Commit

Permalink
Show icon (in correct color) and description (as tooltip) in groups p…
Browse files Browse the repository at this point in the history
…anel
  • Loading branch information
tobiasdiez committed Mar 4, 2017
1 parent 5034747 commit 6514281
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 108 deletions.
184 changes: 93 additions & 91 deletions src/main/java/org/jabref/gui/IconTheme.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,24 +32,21 @@

public class IconTheme {

public static Font FONT;
public static Font FONT_16;
public static javafx.scene.text.Font FX_FONT;

/* Colors */
// JabRef's default colors
public static final Color DEFAULT_COLOR = JabRefPreferences.getInstance().getColor(JabRefPreferences.ICON_ENABLED_COLOR);
public static final Color DEFAULT_DISABLED_COLOR = JabRefPreferences.getInstance().getColor(JabRefPreferences.ICON_DISABLED_COLOR);
private static final String DEFAULT_ICON_PATH = "/images/external/red.png";
private static final Log LOGGER = LogFactory.getLog(IconTheme.class);
private static final Map<String, String> KEY_TO_ICON = readIconThemeFile(
IconTheme.class.getResource("/images/Icons.properties"), "/images/external/");
public static Font FONT;

// Christmas edition
//public static final Color DEFAULT_COLOR = new Color(0x155115);
//public static final Color DEFAULT_DISABLED_COLOR = new Color(0x990000);

private static final Map<String, String> KEY_TO_ICON = readIconThemeFile(
IconTheme.class.getResource("/images/Icons.properties"), "/images/external/");
private static final String DEFAULT_ICON_PATH = "/images/external/red.png";

private static final Log LOGGER = LogFactory.getLog(IconTheme.class);
public static Font FONT_16;
public static javafx.scene.text.Font FX_FONT;

static {
try (InputStream stream = FontBasedIcon.class.getResourceAsStream("/fonts/materialdesignicons-webfont.ttf")) {
Expand All @@ -63,6 +60,90 @@ public class IconTheme {
}
}

public static javafx.scene.paint.Color getDefaultColor() {
return javafx.scene.paint.Color.rgb(DEFAULT_COLOR.getRed(), DEFAULT_COLOR.getGreen(), DEFAULT_COLOR.getBlue(), DEFAULT_COLOR.getAlpha() / 255.0);
}

/**
* Constructs an ImageIcon for the image representing the given function, in the resource
* file listing images.
*
* @param name The name of the icon, such as "open", "save", "saveAs" etc.
* @return The ImageIcon for the function.
*/
public static ImageIcon getImage(String name) {
return new ImageIcon(getIconUrl(name));
}

public static Image getJabRefImageFX() {
return getImageFX("jabrefIcon48");
}

/**
* Constructs an {@link Image} for the image representing the given function, in the resource
* file listing images.
*
* @param name The name of the icon, such as "open", "save", "saveAs" etc.
* @return The {@link Image} for the function.
*/
public static Image getImageFX(String name) {
return new Image(getIconUrl(name).toString());
}

/**
* Looks up the URL for the image representing the given function, in the resource
* file listing images.
*
* @param name The name of the icon, such as "open", "save", "saveAs" etc.
* @return The URL to the actual image to use.
*/
public static URL getIconUrl(String name) {
String key = Objects.requireNonNull(name, "icon name");
if (!KEY_TO_ICON.containsKey(key)) {
LOGGER.warn("Could not find icon url by name " + name + ", so falling back on default icon "
+ DEFAULT_ICON_PATH);
}
String path = KEY_TO_ICON.getOrDefault(key, DEFAULT_ICON_PATH);
return Objects.requireNonNull(IconTheme.class.getResource(path), "Path must not be null for key " + key);
}

/**
* Read a typical java property url into a Map. Currently doesn't support escaping
* of the '=' character - it simply looks for the first '=' to determine where the key ends.
* Both the key and the value is trimmed for whitespace at the ends.
*
* @param url The URL to read information from.
* @param prefix A String to prefix to all values read. Can represent e.g. the directory where icon files are to be
* found.
* @return A Map containing all key-value pairs found.
*/
// FIXME: prefix can be removed?!
private static Map<String, String> readIconThemeFile(URL url, String prefix) {
Objects.requireNonNull(url, "url");
Objects.requireNonNull(prefix, "prefix");

Map<String, String> result = new HashMap<>();

try (BufferedReader in = new BufferedReader(
new InputStreamReader(url.openStream(), StandardCharsets.ISO_8859_1))) {
String line;
while ((line = in.readLine()) != null) {
if (!line.contains("=")) {
continue;
}

int index = line.indexOf('=');
String key = line.substring(0, index).trim();
String value = prefix + line.substring(index + 1).trim();
result.put(key, value);
}
} catch (IOException e) {
LOGGER.warn("Unable to read default icon theme.", e);
}
return result;
}


public enum JabRefIcon {

ADD("\uf416") /*css: mdi-plus-box*/,
Expand Down Expand Up @@ -165,6 +246,8 @@ public enum JabRefIcon {
BLOG("\uf46b"), /* css: rss */
GLOBAL_SEARCH("\uF1E7"), /* css: earth */
DATE_PICKER("\uF0ED;"), /* css: calendar */
DEFAULT_GROUP_ICON("\uF316"), /* css: label-outline */
ALL_ENTRIES_GROUP_ICON("\uF1B8"), /* css: database */
// STILL MISSING:
GROUP_REGULAR("\uF4E6", Color.RED);

Expand Down Expand Up @@ -259,85 +342,4 @@ public FontBasedIcon createWithNewColor(Color newColor) {
}

}


/**
* Constructs an ImageIcon for the image representing the given function, in the resource
* file listing images.
*
* @param name The name of the icon, such as "open", "save", "saveAs" etc.
* @return The ImageIcon for the function.
*/
public static ImageIcon getImage(String name) {
return new ImageIcon(getIconUrl(name));
}

public static Image getJabRefImageFX() {
return getImageFX("jabrefIcon48");
}

/**
* Constructs an {@link Image} for the image representing the given function, in the resource
* file listing images.
*
* @param name The name of the icon, such as "open", "save", "saveAs" etc.
* @return The {@link Image} for the function.
*/
public static Image getImageFX(String name) {
return new Image(getIconUrl(name).toString());
}


/**
* Looks up the URL for the image representing the given function, in the resource
* file listing images.
*
* @param name The name of the icon, such as "open", "save", "saveAs" etc.
* @return The URL to the actual image to use.
*/
public static URL getIconUrl(String name) {
String key = Objects.requireNonNull(name, "icon name");
if (!KEY_TO_ICON.containsKey(key)) {
LOGGER.warn("Could not find icon url by name " + name + ", so falling back on default icon "
+ DEFAULT_ICON_PATH);
}
String path = KEY_TO_ICON.getOrDefault(key, DEFAULT_ICON_PATH);
return Objects.requireNonNull(IconTheme.class.getResource(path), "Path must not be null for key " + key);
}

/**
* Read a typical java property url into a Map. Currently doesn't support escaping
* of the '=' character - it simply looks for the first '=' to determine where the key ends.
* Both the key and the value is trimmed for whitespace at the ends.
*
* @param url The URL to read information from.
* @param prefix A String to prefix to all values read. Can represent e.g. the directory
* where icon files are to be found.
* @return A Map containing all key-value pairs found.
*/
// FIXME: prefix can be removed?!
private static Map<String, String> readIconThemeFile(URL url, String prefix) {
Objects.requireNonNull(url, "url");
Objects.requireNonNull(prefix, "prefix");

Map<String, String> result = new HashMap<>();

try (BufferedReader in = new BufferedReader(
new InputStreamReader(url.openStream(), StandardCharsets.ISO_8859_1))) {
String line;
while ((line = in.readLine()) != null) {
if (!line.contains("=")) {
continue;
}

int index = line.indexOf('=');
String key = line.substring(0, index).trim();
String value = prefix + line.substring(index + 1).trim();
result.put(key, value);
}
} catch (IOException e) {
LOGGER.warn("Unable to read default icon theme.", e);
}
return result;
}
}
1 change: 0 additions & 1 deletion src/main/java/org/jabref/gui/Main.css
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@
.icon {
-fx-font-family: 'Material Design Icons';
-fx-font-size: 16.0;
-fx-fill : -fx-mid-text-color;
}

.tooltip {
Expand Down
18 changes: 11 additions & 7 deletions src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,17 @@
import javafx.beans.property.SimpleIntegerProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.paint.Color;

import org.jabref.gui.IconTheme;
import org.jabref.gui.StateManager;
import org.jabref.gui.util.BindingsHelper;
import org.jabref.logic.groups.DefaultGroupsFactory;
import org.jabref.logic.l10n.Localization;
import org.jabref.logic.layout.format.LatexToUnicodeFormatter;
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.event.EntryEvent;
import org.jabref.model.groups.AbstractGroup;
import org.jabref.model.groups.AllEntriesGroup;
import org.jabref.model.groups.AutomaticGroup;
import org.jabref.model.groups.GroupTreeNode;
import org.jabref.model.strings.StringUtil;
Expand All @@ -37,7 +37,6 @@ public class GroupNodeViewModel {

private final String displayName;
private final boolean isRoot;
private final String iconCode;
private final ObservableList<GroupNodeViewModel> children;
private final BibDatabaseContext databaseContext;
private final GroupTreeNode groupNode;
Expand All @@ -53,7 +52,6 @@ public GroupNodeViewModel(BibDatabaseContext databaseContext, StateManager state
LatexToUnicodeFormatter formatter = new LatexToUnicodeFormatter();
displayName = formatter.format(groupNode.getName());
isRoot = groupNode.isRoot();
iconCode = "";
if (groupNode.getGroup() instanceof AutomaticGroup) {
AutomaticGroup automaticGroup = (AutomaticGroup) groupNode.getGroup();

Expand All @@ -72,6 +70,8 @@ public GroupNodeViewModel(BibDatabaseContext databaseContext, StateManager state
hasChildren.bind(Bindings.isNotEmpty(children));
hits = new SimpleIntegerProperty(0);
calculateNumberOfMatches();
expandedProperty.set(groupNode.getGroup().isExpanded());
expandedProperty.addListener((observable, oldValue, newValue) -> groupNode.getGroup().setExpanded(newValue));

// Register listener
databaseContext.getDatabase().registerListener(this);
Expand Down Expand Up @@ -124,7 +124,7 @@ public boolean isRoot() {
}

public String getDescription() {
return "Some group named " + getDisplayName();
return groupNode.getGroup().getDescription().orElse("");
}

public SimpleIntegerProperty getHits() {
Expand All @@ -147,7 +147,7 @@ public String toString() {
return "GroupNodeViewModel{" +
"displayName='" + displayName + '\'' +
", isRoot=" + isRoot +
", iconCode='" + iconCode + '\'' +
", iconCode='" + getIconCode() + '\'' +
", children=" + children +
", databaseContext=" + databaseContext +
", groupNode=" + groupNode +
Expand All @@ -161,7 +161,7 @@ public int hashCode() {
}

public String getIconCode() {
return iconCode;
return groupNode.getGroup().getIconCode().orElse(IconTheme.JabRefIcon.DEFAULT_GROUP_ICON.getCode());
}

public ObservableList<GroupNodeViewModel> getChildren() {
Expand Down Expand Up @@ -201,4 +201,8 @@ void toggleExpansion() {
boolean isMatchedBy(String searchString) {
return StringUtil.isBlank(searchString) || getDisplayName().contains(searchString);
}

public Color getColor() {
return groupNode.getGroup().getColor().orElse(IconTheme.getDefaultColor());
}
}
3 changes: 0 additions & 3 deletions src/main/java/org/jabref/gui/groups/GroupTree.css
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,6 @@
}

.tree-table-row-cell > .tree-table-cell > .icon {
-fx-font-family: 'MaterialDesignIcons';
-fx-font-size: 16;
-fx-fill: #5e5f5e;
-fx-translate-x: -5px;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public void initialize() {
mainColumn.setCellValueFactory(cellData -> cellData.getValue().valueProperty());
mainColumn.setCellFactory(new ViewModelTreeTableCellFactory<GroupNodeViewModel, GroupNodeViewModel>()
.withText(GroupNodeViewModel::getDisplayName)
.withIcon(GroupNodeViewModel::getIconCode)
.withIcon(GroupNodeViewModel::getIconCode, GroupNodeViewModel::getColor)
.withTooltip(GroupNodeViewModel::getDescription)
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import javafx.scene.control.TreeTableCell;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Paint;
import javafx.scene.text.Text;
import javafx.util.Callback;

Expand All @@ -32,10 +33,11 @@ public ViewModelTreeTableCellFactory<S, T> withGraphic(Callback<S, Node> toGraph
return this;
}

public ViewModelTreeTableCellFactory<S, T> withIcon(Callback<S, String> toIcon) {
public ViewModelTreeTableCellFactory<S, T> withIcon(Callback<S, String> toIcon, Callback<S, Paint> toColor) {
this.toGraphic = viewModel -> {
Text graphic = new Text(toIcon.call(viewModel));
graphic.getStyleClass().add("icon");
graphic.setFill(toColor.call(viewModel));
return graphic;
};
return this;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package org.jabref.logic.groups;

import org.jabref.gui.IconTheme;
import org.jabref.logic.l10n.Localization;
import org.jabref.model.groups.AllEntriesGroup;

public class DefaultGroupsFactory {
public static AllEntriesGroup getAllEntriesGroup() {
return new AllEntriesGroup(Localization.lang("All entries"));
AllEntriesGroup group = new AllEntriesGroup(Localization.lang("All entries"));
group.setIconCode(IconTheme.JabRefIcon.ALL_ENTRIES_GROUP_ICON.getCode());
return group;
}
}
6 changes: 3 additions & 3 deletions src/main/java/org/jabref/model/groups/AbstractGroup.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ public abstract class AbstractGroup implements SearchMatcher {
* The hierarchical context of the group.
*/
protected final GroupHierarchyType context;
protected Optional<Color> color;
protected Optional<Color> color = Optional.empty();
protected boolean isExpanded = true;
protected Optional<String> description;
protected Optional<String> iconCode;
protected Optional<String> description = Optional.empty();
protected Optional<String> iconCode = Optional.empty();

protected AbstractGroup(String name, GroupHierarchyType context) {
this.name = name;
Expand Down

0 comments on commit 6514281

Please sign in to comment.