1 /**
2  * Widget module.
3  *
4  * License:
5  *     MIT. See LICENSE for full details.
6  */
7 module tkd.widget.scrollbar;
8 
9 /**
10  * Imports.
11  */
12 import std.conv;
13 import tkd.element.uielement;
14 import tkd.widget.common.xscrollcommand;
15 import tkd.widget.common.yscrollcommand;
16 import tkd.widget.widget;
17 
18 /**
19  * Scrollbar widgets are typically linked to an associated window that displays 
20  * a document of some sort, such as a file being edited or a drawing. A 
21  * scrollbar displays a thumb in the middle portion of the scrollbar, whose 
22  * position and size provides information about the portion of the document 
23  * visible in the associated window. The thumb may be dragged by the user to 
24  * control the visible region. Depending on the theme, two or more arrow 
25  * buttons may also be present; these are used to scroll the visible region in 
26  * discrete units.
27  *
28  * Example:
29  * ---
30  * auto frame = new Frame()
31  * 	.grid(0, 0);
32  *
33  * auto canvas = new Canvas(frame);
34  * 	.setWidth(300)
35  * 	.setHeight(150)
36  * 	.setScrollRegion(-100, -150, 500, 350)
37  *
38  * auto yscroll = new YScrollBar(frame)
39  * 	.attachWidget(canvas)
40  * 	.grid(1, 0, 0, 0, 1, 1, "nes");
41  *
42  * auto xscroll = new XScrollBar(frame)
43  * 	.attachWidget(canvas)
44  * 	.grid(0, 1, 0, 0, 1, 1, "esw");
45  *
46  * canvas.attachXScrollBar(xscroll)
47  * 	.attachYScrollBar(yscroll)
48  * 	.grid(0, 0, 0, 0, 1, 1, "nesw");
49  * ---
50  *
51  * Additional_Events:
52  *     Additional events that can also be bound to using the $(LINK2 ../element/uielement.html#UiElement.bind, bind) method.
53  *     $(P
54  *         <<PrevWindow>>,
55  *         <Alt-Key>,
56  *         <B1-Motion>,
57  *         <B2-Motion>,
58  *         <Button-1>,
59  *         <Button-2>,
60  *         <ButtonRelease-1>,
61  *         <ButtonRelease-2>,
62  *         <Key-F10>,
63  *         <Key-Tab>,
64  *     )
65  *
66  * States:
67  *     The scrollbar automatically sets the disabled state when the entire 
68  *     range is visible and clears it otherwise.
69  *
70  * See_Also:
71  *     $(LINK2 ./widget.html, tkd.widget.widget)
72  */
73 abstract class ScrollBar : Widget
74 {
75 	/**
76 	 * Construct the widget.
77 	 *
78 	 * Params:
79 	 *     parent = The parent of this widget.
80 	 *
81 	 * See_Also:
82 	 *     $(LINK2 ../element/uielement.html, tkd.element.uielement) $(BR)
83 	 */
84 	this(UiElement parent = null)
85 	{
86 		super(parent);
87 		this._elementId = "scrollbar";
88 
89 		this._tk.eval("ttk::scrollbar %s", this.id);
90 	}
91 
92 	/**
93 	 * Returns a real number indicating the fractional change in the scrollbar 
94 	 * setting that corresponds to a given change in thumb position. For 
95 	 * example, if the scrollbar is horizontal, the result indicates how much 
96 	 * the scrollbar setting must change to move the thumb deltaX pixels to the 
97 	 * right (deltaY is ignored in this case). If the scrollbar is vertical, 
98 	 * the result indicates how much the scrollbar setting must change to move 
99 	 * the thumb deltaY pixels down. The arguments and the result may be zero 
100 	 * or negative.
101 	 *
102 	 * Params:
103 	 *     deltaX = The amount to move horizontally.
104 	 *     deltaY = The amount to move vertically.
105 	 *
106 	 * Returns:
107 	 *     The fractional change.
108 	 */
109 	public double getDelta(int deltaX, int deltaY)
110 	{
111 		this._tk.eval("%s delta %s %s", this.id, deltaX, deltaY);
112 		return this._tk.getResult!(double);
113 	}
114 
115 	/**
116 	 * Returns a real number between 0 and 1 indicating where the point given 
117 	 * by x and y lies in the trough area of the scrollbar, where 0.0 
118 	 * corresponds to the top or left of the trough and 1.0 corresponds to the 
119 	 * bottom or right. X and y are pixel coordinates relative to the scrollbar 
120 	 * widget. If x and y refer to a point outside the trough, the closest 
121 	 * point in the trough is used.
122 	 *
123 	 * Params:
124 	 *     x = The x position.
125 	 *     y = The y position.
126 	 *
127 	 * Returns:
128 	 *     The fractional position.
129 	 */
130 	public double getFraction(int x, int y)
131 	{
132 		this._tk.eval("%s fraction %s %s", this.id, x, y);
133 		return this._tk.getResult!(double);
134 	}
135 }
136 
137 /**
138  * Class representing a horizontal scrollbar widget.
139  */
140 class XScrollBar : ScrollBar
141 {
142 	/**
143 	 * Construct the widget.
144 	 *
145 	 * Params:
146 	 *     parent = The parent of this widget.
147 	 *
148 	 * See_Also:
149 	 *     $(LINK2 ../element/uielement.html, tkd.element.uielement) $(BR)
150 	 */
151 	this(UiElement parent = null)
152 	{
153 		super(parent);
154 		this._tk.eval("%s configure -orient horizontal", this.id);
155 	}
156 
157 	/**
158 	 * Attach a horizontally scrollable widget to this scrollbar.
159 	 *
160 	 * Params:
161 	 *     scrollableWidget = A horizontally scrollable widget.
162 	 *
163 	 * Returns:
164 	 *     This widget to aid method chaining.
165 	 *
166 	 * See_Also:
167 	 *     $(LINK2 ./common/xscrollcommand.html, tkd.widget.common.xscrollcommand) $(BR)
168 	 */
169 	public auto attachWidget(this T, S)(IXScrollable!(S) scrollableWidget)
170 	{
171 		auto widget = cast(Widget)scrollableWidget;
172 
173 		this._tk.eval("%s configure -command [list %s xview]", this.id, widget.id);
174 
175 		return cast(T) this;
176 	}
177 
178 }
179 
180 /**
181  * Class representing a vertical scrollbar widget.
182  */
183 class YScrollBar : ScrollBar
184 {
185 	/**
186 	 * Construct the widget.
187 	 *
188 	 * Params:
189 	 *     parent = The parent of this widget.
190 	 *
191 	 * See_Also:
192 	 *     $(LINK2 ../element/uielement.html, tkd.element.uielement) $(BR)
193 	 */
194 	this(UiElement parent = null)
195 	{
196 		super(parent);
197 		this._tk.eval("%s configure -orient vertical", this.id);
198 	}
199 
200 	/**
201 	 * Attach a vertically scrollable widget to this scrollbar.
202 	 *
203 	 * Params:
204 	 *     scrollableWidget = A vertically scrollable widget.
205 	 *
206 	 * Returns:
207 	 *     This widget to aid method chaining.
208 	 *
209 	 * See_Also:
210 	 *     $(LINK2 ./common/yscrollcommand.html, tkd.widget.common.yscrollcommand) $(BR)
211 	 */
212 	public auto attachWidget(this T, S)(IYScrollable!(S) scrollableWidget)
213 	{
214 		auto widget = cast(Widget)scrollableWidget;
215 
216 		this._tk.eval("%s configure -command [list %s yview]", this.id, widget.id);
217 
218 		return cast(T) this;
219 	}
220 }