1 package be
.nikiroo
.utils
.resources
;
3 import java
.util
.ArrayList
;
7 import java
.util
.TreeMap
;
9 import be
.nikiroo
.utils
.resources
.Meta
.Format
;
12 * A graphical item that reflect a configuration option from the given
18 * the type of {@link Bundle} to edit
20 public class MetaInfo
<E
extends Enum
<E
>> {
21 private final Bundle
<E
> bundle
;
27 private List
<Runnable
> reloadedListeners
= new ArrayList
<Runnable
>();
28 private List
<Runnable
> saveListeners
= new ArrayList
<Runnable
>();
31 private String description
;
33 public MetaInfo(Class
<E
> type
, Bundle
<E
> bundle
, E id
) {
38 this.meta
= type
.getDeclaredField(id
.name()).getAnnotation(
40 } catch (NoSuchFieldException e
) {
41 } catch (SecurityException e
) {
44 // We consider that if a description bundle is used, everything is in it
46 String description
= null;
47 if (bundle
.getDescriptionBundle() != null) {
48 description
= bundle
.getDescriptionBundle().getString(id
);
49 if (description
!= null && description
.trim().isEmpty()) {
54 if (description
== null) {
55 description
= meta
.description();
56 if (meta
.info() != null && !meta
.info().isEmpty()) {
57 description
+= " (" + meta
.info() + ")";
61 String name
= id
.toString();
62 if (name
.length() > 1) {
63 name
= name
.substring(0, 1) + name
.substring(1).toLowerCase();
64 name
= name
.replace("_", " ");
68 this.description
= description
;
74 * THe name of this item, deduced from its ID.
76 * In other words, it is the ID but presented in a displayable form.
80 public String
getName() {
85 * The description of this item (information to present to the user).
87 * @return the description
89 public String
getDescription() {
93 public Format
getFormat() {
98 * The value stored by this item, as a {@link String}.
102 public String
getString() {
106 public String
getDefaultString() {
110 public Boolean
getBoolean() {
111 return BundleHelper
.parseBoolean(getString());
114 public Boolean
getDefaultBoolean() {
115 return BundleHelper
.parseBoolean(getDefaultString());
118 public Character
getCharacter() {
119 return BundleHelper
.parseCharacter(getString());
122 public Character
getDefaultCharacter() {
123 return BundleHelper
.parseCharacter(getDefaultString());
126 public Integer
getInteger() {
127 return BundleHelper
.parseInteger(getString());
130 public Integer
getDefaultInteger() {
131 return BundleHelper
.parseInteger(getDefaultString());
134 public Integer
getColor() {
135 return BundleHelper
.parseColor(getString());
138 public Integer
getDefaultColor() {
139 return BundleHelper
.parseColor(getDefaultString());
142 public List
<String
> getList() {
143 return BundleHelper
.parseList(getString());
146 public List
<String
> getDefaultList() {
147 return BundleHelper
.parseList(getDefaultString());
151 * The value stored by this item, as a {@link String}.
156 public void setString(String value
) {
160 public void setBoolean(boolean value
) {
161 setString(BundleHelper
.fromBoolean(value
));
164 public void setCharacter(char value
) {
165 setString(BundleHelper
.fromCharacter(value
));
168 public void setInteger(int value
) {
169 setString(BundleHelper
.fromInteger(value
));
172 public void setColor(int value
) {
173 setString(BundleHelper
.fromColor(value
));
176 public void setList(List
<String
> value
) {
177 setString(BundleHelper
.fromList(value
));
181 * Reload the value from the {@link Bundle}.
183 public void reload() {
184 value
= bundle
.getString(id
);
185 for (Runnable listener
: reloadedListeners
) {
188 } catch (Exception e
) {
189 // TODO: error management?
195 // listeners will be called AFTER reload
196 public void addReloadedListener(Runnable listener
) {
197 reloadedListeners
.add(listener
);
201 * Save the current value to the {@link Bundle}.
204 for (Runnable listener
: saveListeners
) {
207 } catch (Exception e
) {
208 // TODO: error management?
212 bundle
.setString(id
, value
);
215 // listeners will be called BEFORE save
216 public void addSaveListener(Runnable listener
) {
217 saveListeners
.add(listener
);
221 * Create a list of {@link MetaInfo}, one for each of the item in the given
225 * the type of {@link Bundle} to edit
227 * a class instance of the item type to work on
229 * the {@link Bundle} to sort through
233 static public <E
extends Enum
<E
>> List
<MetaInfo
<E
>> getItems(Class
<E
> type
,
235 List
<MetaInfo
<E
>> list
= new ArrayList
<MetaInfo
<E
>>();
236 for (E id
: type
.getEnumConstants()) {
237 list
.add(new MetaInfo
<E
>(type
, bundle
, id
));
243 // TODO: multiple levels?
244 static public <E
extends Enum
<E
>> Map
<MetaInfo
<E
>, List
<MetaInfo
<E
>>> getGroupedItems(
245 Class
<E
> type
, Bundle
<E
> bundle
) {
246 Map
<MetaInfo
<E
>, List
<MetaInfo
<E
>>> map
= new TreeMap
<MetaInfo
<E
>, List
<MetaInfo
<E
>>>();
247 Map
<MetaInfo
<E
>, List
<MetaInfo
<E
>>> map1
= new TreeMap
<MetaInfo
<E
>, List
<MetaInfo
<E
>>>();
249 List
<MetaInfo
<E
>> ungrouped
= new ArrayList
<MetaInfo
<E
>>();
250 for (MetaInfo
<E
> info
: getItems(type
, bundle
)) {
251 if (info
.meta
.group()) {
252 List
<MetaInfo
<E
>> list
= new ArrayList
<MetaInfo
<E
>>();
254 map1
.put(info
, list
);
260 for (int i
= 0; i
< ungrouped
.size(); i
++) {
261 MetaInfo
<E
> info
= ungrouped
.get(i
);
262 MetaInfo
<E
> group
= findParent(info
, map
.keySet());
264 map
.get(group
).add(info
);
265 ungrouped
.remove(i
--);
269 if (ungrouped
.size() > 0) {
270 map
.put(null, ungrouped
);
276 static private <E
extends Enum
<E
>> MetaInfo
<E
> findParent(MetaInfo
<E
> info
,
277 Set
<MetaInfo
<E
>> candidates
) {
278 MetaInfo
<E
> group
= null;
279 for (MetaInfo
<E
> pcandidate
: candidates
) {
280 if (info
.id
.toString().startsWith(pcandidate
.id
.toString())) {
282 || group
.id
.toString().length() < pcandidate
.id
283 .toString().length()) {