d95e98c986a0e53266bbd203f95efa90066a7580
1 package be
.nikiroo
.utils
.resources
;
3 import java
.util
.ArrayList
;
4 import java
.util
.Iterator
;
8 import java
.util
.TreeMap
;
10 import be
.nikiroo
.utils
.resources
.Meta
.Format
;
13 * A graphical item that reflect a configuration option from the given
19 * the type of {@link Bundle} to edit
21 public class MetaInfo
<E
extends Enum
<E
>> implements Iterable
<MetaInfo
<E
>> {
22 private final Bundle
<E
> bundle
;
26 private List
<MetaInfo
<E
>> children
= new ArrayList
<MetaInfo
<E
>>();
29 private List
<Runnable
> reloadedListeners
= new ArrayList
<Runnable
>();
30 private List
<Runnable
> saveListeners
= new ArrayList
<Runnable
>();
33 private String description
;
35 public MetaInfo(Class
<E
> type
, Bundle
<E
> bundle
, E id
) {
40 this.meta
= type
.getDeclaredField(id
.name()).getAnnotation(
42 } catch (NoSuchFieldException e
) {
43 } catch (SecurityException e
) {
46 // We consider that if a description bundle is used, everything is in it
48 String description
= null;
49 if (bundle
.getDescriptionBundle() != null) {
50 description
= bundle
.getDescriptionBundle().getString(id
);
51 if (description
!= null && description
.trim().isEmpty()) {
56 if (description
== null) {
57 description
= meta
.description();
58 if (description
== null) {
61 if (meta
.info() != null && !meta
.info().isEmpty()) {
62 if (!description
.isEmpty()) {
63 description
+= "\n\n";
65 description
+= meta
.info();
69 String name
= id
.toString();
70 if (name
.length() > 1) {
71 name
= name
.substring(0, 1) + name
.substring(1).toLowerCase();
72 name
= name
.replace("_", " ");
76 this.description
= description
;
82 * THe name of this item, deduced from its ID.
84 * In other words, it is the ID but presented in a displayable form.
88 public String
getName() {
93 * The description of this item (information to present to the user).
95 * @return the description
97 public String
getDescription() {
101 public Format
getFormat() {
102 return meta
.format();
105 // for ComboBox, this is mostly a suggestion
106 public String
[] getAllowedValues() {
111 public boolean isArray() {
116 * The value stored by this item, as a {@link String}.
120 public String
getString() {
124 public String
getDefaultString() {
128 public Boolean
getBoolean() {
129 return BundleHelper
.parseBoolean(getString());
132 public Boolean
getDefaultBoolean() {
133 return BundleHelper
.parseBoolean(getDefaultString());
136 public Character
getCharacter() {
137 return BundleHelper
.parseCharacter(getString());
140 public Character
getDefaultCharacter() {
141 return BundleHelper
.parseCharacter(getDefaultString());
144 public Integer
getInteger() {
145 return BundleHelper
.parseInteger(getString());
148 public Integer
getDefaultInteger() {
149 return BundleHelper
.parseInteger(getDefaultString());
152 public Integer
getColor() {
153 return BundleHelper
.parseColor(getString());
156 public Integer
getDefaultColor() {
157 return BundleHelper
.parseColor(getDefaultString());
160 public List
<String
> getList() {
161 return BundleHelper
.parseList(getString());
164 public List
<String
> getDefaultList() {
165 return BundleHelper
.parseList(getDefaultString());
169 * The value stored by this item, as a {@link String}.
174 public void setString(String value
) {
178 public void setBoolean(boolean value
) {
179 setString(BundleHelper
.fromBoolean(value
));
182 public void setCharacter(char value
) {
183 setString(BundleHelper
.fromCharacter(value
));
186 public void setInteger(int value
) {
187 setString(BundleHelper
.fromInteger(value
));
190 public void setColor(int value
) {
191 setString(BundleHelper
.fromColor(value
));
194 public void setList(List
<String
> value
) {
195 setString(BundleHelper
.fromList(value
));
199 * Reload the value from the {@link Bundle}.
201 public void reload() {
202 value
= bundle
.getString(id
);
203 for (Runnable listener
: reloadedListeners
) {
206 } catch (Exception e
) {
207 // TODO: error management?
213 // listeners will be called AFTER reload
214 public void addReloadedListener(Runnable listener
) {
215 reloadedListeners
.add(listener
);
219 * Save the current value to the {@link Bundle}.
222 for (Runnable listener
: saveListeners
) {
225 } catch (Exception e
) {
226 // TODO: error management?
230 bundle
.setString(id
, value
);
233 // listeners will be called BEFORE save
234 public void addSaveListener(Runnable listener
) {
235 saveListeners
.add(listener
);
239 public Iterator
<MetaInfo
<E
>> iterator() {
240 return children
.iterator();
243 public List
<MetaInfo
<E
>> getChildren() {
248 * Create a list of {@link MetaInfo}, one for each of the item in the given
252 * the type of {@link Bundle} to edit
254 * a class instance of the item type to work on
256 * the {@link Bundle} to sort through
260 static public <E
extends Enum
<E
>> List
<MetaInfo
<E
>> getItems(Class
<E
> type
,
262 List
<MetaInfo
<E
>> list
= new ArrayList
<MetaInfo
<E
>>();
263 for (E id
: type
.getEnumConstants()) {
264 list
.add(new MetaInfo
<E
>(type
, bundle
, id
));
270 // TODO: multiple levels?
271 static public <E
extends Enum
<E
>> Map
<MetaInfo
<E
>, List
<MetaInfo
<E
>>> getGroupedItems(
272 Class
<E
> type
, Bundle
<E
> bundle
) {
273 Map
<MetaInfo
<E
>, List
<MetaInfo
<E
>>> map
= new TreeMap
<MetaInfo
<E
>, List
<MetaInfo
<E
>>>();
274 Map
<MetaInfo
<E
>, List
<MetaInfo
<E
>>> map1
= new TreeMap
<MetaInfo
<E
>, List
<MetaInfo
<E
>>>();
276 List
<MetaInfo
<E
>> ungrouped
= new ArrayList
<MetaInfo
<E
>>();
277 for (MetaInfo
<E
> info
: getItems(type
, bundle
)) {
278 if (info
.meta
.group()) {
279 List
<MetaInfo
<E
>> list
= new ArrayList
<MetaInfo
<E
>>();
281 map1
.put(info
, list
);
287 for (int i
= 0; i
< ungrouped
.size(); i
++) {
288 MetaInfo
<E
> info
= ungrouped
.get(i
);
289 MetaInfo
<E
> group
= findParent(info
, map
.keySet());
291 map
.get(group
).add(info
);
292 ungrouped
.remove(i
--);
296 if (ungrouped
.size() > 0) {
297 map
.put(null, ungrouped
);
303 static private <E
extends Enum
<E
>> MetaInfo
<E
> findParent(MetaInfo
<E
> info
,
304 Set
<MetaInfo
<E
>> candidates
) {
305 MetaInfo
<E
> group
= null;
306 for (MetaInfo
<E
> pcandidate
: candidates
) {
307 if (info
.id
.toString().startsWith(pcandidate
.id
.toString())) {
309 || group
.id
.toString().length() < pcandidate
.id
310 .toString().length()) {