Browse Source

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 years ago
parent
commit
bc63c527ef

+ 32
- 3
src/main/java/com/dmdirc/ui/messages/EventFormatter.java View File

@@ -22,8 +22,12 @@
22 22
 
23 23
 package com.dmdirc.ui.messages;
24 24
 
25
+import com.dmdirc.events.DisplayProperty;
26
+import com.dmdirc.events.DisplayPropertyMap;
25 27
 import com.dmdirc.events.DisplayableEvent;
26 28
 
29
+import com.dmdirc.interfaces.Displayable;
30
+import com.dmdirc.util.colours.ColourUtils;
27 31
 import java.util.Optional;
28 32
 
29 33
 import javax.inject.Inject;
@@ -111,13 +115,20 @@ public class EventFormatter {
111 115
     private String getReplacement(final Object dataSource, final String tag) {
112 116
         final String[] functionParts = tag.split("\\|");
113 117
         final String[] dataParts = functionParts[0].split("\\.");
118
+        final DisplayPropertyMap displayProperties = new DisplayPropertyMap();
114 119
 
115 120
         Object target = dataSource;
116 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 123
             if (result.isPresent()) {
120 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 132
             } else {
122 133
                 return ERROR_STRING;
123 134
             }
@@ -128,7 +139,25 @@ public class EventFormatter {
128 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 View File

@@ -61,10 +61,8 @@ public class EventPropertyManager {
61 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 66
         try {
69 67
             final Method method = type.getMethod(methodName);
70 68
             // TODO: This is needed for AutoValues, should probably get return types not real types
@@ -77,8 +75,7 @@ public class EventPropertyManager {
77 75
 
78 76
             return Optional.ofNullable(result);
79 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 80
         return Optional.empty();
84 81
     }

+ 5
- 2
src/main/java/com/dmdirc/ui/messages/Styliser.java View File

@@ -333,14 +333,17 @@ public class Styliser implements ConfigChangeListener, StyleApplier {
333 333
 
334 334
         // Nickname links
335 335
         if (string.charAt(0) == CODE_NICKNAME) {
336
+            int count = 1;
336 337
             if (state.isInLink) {
337 338
                 maker.endNicknameLink();
338 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 344
             state.isInLink = !state.isInLink;
342 345
 
343
-            return 1;
346
+            return count;
344 347
         }
345 348
 
346 349
         // Fixed pitch

Loading…
Cancel
Save