]> git.ktnx.net Git - mobile-ledger.git/blob - app/src/main/java/net/ktnx/mobileledger/utils/Colors.java
work around float weirdness causing 0/360 to become negative
[mobile-ledger.git] / app / src / main / java / net / ktnx / mobileledger / utils / Colors.java
1 package net.ktnx.mobileledger.utils;
2
3 import android.app.Activity;
4 import android.content.res.Resources;
5 import androidx.annotation.ColorInt;
6 import androidx.annotation.ColorLong;
7 import android.util.Log;
8 import android.util.TypedValue;
9
10 import net.ktnx.mobileledger.R;
11 import net.ktnx.mobileledger.model.Data;
12 import net.ktnx.mobileledger.model.MobileLedgerProfile;
13
14 public class Colors {
15     public static final int DEFAULT_HUE_DEG = 261;
16     public static @ColorInt
17     int accent;
18     @ColorInt
19     public static int tableRowLightBG;
20     @ColorInt
21     public static int tableRowDarkBG;
22     @ColorInt
23     public static int primary, defaultTextColor;
24     public static int profileThemeId = -1;
25
26     public static ObservableValue<Integer> themeWatch = new ObservableValue<>(0);
27     public static void refreshColors(Resources.Theme theme) {
28         TypedValue tv = new TypedValue();
29         theme.resolveAttribute(R.attr.table_row_dark_bg, tv, true);
30         tableRowDarkBG = tv.data;
31         theme.resolveAttribute(R.attr.table_row_light_bg, tv, true);
32         tableRowLightBG = tv.data;
33         theme.resolveAttribute(R.attr.colorPrimary, tv, true);
34         primary = tv.data;
35         theme.resolveAttribute(android.R.color.tab_indicator_text, tv, true);
36         defaultTextColor = tv.data;
37         theme.resolveAttribute(R.attr.colorAccent, tv, true);
38         accent = tv.data;
39
40         // trigger theme observers
41         themeWatch.notifyObservers();
42     }
43     public static @ColorLong
44     long hsvaColor(float hue, float saturation, float value, float alpha) {
45         if (alpha < 0 || alpha > 1)
46             throw new IllegalArgumentException("alpha must be between 0 and 1");
47
48         @ColorLong long rgb = hsvTriplet(hue, saturation, value);
49
50         long a_bits = Math.round(255 * alpha);
51         return (a_bits << 24) | rgb;
52     }
53     public static @ColorInt
54     int hsvColor(float hue, float saturation, float value) {
55         return 0xff000000 | hsvTriplet(hue, saturation, value);
56     }
57     public static @ColorInt
58     int hsvTriplet(float hue, float saturation, float value) {
59         @ColorLong long result;
60         int r, g, b;
61
62         if ((hue < -0.00005) || (hue > 1.0000005) || (saturation < 0) || (saturation > 1) ||
63             (value < 0) || (value > 1)) throw new IllegalArgumentException(String.format(
64                 "hue, saturation, value and alpha must all be between 0 and 1. Arguments given: " +
65                 "hue=%1.5f, sat=%1.5f, val=%1.5f", hue, saturation, value));
66
67         int h = (int) (hue * 6);
68         float f = hue * 6 - h;
69         float p = value * (1 - saturation);
70         float q = value * (1 - f * saturation);
71         float t = value * (1 - (1 - f) * saturation);
72
73         switch (h) {
74             case 0:
75             case 6:
76                 return tupleToColor(value, t, p);
77             case 1:
78                 return tupleToColor(q, value, p);
79             case 2:
80                 return tupleToColor(p, value, t);
81             case 3:
82                 return tupleToColor(p, q, value);
83             case 4:
84                 return tupleToColor(t, p, value);
85             case 5:
86                 return tupleToColor(value, p, q);
87             default:
88                 throw new RuntimeException(String.format("Unexpected value for h (%d) while " +
89                                                          "converting hsv(%1.2f, %1.2f, %1.2f) to " +
90                                                          "rgb", h, hue, saturation, value));
91         }
92     }
93
94     public static @ColorInt
95     int tupleToColor(float r, float g, float b) {
96         int r_int = Math.round(255 * r);
97         int g_int = Math.round(255 * g);
98         int b_int = Math.round(255 * b);
99         return (r_int << 16) | (g_int << 8) | b_int;
100     }
101     public static @ColorInt
102     int getPrimaryColorForHue(int degrees) {
103         // 0/360f becomes -0.000something for some reason
104         if (degrees == 0) return getPrimaryColorForHue(0f);
105         return getPrimaryColorForHue(degrees / 360f);
106     }
107     public static @ColorInt
108     int getPrimaryColorForHue(float hue) {
109         int result = hsvColor(hue, 0.61f, 0.95f);
110         Log.d("colors", String.format("getPrimaryColorForHue(%1.2f) = %x", hue, result));
111         return result;
112     }
113     public static void setupTheme(Activity activity) {
114         MobileLedgerProfile profile = Data.profile.get();
115         if (profile != null) {
116             switch (Data.profile.get().getThemeId()) {
117                 case 0:
118                     activity.setTheme(R.style.AppTheme_NoActionBar_0);
119                     break;
120                 case 15:
121                     activity.setTheme(R.style.AppTheme_NoActionBar_15);
122                     break;
123                 case 30:
124                     activity.setTheme(R.style.AppTheme_NoActionBar_30);
125                     break;
126                 case 45:
127                     activity.setTheme(R.style.AppTheme_NoActionBar_45);
128                     break;
129                 case 60:
130                     activity.setTheme(R.style.AppTheme_NoActionBar_60);
131                     break;
132                 case 75:
133                     activity.setTheme(R.style.AppTheme_NoActionBar_75);
134                     break;
135                 case 90:
136                     activity.setTheme(R.style.AppTheme_NoActionBar_90);
137                     break;
138                 case 105:
139                     activity.setTheme(R.style.AppTheme_NoActionBar_105);
140                     break;
141                 case 120:
142                     activity.setTheme(R.style.AppTheme_NoActionBar_120);
143                     break;
144                 case 135:
145                     activity.setTheme(R.style.AppTheme_NoActionBar_135);
146                     break;
147                 case 150:
148                     activity.setTheme(R.style.AppTheme_NoActionBar_150);
149                     break;
150                 case 165:
151                     activity.setTheme(R.style.AppTheme_NoActionBar_165);
152                     break;
153                 case 180:
154                     activity.setTheme(R.style.AppTheme_NoActionBar_180);
155                     break;
156                 case 195:
157                     activity.setTheme(R.style.AppTheme_NoActionBar_195);
158                     break;
159                 case 210:
160                     activity.setTheme(R.style.AppTheme_NoActionBar_210);
161                     break;
162                 case 225:
163                     activity.setTheme(R.style.AppTheme_NoActionBar_225);
164                     break;
165                 case 240:
166                     activity.setTheme(R.style.AppTheme_NoActionBar_240);
167                     break;
168                 case 255:
169                     activity.setTheme(R.style.AppTheme_NoActionBar_255);
170                     break;
171                 case 270:
172                     activity.setTheme(R.style.AppTheme_NoActionBar_270);
173                     break;
174                 case 285:
175                     activity.setTheme(R.style.AppTheme_NoActionBar_285);
176                     break;
177                 case 300:
178                     activity.setTheme(R.style.AppTheme_NoActionBar_300);
179                     break;
180                 case 315:
181                     activity.setTheme(R.style.AppTheme_NoActionBar_315);
182                     break;
183                 case 330:
184                     activity.setTheme(R.style.AppTheme_NoActionBar_330);
185                     break;
186                 case 345:
187                     activity.setTheme(R.style.AppTheme_NoActionBar_345);
188                     break;
189                 default:
190                     activity.setTheme(R.style.AppTheme_NoActionBar);
191             }
192         }
193         else activity.setTheme(R.style.AppTheme_NoActionBar);
194
195         refreshColors(activity.getTheme());
196     }
197
198 }