Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add icon + color and description to groups #2612

Merged
merged 5 commits into from
Mar 6, 2017
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/main/java/org/jabref/collab/GroupChange.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
import org.jabref.gui.groups.GroupTreeNodeViewModel;
import org.jabref.gui.groups.UndoableModifySubtree;
import org.jabref.gui.undo.NamedCompound;
import org.jabref.logic.groups.DefaultGroupsFactory;
import org.jabref.logic.l10n.Localization;
import org.jabref.model.database.BibDatabase;
import org.jabref.model.groups.AllEntriesGroup;
import org.jabref.model.groups.GroupTreeNode;

class GroupChange extends Change {
Expand All @@ -34,7 +34,7 @@ public boolean makeChange(BasePanel panel, BibDatabase secondary, NamedCompound
root.removeAllChildren();
if (changedGroups == null) {
// I think setting root to null is not possible
root.setGroup(new AllEntriesGroup(Localization.lang("All entries")));
root.setGroup(DefaultGroupsFactory.getAllEntriesGroup());
} else {
// change root group, even though it'll be AllEntries anyway
root.setGroup(changedGroups.getGroup());
Expand Down
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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sort this and the following two variable to a different part of the class declaration. In the current form they are commented as "default colors".

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
41 changes: 35 additions & 6 deletions src/main/java/org/jabref/gui/groups/GroupDialog.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
import javax.swing.SwingConstants;
import javax.swing.event.CaretListener;

import javafx.scene.paint.Color;

import org.jabref.Globals;
import org.jabref.JabRefGUI;
import org.jabref.gui.Dialog;
Expand Down Expand Up @@ -80,6 +82,10 @@ class GroupDialog extends JDialog implements Dialog<AbstractGroup> {
Localization.lang("Refine supergroup: When selected, view entries contained in both this group and its supergroup"));
private final JRadioButton unionButton = new JRadioButton(
Localization.lang("Include subgroups: When selected, view entries contained in this group or its subgroups"));
private final JTextField colorField = new JTextField(GroupDialog.TEXTFIELD_LENGTH);
private final JTextField descriptionField = new JTextField(GroupDialog.TEXTFIELD_LENGTH);
private final JTextField iconField = new JTextField(GroupDialog.TEXTFIELD_LENGTH);

// for KeywordGroup
private final JTextField keywordGroupSearchField = new JTextField(GroupDialog.TEXTFIELD_LENGTH);
private final TextField keywordGroupSearchTerm = new TextField(FieldName.KEYWORDS, "", false);
Expand Down Expand Up @@ -209,7 +215,7 @@ public GroupDialog(JabRefFrame jabrefFrame, AbstractGroup editedGroup) {
// create layout
FormLayout layoutAll = new FormLayout(
"right:pref, 4dlu, fill:600px, 4dlu, fill:pref",
"p, 3dlu, p, 3dlu, p, 0dlu, p, 0dlu, p, 0dlu, p, 3dlu, p, 3dlu, p, "
"p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 0dlu, p, 0dlu, p, 0dlu, p, 3dlu, p, 3dlu, p, "
+ "0dlu, p, 0dlu, p, 3dlu, p, 3dlu, "
+ "p, 3dlu, p, 3dlu, top:80dlu, 9dlu, p, 9dlu, p");

Expand All @@ -221,6 +227,18 @@ public GroupDialog(JabRefFrame jabrefFrame, AbstractGroup editedGroup) {
builderAll.append(nameField);
builderAll.nextLine();
builderAll.nextLine();
builderAll.append(Localization.lang("Description"));
builderAll.append(descriptionField);
builderAll.nextLine();
builderAll.nextLine();
builderAll.append(Localization.lang("Color"));
builderAll.append(colorField);
builderAll.nextLine();
builderAll.nextLine();
builderAll.append(Localization.lang("Icon"));
builderAll.append(iconField);
builderAll.nextLine();
builderAll.nextLine();
builderAll.append(explicitRadioButton, 5);
builderAll.nextLine();
builderAll.nextLine();
Expand Down Expand Up @@ -339,6 +357,14 @@ public void actionPerformed(ActionEvent e) {
autoGroupPersonsField.getText().trim());
}
}
try {
resultingGroup.setColor(Color.valueOf(colorField.getText()));
} catch (IllegalArgumentException ex) {
// Ignore invalid color (we should probably notify the user instead...)
}
resultingGroup.setDescription(descriptionField.getText());
resultingGroup.setIconCode(iconField.getText());

dispose();
} catch (IllegalArgumentException exception) {
jabrefFrame.showMessage(exception.getLocalizedMessage());
Expand All @@ -349,6 +375,9 @@ public void actionPerformed(ActionEvent e) {
ItemListener itemListener = e -> updateComponents();

nameField.addCaretListener(caretListener);
colorField.addCaretListener(caretListener);
descriptionField.addCaretListener(caretListener);
iconField.addCaretListener(caretListener);
keywordGroupSearchField.addCaretListener(caretListener);
keywordGroupSearchTerm.addCaretListener(caretListener);
keywordGroupCaseSensitive.addItemListener(itemListener);
Expand All @@ -363,9 +392,13 @@ public void actionPerformed(ActionEvent e) {
explicitRadioButton.setSelected(true);
setContext(GroupHierarchyType.INDEPENDENT);
} else {
nameField.setText(editedGroup.getName());
colorField.setText(editedGroup.getColor().map(Color::toString).orElse(""));
descriptionField.setText(editedGroup.getDescription().orElse(""));
iconField.setText(editedGroup.getIconCode().orElse(""));

if (editedGroup.getClass() == WordKeywordGroup.class) {
WordKeywordGroup group = (WordKeywordGroup) editedGroup;
nameField.setText(group.getName());
keywordGroupSearchField.setText(group.getSearchField());
keywordGroupSearchTerm.setText(group.getSearchExpression());
keywordGroupCaseSensitive.setSelected(group.isCaseSensitive());
Expand All @@ -374,7 +407,6 @@ public void actionPerformed(ActionEvent e) {
setContext(editedGroup.getHierarchicalContext());
} else if (editedGroup.getClass() == RegexKeywordGroup.class) {
RegexKeywordGroup group = (RegexKeywordGroup) editedGroup;
nameField.setText(group.getName());
keywordGroupSearchField.setText(group.getSearchField());
keywordGroupSearchTerm.setText(group.getSearchExpression());
keywordGroupCaseSensitive.setSelected(group.isCaseSensitive());
Expand All @@ -383,18 +415,15 @@ public void actionPerformed(ActionEvent e) {
setContext(editedGroup.getHierarchicalContext());
} else if (editedGroup.getClass() == SearchGroup.class) {
SearchGroup group = (SearchGroup) editedGroup;
nameField.setText(group.getName());
searchGroupSearchExpression.setText(group.getSearchExpression());
searchGroupCaseSensitive.setSelected(group.isCaseSensitive());
searchGroupRegExp.setSelected(group.isRegularExpression());
searchRadioButton.setSelected(true);
setContext(editedGroup.getHierarchicalContext());
} else if (editedGroup.getClass() == ExplicitGroup.class) {
nameField.setText(editedGroup.getName());
explicitRadioButton.setSelected(true);
setContext(editedGroup.getHierarchicalContext());
} else if (editedGroup.getClass() == AutomaticKeywordGroup.class) {
nameField.setText(editedGroup.getName());
autoRadioButton.setSelected(true);
setContext(editedGroup.getHierarchicalContext());

Expand Down
Loading