-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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 auto group colour assignment #10521
Add auto group colour assignment #10521
Conversation
I tried this PR. Can confirm the groups automatically get assigned different group colours. I am more of a user, so i will not comment on coding details. Feedback
To conclude: I personally would prefer if this feature was optional and activated by user choice. |
You might find the group
and then you get it with any children |
I would recommend testing this implementation with a database with thousands of groups and subgroups and a large groups tree depth (e.g., a depth of 20 to 30). I wonder how things will look like in that case. |
Sorry, I forgot to mention that users need to click the button under the colour picker labeled 'Auto:OFF' to activate this feature. However, I'm not sure if this setting is intuitive. |
A checkbox would be more intuitive than a button to enable/disable the feature |
I would expect it as follows: New group creation: color automatically set Existing group edit: Button next to the color with "refresh" circle as icon. On click: New auto color is assigned. No need for a setting to activate and deactivate |
Should I provide an option for users to enable this feature themselves in order to adhere to the rule of avoiding unnecessary usage of color? |
Good point with too many colors. I am currently afraid of the WTFs of the checkbox present at group modification. Because checking and unchecking has no effect there. In case there is a help button next to it linking to user documentation for group coloring, it is OK for me. Add a section to the groups help in user-documentstion repo. |
Currently, the automatic color assignment after clicking the checkbox will only take effect the next time the dialog box is opened. I can change it so that when the user clicks the checkbox, a random color is immediately generated and replaces the current color in the color picker (if clicked again, it will immediately revert to gray). If it's made this way, it would be more intuitive, so would it eliminate the need for a help button? Additionally, do I need to add a refresh button? |
Yes this sounds like a good idea |
…to-group' into 7613-assign-color-automatically-to-group
I would remove that, because the user can choose another color by his own. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code seemed to guess random colors and evaluate them. The issue wanted to work on existing colors.
Attached a new calculation based on "Newton-Cotes formulas"
private static final List<Color> TOP_LEVEL_COLORS = new ArrayList<>(); | ||
private static final int TRIES = 10000; | ||
|
||
// Get most distinct color |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove that comment - it is the same as the method name and thus obsolete
(and this is a good thing, because this is an indication that the method names are well-chosen)
return mostDistinct; | ||
} | ||
|
||
// Generate color for top groups |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove comment
return useRandom ? getDistinctHue() : IconTheme.getDefaultGroupColor(); | ||
} | ||
|
||
// Generate color for subgroups |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove comment
private static final int TRIES = 10000; | ||
|
||
// Get most distinct color | ||
private static Color getDistinctHue() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method doesn't take the existing colors into consideration.
Please adjust the algorithm to use the colors of the existing subgroup (or all the top level groups) and then calculcate THE ONE most distant color.
I would just work with H
, not S
and V
Some inspiration
(read on later)
import java.awt.Color;
import java.util.ArrayList;
import java.util.List;
public class ColorDistance {
// Find a Hue value that maximizes the sum of distances
public static float findFurthestHue(List<Color> colors) {
float maxDistanceSum = -1;
float furthestHue = 0;
// Iterate over the Hue space [0, 1)
for (int h = 0; h < 360; h++) {
float candidateHue = h / 360.0f;
double distanceSum = 0;
for (Color color : colors) {
float[] currentHSV = new float[3];
Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), currentHSV);
float dh = Math.abs(candidateHue - currentHSV[0]);
dh = Math.min(dh, 1.0f - dh); // Hue is circular
distanceSum += dh;
}
if (distanceSum > maxDistanceSum) {
maxDistanceSum = distanceSum;
furthestHue = candidateHue;
}
}
return furthestHue;
}
public static void main(String[] args) {
// Sample list of colors
List<Color> colors = new ArrayList<>();
colors.add(new Color(255, 0, 0)); // Red
colors.add(new Color(0, 255, 0)); // Green
colors.add(new Color(0, 0, 255)); // Blue
colors.add(new Color(255, 255, 0)); // Yellow
// Find a Hue that is furthest away from all colors in the list
float furthestHue = findFurthestHue(colors);
// Output the result
System.out.println("Furthest Hue: " + furthestHue);
}
}
Instead of plainly searching, one can use the Newton-Cotes formula
.
Applying Newton-Cotes formulas (like the "Trapezoidal Rule" or "Simpson's Rule") used in numerical integration, we can attempt to optimize our search instead of brute-forcing the entire color space.
One approach to find a value that maximizes the sum of distances is to use a heuristic like the median. For circular quantities like Hue, you may want to convert them to a linear space, e.g., by using the sine and cosine values, before finding the average or median.
import java.awt.Color;
import java.util.ArrayList;
import java.util.List;
public class ColorDistance {
public static float findFurthestHue(List<Color> colors) {
double sumSin = 0;
double sumCos = 0;
for (Color color : colors) {
float[] hsv = new float[3];
Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), hsv);
double angle = hsv[0] * 2 * Math.PI;
sumSin += Math.sin(angle);
sumCos += Math.cos(angle);
}
double meanAngle = Math.atan2(-sumSin, -sumCos) + Math.PI;
float furthestHue = (float) (meanAngle / (2 * Math.PI));
return furthestHue;
}
public static void main(String[] args) {
// Sample list of colors
List<Color> colors = new ArrayList<>();
colors.add(new Color(255, 0, 0)); // Red
colors.add(new Color(0, 255, 0)); // Green
colors.add(new Color(0, 0, 255)); // Blue
colors.add(new Color(255, 255, 0)); // Yellow
// Find a Hue that is furthest away from all colors in the list
float furthestHue = findFurthestHue(colors);
// Output the result
System.out.println("Furthest Hue: " + furthestHue);
}
}
DevCall discusssions:
Decisions:
We will then check the feedback |
When pressing "OK" the group gets assigned a color. But a user may want to have NO color. --> We need a checkbox for having a color. If the checkbox is disabled, JabRef removes the color at "OK". Can only be undone if the dialog is NOT closed. |
Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com>
First shot for calculated auto coloring is there. Screenshot: The first color of the subgroup is the color of the parent group a bit darker. Not sure if that is a good idea, but I did not want to start totally random at a sub group Code smell: Auto coloring is saved in a global variable - and not in the preference I needed some |
Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com>
Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com>
Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com>
Assign colour with maximal HSV distance when create a new group. Greatest distance is used for top level groups. I have also implemented method for sub level groups using single hue scale, but I am having trouble distinguishing between top level groups and sub level groups while creating a new group now. So, the colour of the sub group in the screenshot does not use the same hue scale as their top level group.
Fixes #7613
This is my first pr, I appreciate feedback from all aspects. If there's anything I did wrong please correct me.
Mandatory checks
CHANGELOG.md
described in a way that is understandable for the average user (if applicable)