Переглянути джерело

Apply object display properties when formatting events.

If an object in a formatter tag ({{foo.bar.baz}}) is Displayable,
then we will modify the output based on its display properties.

Currently only supports user links and foreground colours.

This also changes the internal format of nickname links to be
`\u16<nick to link to>\u16<text to show>\u16`, allowing the
link and text to differ. This means if you formatted users
by showing their realname, you could still click them to
open a query.

Closes #424
Closes DMDirc/Plugins#507
pull/748/head
Chris Smith 7 роки тому
джерело
коміт
bc63c527ef

+ 32
- 3
src/main/java/com/dmdirc/ui/messages/EventFormatter.java Переглянути файл

22
 
22
 
23
 package com.dmdirc.ui.messages;
23
 package com.dmdirc.ui.messages;
24
 
24
 
25
+import com.dmdirc.events.DisplayProperty;
26
+import com.dmdirc.events.DisplayPropertyMap;
25
 import com.dmdirc.events.DisplayableEvent;
27
 import com.dmdirc.events.DisplayableEvent;
26
 
28
 
29
+import com.dmdirc.interfaces.Displayable;
30
+import com.dmdirc.util.colours.ColourUtils;
27
 import java.util.Optional;
31
 import java.util.Optional;
28
 
32
 
29
 import javax.inject.Inject;
33
 import javax.inject.Inject;
111
     private String getReplacement(final Object dataSource, final String tag) {
115
     private String getReplacement(final Object dataSource, final String tag) {
112
         final String[] functionParts = tag.split("\\|");
116
         final String[] functionParts = tag.split("\\|");
113
         final String[] dataParts = functionParts[0].split("\\.");
117
         final String[] dataParts = functionParts[0].split("\\.");
118
+        final DisplayPropertyMap displayProperties = new DisplayPropertyMap();
114
 
119
 
115
         Object target = dataSource;
120
         Object target = dataSource;
116
         for (String part : dataParts) {
121
         for (String part : dataParts) {
117
-            final Optional<Object> result =
118
-                    propertyManager.getProperty(target, target.getClass(), part);
122
+            final Optional<Object> result = propertyManager.getProperty(target, target.getClass(), part);
119
             if (result.isPresent()) {
123
             if (result.isPresent()) {
120
                 target = result.get();
124
                 target = result.get();
125
+
126
+                // Collate all the display properties for objects as we traverse. More specific ones will
127
+                // override earlier ones.
128
+                if (target instanceof Displayable) {
129
+                    displayProperties.putAll(((Displayable) target).getDisplayProperties());
130
+                }
131
+
121
             } else {
132
             } else {
122
                 return ERROR_STRING;
133
                 return ERROR_STRING;
123
             }
134
             }
128
             value = propertyManager.applyFunction(value, functionParts[i]);
139
             value = propertyManager.applyFunction(value, functionParts[i]);
129
         }
140
         }
130
 
141
 
131
-        return value;
142
+        return applyDisplayProperties(displayProperties, value);
143
+    }
144
+
145
+    // TODO: It should be possible for plugins etc to add new ways of applying properties.
146
+    private String applyDisplayProperties(final DisplayPropertyMap displayProperties, final String value) {
147
+        final StringBuilder res = new StringBuilder(value);
148
+
149
+        displayProperties.get(DisplayProperty.LINK_USER).ifPresent(user -> res
150
+                .insert(0, StyleApplier.CODE_NICKNAME)
151
+                .insert(0, user.getNickname())
152
+                .insert(0, StyleApplier.CODE_NICKNAME)
153
+                .append(StyleApplier.CODE_NICKNAME));
154
+
155
+        displayProperties.get(DisplayProperty.FOREGROUND_COLOUR).ifPresent(colour -> res
156
+                .insert(0, ColourUtils.getHex(colour))
157
+                .insert(0, IRCControlCodes.COLOUR_HEX)
158
+                .append(IRCControlCodes.COLOUR_HEX));
159
+
160
+        return res.toString();
132
     }
161
     }
133
 
162
 
134
 }
163
 }

+ 3
- 6
src/main/java/com/dmdirc/ui/messages/EventPropertyManager.java Переглянути файл

61
         functions.put("bracketed", s -> Strings.isNullOrEmpty(s) ? "" : " (" + s + ')');
61
         functions.put("bracketed", s -> Strings.isNullOrEmpty(s) ? "" : " (" + s + ')');
62
     }
62
     }
63
 
63
 
64
-    public <S> Optional<Object> getProperty(final S object, final Class<? extends S> type,
65
-            final String property) {
66
-        final String methodName = "get" + property.substring(0, 1).toUpperCase()
67
-                + property.substring(1);
64
+    public <S> Optional<Object> getProperty(final S object, final Class<? extends S> type, final String property) {
65
+        final String methodName = "get" + property.substring(0, 1).toUpperCase() + property.substring(1);
68
         try {
66
         try {
69
             final Method method = type.getMethod(methodName);
67
             final Method method = type.getMethod(methodName);
70
             // TODO: This is needed for AutoValues, should probably get return types not real types
68
             // TODO: This is needed for AutoValues, should probably get return types not real types
77
 
75
 
78
             return Optional.ofNullable(result);
76
             return Optional.ofNullable(result);
79
         } catch (ReflectiveOperationException ex) {
77
         } catch (ReflectiveOperationException ex) {
80
-            LOG.warn(USER_ERROR, "Unable to format event: could not retrieve property {}",
81
-                    ex.getMessage(), ex);
78
+            LOG.warn(USER_ERROR, "Unable to format event: could not retrieve property {}", property, ex);
82
         }
79
         }
83
         return Optional.empty();
80
         return Optional.empty();
84
     }
81
     }

+ 5
- 2
src/main/java/com/dmdirc/ui/messages/Styliser.java Переглянути файл

333
 
333
 
334
         // Nickname links
334
         // Nickname links
335
         if (string.charAt(0) == CODE_NICKNAME) {
335
         if (string.charAt(0) == CODE_NICKNAME) {
336
+            int count = 1;
336
             if (state.isInLink) {
337
             if (state.isInLink) {
337
                 maker.endNicknameLink();
338
                 maker.endNicknameLink();
338
             } else {
339
             } else {
339
-                maker.startNicknameLink(readUntilControl(string.substring(1)));
340
+                int next = string.indexOf(CODE_NICKNAME, 1);
341
+                maker.startNicknameLink(string.substring(1, next));
342
+                count += next;
340
             }
343
             }
341
             state.isInLink = !state.isInLink;
344
             state.isInLink = !state.isInLink;
342
 
345
 
343
-            return 1;
346
+            return count;
344
         }
347
         }
345
 
348
 
346
         // Fixed pitch
349
         // Fixed pitch

Завантаження…
Відмінити
Зберегти