1 /// Basic implementation of clipboard I/O without communicating with the system. Exchanges clipboard data
2 /// only between nodes with access, and does not transfer them to other apps.
3 module fluid.clipboard_chain;
4 
5 import fluid.node;
6 import fluid.types;
7 import fluid.utils;
8 import fluid.node_chain;
9 
10 import fluid.io.clipboard;
11 
12 @safe:
13 
14 alias clipboardChain = nodeBuilder!ClipboardChain;
15 
16 /// Local clipboard provider. Makes it possible to copy and paste text between nodes in the same branch.
17 ///
18 /// `ClipboardChain` does not communicate with the system, so the clipboard will *not* be accessible to other apps.
19 /// This makes this node suitable for testing.
20 class ClipboardChain : NodeChain, ClipboardIO {
21 
22     mixin controlIO;
23 
24     private {
25         string _value;
26     }
27 
28     this(Node next = null) {
29         super(next);
30     }
31 
32     /// Returns:
33     ///     Current clipboard content.
34     string value() const {
35         return _value;
36     }
37 
38     /// Replace the clipboard contents.
39     /// Params:
40     ///     newValue = New clipboard content.
41     /// Returns:
42     ///     Same text as passed into the function.
43     string value(string newValue) {
44         return _value = newValue;
45     }
46 
47     override void beforeResize(Vector2) {
48         startIO();
49     }
50 
51     override void afterResize(Vector2) {
52         stopIO();
53     }
54 
55     override bool writeClipboard(string text) {
56         _value = text;
57         return true;
58     }
59 
60     char[] readClipboard(return scope char[] buffer, ref int offset) nothrow {
61 
62         import std.algorithm : min;
63 
64         // Read the entire text, nothing remains to be read
65         if (offset >= _value.length) return null;
66 
67         // Get remaining text
68         const text = _value[offset .. $];
69         const length = min(text.length, buffer.length);
70 
71         offset += length;
72         return buffer[0 .. length] = text[0 .. length];
73 
74     }
75 
76 }
77 
78 ///
79 @("Example of basic ClipboardChain usage compiles and works")
80 unittest {
81 
82     import fluid;
83 
84     TextInput first, second;
85 
86     // Children of a ClipboardChain will share the same clipboard
87     auto root = clipboardChain(
88         vspace(
89             first  = textInput(),
90             second = textInput(),
91         ),
92     );
93     root.draw();
94 
95     // Text copied by the first input...
96     first.value = "Hello!";
97     first.selectAll();
98     first.copy();
99 
100     // ... can now be pasted into the other
101     second.paste();
102     assert(second.value == "Hello!");
103 
104 }