Skip to content

Commit

Permalink
Implemented correct commands for button and other command widgets.
Browse files Browse the repository at this point in the history
Added first implementation of a checkbutton.
  • Loading branch information
Gary Willoughby committed Feb 7, 2014
1 parent ddbe73c commit 52d77e0
Show file tree
Hide file tree
Showing 17 changed files with 347 additions and 81 deletions.
20 changes: 10 additions & 10 deletions docs/tkd/element/uielement.html
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,13 @@ <h2><a name="UiElement.getCursor"></a>string <span class="symbol">getCursor</spa
<h3>Return Value</h3><p>The widget's cursor.</p>
</div>
</div>
<h2><a name="UiElement.bind"></a>void <span class="symbol">bind</span>(string binding, UiElementCallback callback);
<h2><a name="UiElement.bind"></a>void <span class="symbol">bind</span>(string binding, UiElementBindCallback callback);
</h2>
<div class="declaration-description"><div class="sections"><p>Bind an event to this element.
</p>
<h3>Parameters</h3><table class="parameter-list"><tr><td>string binding</td>
<td>The binding that triggers this event.</td></tr>
<tr><td>UiElementCallback callback</td>
<tr><td>UiElementBindCallback callback</td>
<td>The delegate callback to execute when the event triggers.</td></tr>
</table>
</div>
Expand All @@ -94,28 +94,28 @@ <h3>Parameters</h3><table class="parameter-list"><tr><td>string binding</td>
</div>
</div>
</div>
<h2><a name="UiElementCallback"></a>alias <span class="symbol">UiElementCallback</span> = void delegate(UiElement sender, EventArgs args);
<h2><a name="UiElementBindCallback"></a>alias <span class="symbol">UiElementBindCallback</span> = void delegate(UiElement sender, BindArgs args);
</h2>
<div class="declaration-description"><div class="sections"><p>Alias representing an element callback triggered during events.</p>
<div class="declaration-description"><div class="sections"><p>Alias representing an element callback.</p>
</div>
</div>
<h2><a name="EventArgs"></a>struct <span class="symbol">EventArgs</span>;
<h2><a name="BindArgs"></a>struct <span class="symbol">BindArgs</span>;
</h2>
<div class="declaration-description"><div class="sections"><p>The <span class="symbol">EventArgs</span> struct passed to the UiElementCallback on invocation.</p>
<div class="declaration-description"><div class="sections"><p>The <span class="symbol">BindArgs</span> struct passed to the UiElementBindCallback on invocation.</p>
</div>
<div class="struct-members"><h2><a name="EventArgs.element"></a>UiElement <span class="symbol">element</span>;
<div class="struct-members"><h2><a name="BindArgs.element"></a>UiElement <span class="symbol">element</span>;
</h2>
<div class="declaration-description"><div class="sections"><p>The <span class="symbol">element</span> that raised the event.</p>
</div>
</div>
<h2><a name="EventArgs.binding"></a>string <span class="symbol">binding</span>;
<h2><a name="BindArgs.binding"></a>string <span class="symbol">binding</span>;
</h2>
<div class="declaration-description"><div class="sections"><p>The event that occurred.</p>
</div>
</div>
<h2><a name="EventArgs.callback"></a>UiElementCallback <span class="symbol">callback</span>;
<h2><a name="BindArgs.callback"></a>UiElementBindCallback <span class="symbol">callback</span>;
</h2>
<div class="declaration-description"><div class="sections"><p>The <span class="symbol">callback</span> which was called during the event.</p>
<div class="declaration-description"><div class="sections"><p>The <span class="symbol">callback</span> which was invoked for the event.</p>
</div>
</div>
</div>
Expand Down
5 changes: 3 additions & 2 deletions docs/tkd/widget/button.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ <h3>License</h3><p>MIT. See LICENSE for full details.</p>
<div class="declaration-description"><div class="sections"><p>Class representing a button widget.
</p>
<p><h3>Common Commands:</h3>
<a href="./command/invoke.html">invoke()</a>
<a href="./command/setdefault.html">setDefault()</a></p>
<a href="./common/command.html">setDefault()</a>
<a href="./common/default_.html">setDefault()</a>
<a href="./common/invoke.html">invoke()</a></p>
</div>
<div class="class-members"><h2><a name="Button.this"></a> this(UiElement parent = null, string text = null);
</h2>
Expand Down
42 changes: 42 additions & 0 deletions docs/tkd/widget/checkbutton.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<link type="text/css" href="http://www.nomad.so/ddoc/css/theme.css" rel="stylesheet" media="all" />
<script type="text/javascript" src="http://www.nomad.so/ddoc/javascript/jquery-2.0.3.min.js"></script>
<script type="text/javascript" src="http://www.nomad.so/ddoc/javascript/jquery.scrollTo.min.js"></script>
<script type="text/javascript" src="http://www.nomad.so/ddoc/javascript/index.js"></script>
<title>tkd.widget.checkbutton</title>
</head>
<body>
<h1>tkd.widget.checkbutton</h1>
<!-- Generated by Ddoc from tkd/widget/checkbutton.d -->
<div class="sections"><p>Widget module.
</p>
<h3>License</h3><p>MIT. See LICENSE for full details.</p>
</div>
<div class="module-members"><h2><a name="CheckButton"></a>class <span class="symbol">CheckButton</span>: tkd.widget.textwidget.TextWidget;
</h2>
<div class="declaration-description"><div class="sections"><p>Class representing a checkbutton widget.
</p>
<p><h3>Common Commands:</h3>
<a href="./common/command.html">setDefault()</a>
<a href="./common/invoke.html">invoke()</a></p>
</div>
<div class="class-members"><h2><a name="CheckButton.this"></a> this(UiElement parent = null, string text = null);
</h2>
<div class="declaration-description"><div class="sections"><p>Construct the widget.
</p>
<h3>Parameters</h3><table class="parameter-list"><tr><td>UiElement parent</td>
<td>An optional parent of this widget.</td></tr>
<tr><td>string text</td>
<td>The text of the checkbutton.</td></tr>
</table>
</div>
</div>
</div>
</div>
</div>

</body>
</html>
20 changes: 20 additions & 0 deletions docs/tkd/widget/common/command.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<link type="text/css" href="http://www.nomad.so/ddoc/css/theme.css" rel="stylesheet" media="all" />
<script type="text/javascript" src="http://www.nomad.so/ddoc/javascript/jquery-2.0.3.min.js"></script>
<script type="text/javascript" src="http://www.nomad.so/ddoc/javascript/jquery.scrollTo.min.js"></script>
<script type="text/javascript" src="http://www.nomad.so/ddoc/javascript/index.js"></script>
<title>tkd.widget.common.command</title>
</head>
<body>
<h1>tkd.widget.common.command</h1>
<!-- Generated by Ddoc from tkd/widget/common/command.d -->
<div class="sections"><p>Command module.
</p>
<h3>License</h3><p>MIT. See LICENSE for full details.</p>
</div>

</body>
</html>
20 changes: 20 additions & 0 deletions docs/tkd/widget/common/default_.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<link type="text/css" href="http://www.nomad.so/ddoc/css/theme.css" rel="stylesheet" media="all" />
<script type="text/javascript" src="http://www.nomad.so/ddoc/javascript/jquery-2.0.3.min.js"></script>
<script type="text/javascript" src="http://www.nomad.so/ddoc/javascript/jquery.scrollTo.min.js"></script>
<script type="text/javascript" src="http://www.nomad.so/ddoc/javascript/index.js"></script>
<title>tkd.widget.common.default_</title>
</head>
<body>
<h1>tkd.widget.common.default_</h1>
<!-- Generated by Ddoc from tkd/widget/common/default_.d -->
<div class="sections"><p>Default module.
</p>
<h3>License</h3><p>MIT. See LICENSE for full details.</p>
</div>

</body>
</html>
26 changes: 26 additions & 0 deletions docs/tkd/widget/common/invoke.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<link type="text/css" href="http://www.nomad.so/ddoc/css/theme.css" rel="stylesheet" media="all" />
<script type="text/javascript" src="http://www.nomad.so/ddoc/javascript/jquery-2.0.3.min.js"></script>
<script type="text/javascript" src="http://www.nomad.so/ddoc/javascript/jquery.scrollTo.min.js"></script>
<script type="text/javascript" src="http://www.nomad.so/ddoc/javascript/index.js"></script>
<title>tkd.widget.common.invoke</title>
</head>
<body>
<h1>tkd.widget.common.invoke</h1>
<!-- Generated by Ddoc from tkd/widget/common/invoke.d -->
<div class="sections"><p>Invoke module.
</p>
<h3>License</h3><p>MIT. See LICENSE for full details.</p>
</div>
<div class="module-members"><h2><a name="invoke"></a>void <span class="symbol">invoke</span>()();
</h2>
<div class="declaration-description"><div class="sections"><p>Invoke the command associated with the widget.</p>
</div>
</div>
</div>

</body>
</html>
21 changes: 21 additions & 0 deletions docs/tkd/widget/widget.html
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,27 @@ <h2><a name="Widget.pack"></a>void <span class="symbol">pack</span>();
</div>
</div>
</div>
<h2><a name="WidgetCommandCallback"></a>alias <span class="symbol">WidgetCommandCallback</span> = void delegate(Widget widget, CommandArgs args);
</h2>
<div class="declaration-description"><div class="sections"><p>Alias representing a widget command callback.</p>
</div>
</div>
<h2><a name="CommandArgs"></a>struct <span class="symbol">CommandArgs</span>;
</h2>
<div class="declaration-description"><div class="sections"><p>The <span class="symbol">CommandArgs</span> struct passed to the WidgetCommandCallback on invocation.</p>
</div>
<div class="struct-members"><h2><a name="CommandArgs.widget"></a>Widget <span class="symbol">widget</span>;
</h2>
<div class="declaration-description"><div class="sections"><p>The <span class="symbol">widget</span> that issued the command.</p>
</div>
</div>
<h2><a name="CommandArgs.callback"></a>WidgetCommandCallback <span class="symbol">callback</span>;
</h2>
<div class="declaration-description"><div class="sections"><p>The <span class="symbol">callback</span> which was invoked as the command.</p>
</div>
</div>
</div>
</div>
</div>

</body>
Expand Down
10 changes: 6 additions & 4 deletions source/example.d
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class Application : TkdApplication
/**
* Event callbacks.
*/
private void button_hello_click(UiElement element, EventArgs args)
private void button_hello_command(Widget widget, CommandArgs args)
{
string[] words = ["Mary", "had", "a", "little", "lamb"];
string currentWord = this.button.hello.getText();
Expand All @@ -25,7 +25,7 @@ class Application : TkdApplication
this.button.hello.setText(nextword);
}

private void button_quit_click(UiElement element, EventArgs args)
private void button_quit_command(Widget widget, CommandArgs args)
{
this.exit();
}
Expand All @@ -38,15 +38,17 @@ class Application : TkdApplication
this.frame.root = new Frame();
this.button.hello = new Button(this.frame.root, "Mary");
this.button.exit = new Button(this.frame.root, "Exit");
this.checkbutton.option = new CheckButton(this.frame.root, "Option");

this.button.hello.bind("<Button-1>", &this.button_hello_click);
this.button.hello.setCommand(&this.button_hello_command);
this.button.hello.addImage(new Png!("thumbnail.png"), ImagePosition.top);

this.button.exit.bind("<Button-1>", &this.button_quit_click);
this.button.exit.setCommand(&this.button_quit_command);

this.frame.root.pack();
this.button.hello.pack();
this.button.exit.pack();
this.checkbutton.option.pack();
}
}

Expand Down
94 changes: 39 additions & 55 deletions source/tkd/element/uielement.d
Original file line number Diff line number Diff line change
Expand Up @@ -116,20 +116,47 @@ abstract class UiElement : Element
* binding = The binding that triggers this event.
* callback = The delegate callback to execute when the event triggers.
*/
public void bind(string binding, UiElementCallback callback)
public void bind(string binding, UiElementBindCallback callback)
{
this.unbind(binding);

EventArgs* eventArgs = cast(EventArgs*)malloc(EventArgs.sizeof);
BindArgs* args = cast(BindArgs*)malloc(BindArgs.sizeof);

(*eventArgs).element = this;
(*eventArgs).binding = binding;
(*eventArgs).callback = callback;
(*args).element = this;
(*args).binding = binding;
(*args).callback = callback;

string command = format("command-%s", this.generateHash(binding ~ this.id));
string tkScript = format("bind %s %s { %s }", this.id, binding, command);

this._tk.createCommand(command, &commandCallback, eventArgs, &deleteCommandCallback);
Tcl_CmdProc bindCallbackHandler = function(ClientData data, Tcl_Interp* tclInterpreter, int argc, const(char)** argv)
{
BindArgs args = *cast(BindArgs*)data;

try
{
args.callback(args.element, args);
}
catch (Throwable ex)
{
string error = "Error occurred in bound callback. ";
error ~= ex.msg ~ "\n";
error ~= "UiElement: " ~ args.element.id ~ "\n";
error ~= "Binding: " ~ args.binding ~ "\n";

Tcl_SetResult(tclInterpreter, error.toStringz, TCL_STATIC);
return TCL_ERROR;
}

return TCL_OK;
};

Tcl_CmdDeleteProc deleteBindCallbackHandler = function(ClientData data)
{
free(data);
};

this._tk.createCommand(command, bindCallbackHandler, args, deleteBindCallbackHandler);
this._tk.eval(tkScript);
}

Expand All @@ -150,14 +177,14 @@ abstract class UiElement : Element
}

/**
* Alias representing an element callback triggered during events.
* Alias representing an element callback.
*/
alias void delegate(UiElement sender, EventArgs args) UiElementCallback;
alias void delegate(UiElement sender, BindArgs args) UiElementBindCallback;

/**
* The EventArgs struct passed to the UiElementCallback on invocation.
* The BindArgs struct passed to the UiElementBindCallback on invocation.
*/
struct EventArgs
struct BindArgs
{
/**
* The element that raised the event.
Expand All @@ -170,50 +197,7 @@ struct EventArgs
string binding;

/**
* The callback which was called during the event.
* The callback which was invoked for the event.
*/
UiElementCallback callback;
}

/**
* The function used to create new commands. All bound events trigger for the above element call this function.
*
* Params:
* data = Client data registered with the new command.
* tclInterpreter = The native Tcl interpreter.
* argc = The number of parameters called from Tcl.
* argv = A pointer to an array of string parameters called from Tcl.
*/
private extern(C) int commandCallback(ClientData data, Tcl_Interp* tclInterpreter, int argc, const(char)** argv) nothrow
{
EventArgs eventArgs = *cast(EventArgs*)data;

try
{
eventArgs.callback(eventArgs.element, eventArgs);
}
catch (Throwable ex)
{
string error = "Error occurred in bound callback. ";
error ~= ex.msg ~ "\n";
error ~= "UiElement: " ~ eventArgs.element.id ~ "\n";
error ~= "Binding: " ~ eventArgs.binding ~ "\n";

Tcl_SetResult(tclInterpreter, error.toStringz, TCL_STATIC);
return TCL_ERROR;
}

return TCL_OK;
}

/**
* Function automatically called by Tcl when deleting a custom command from the interpreter.
* Freeing the memory allocated from creating the command's client data.
*
* Params:
* data = The client data registered with this command on creation.
*/
private extern(C) void deleteCommandCallback(ClientData data) nothrow
{
free(data);
UiElementBindCallback callback;
}
1 change: 1 addition & 0 deletions source/tkd/tkdapplication.d
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ abstract class TkdApplication
* Storage for elements.
*/
protected Store!(Button) button;
protected Store!(CheckButton) checkbutton;
protected Store!(Frame) frame;
protected Store!(Image) image;

Expand Down

0 comments on commit 52d77e0

Please sign in to comment.