1 module fluid.showcase.buttons; 2 3 import std.range; 4 5 import fluid; 6 import fluid.showcase; 7 8 9 @safe: 10 11 12 @( 13 () => label("Buttons are the most basic node when it comes to user input. Pressing a button triggers an event, " 14 ~ "and that's about the functionality of the button. Under the hood, buttons are labels — but they're modified " 15 ~ "to react to user clicks."), 16 () => label("To initialize a button, you need to pass a delegate to dictate the button's effect. Here's one that " 17 ~ "does nothing:"), 18 ) 19 Label buttonExample() { 20 21 return button("Hello, World!", delegate { }); 22 23 } 24 25 @( 26 () => label("Naturally, user interfaces are made to react to user input and other events that happen in the " 27 ~ "system. The interface needs to change to keep displayed information up to date. Glui nodes expose " 28 ~ "properties that make them possible to change. So, we can make the button change its text when clicked."), 29 () => label("Just note that to refer to the button within itself we need to declare it beforehand."), 30 ) 31 Label mutableLabelExample() { 32 33 import std.range : cycle; 34 35 Button!() myButton; 36 auto texts = cycle(["Hello!", "Bonjour!", "¡Hola!", "Здравствуйте!"]); 37 38 // Create the button 39 myButton = button(texts.front, delegate { 40 41 // Switch to the next text when clicked 42 texts.popFront; 43 myButton.text = texts.front; 44 45 }); 46 47 return myButton; 48 49 } 50 51 @( 52 () => label("Let's try making this a bit more complex. Once we connect a few nodes, we need to retain access to " 53 ~ "all the nodes we're interested. If we place a label in a frame, we still need to keep a reference to the " 54 ~ "label if we intend to change it. Fortunately, we can assign variables while building the tree. This is " 55 ~ "somewhat unconventional, since a typical user interface system would instead have you query nodes by ID, " 56 ~ "but this is simpler and more flexible."), 57 ) 58 Frame nestedLabelFirstExample() { 59 60 Label myLabel; 61 auto texts = cycle(["Hello!", "Bonjour!", "¡Hola!", "Здравствуйте!"]); 62 63 return vframe( 64 myLabel = label(texts.front), 65 button("Change text", delegate { 66 67 // Change text of the button when clicked 68 texts.popFront; 69 myLabel.text = texts.front; 70 71 }), 72 ); 73 74 } 75 76 @( 77 () => label("Of course, we also have the choice to assign the label on the same line it was declared " 78 ~ "on. The downside of that usage is that it is usually helpful to keep each component of the tree united " 79 ~ "for easier analysis. However, it might be preferrable if the tree is becoming complex, so you might need " 80 ~ "to find the right balance."), 81 82 () => label(.headingTheme, "Editing layouts"), 83 () => label("Frame contents can be changed at runtime by changing their 'children' property. The operation is a " 84 ~ "bit more complex than updating labels, and you have to pay attention to this one if you intend to rearrange " 85 ~ "frames this way."), 86 ) 87 Frame mutableFrameExample() { 88 89 import std.algorithm : bringToFront; 90 91 Frame myFrame; 92 93 return vframe( 94 myFrame = hframe( 95 label("Foo, "), 96 label("Bar, "), 97 label("Baz, "), 98 ), 99 button("Reorder nodes", delegate { 100 101 // Move the last node to start 102 bringToFront( 103 myFrame.children[0..$-1], 104 myFrame.children[$-1..$] 105 ); 106 myFrame.updateSize(); 107 108 }), 109 ); 110 111 } 112 113 // TODO cover .layout? 114 115 @( 116 () => label("Fluid frames provide full control over their contents, making it possible to use the power of D " 117 ~ "libraries for the job. See, to move the nodes around in the example above, we use 'bringToFront' from " 118 ~ "std.algorithm. As a downside to this, Fluid is not able to detect changes and resize ahead of time, like it " 119 ~ "does with labels, so you must call 'updateSize()' on the frame for the changes to apply. Fluid will issue " 120 ~ "an error at runtime if you don't do this, so be careful!"), 121 () => label("Do not worry though, a lot of layout management can be made easier with helpers like nodeSlot, which " 122 ~ "we'll cover later."), 123 ) 124 void endExample() { }