Interface Object

by ExPixel
For those of use who hate to use winset.
ID:116350
 
I created this library because the us of winset was never very appealing to me. I wanted to share this with everyone else who had this little problem. It's not as complicated as forum_account's library (click the link if it's what you want) but it can be used without have code pre-generated. You simply have to bind this object to a client and a control.

DOCUMENTATION YEAH!!!!

IMPORTANT NOTE: Leaving the arguments blank in the Parameter Proc called will make the proc return the
value of the parameter of the control

IMPORTANT NOTE 2: The return values are going to be either numbers, text, or a boolean(true or false, 0 or 1). So calling Control.FontSize() will return a number.

Naming Convention For Parameter's Proc:

The naming convention used isn't very complicated. All spaces and dashes(-) are removed,
instead the character that comes after them are capitalized. The first letter of the paremeter
is also capitalized. So to change the text on a label you would do something like so:
var/LabelControl/L = new("default.label1", client)
L.Text("blah")//sets the text to "blah"
var/v = L.Text()//L.Text() returns the label's text and sets the variable 'v' to the labe's text



Control Types:

CONTROL - Highest level of controls, does not include Macro or menu

MacroControl - Macros

MenuControl - Menus

LabelControl - Labels

BrowserControl - Browsers

WindowControl - Windows

TabControl - Tabs

ButtonControl - Buttons

InfoControl - Infos

InputControl - Inputs

OutputControl - Outputs

BarControl - Bars

ChildControl - Childs

GridControl - Grids


How it works:

- You may initialize a control by simply calling the bind(control, client) proc
The first argument is the control and the second is the client/mob(with a client)
- You can also initialize a control by supplying the arguments of bind in the control's
New proc e.g. var/LabelControl/L = new("somewindow.somecontrol", src)
Great work! Very helpful.

Also, First >:D
Galactic Soldier wrote:
It isn't helpful, it's an alternative to a very easy and simple way of doing something; in other words, redundant.

It's not redundant. [Link 1] -> [Link 2]
Galactic Soldier wrote:
It isn't helpful, it's an alternative to a very easy and simple way of doing something; in other words, redundant.

I can't speak for this library but the Interface library is very similar. I'm not entirely sure what you mean, but this library is certainly an improvement over winset and winget. The Interface library caches certain properties for you (I don't know if this library does). If you do something like this:

label.Text("hello")

// later on...
world << label.Text()

The output statement will print "hello" without needing to call winget to retrieve the value. For most properties it remembers the value you set, so there's no delay while the server asks the client what the labels text property is set to. Also, when you set the text property you don't have to worry about escaping the string (things like winset(src, "label1", "text=[t]") may not work if t is a string with spaces or quotes).

It also handles the parsing of values. These two statements are equivalent:

if(winget(client, "window.label", "focus") == "true")

if(label.Focus())

The first line is certainly messier. It's a lot more complex looking and you have to remember that it'll return the string "true" or "false". The second line has no strings, just a variable name and a proc name. You don't have to worry about the return value and if you spell something wrong you'll get a compiler error. When you're working with winset and winget, everything is contained in a string so you can't get compile-time errors for using the wrong control or property names.

Edit: By providing objects that manage the interaction with interface controls, you can give them procs to handle more elaborate operations. For example, the Interface library provides procs on the /Browser object to display HTML, show a webpage, cache an image, or call a JavaScript function. You could say these capabilities are redundant - the library can't implement these actions unless there's some way for BYOND to do them already - but the way they're used is much simpler. Users don't have to remember all of the details of using winset, winget, browse, browse_rsc, output, etc.
I don't understand this part:

ExPixel wrote:
It's not as complicated as forum_account's library (click the link if it's what you want) but it can be used without have code pre-generated. You simply have to bind this object to a client and a control.

The Interface library works the same way =)
Galactic Soldier wrote:
It's a slightly more ineffective way to produce the same results; tunneling one procedure through another. Maybe an improvement in conventional coding mannerisms (shouldn't matter, the other way of doing it is quite self-explanatory), but nothing more than that.

You say that like it's a bad thing but that's all that programming is. DM provides some basic capabilities and we create procs that "tunnel" higher level commands down to BYOND's basic operations. Here's an example:

mob
proc
attack(mob/m)
m.take_damage(10)

take_damage(d)
set_health(health - d)

set_health(h)
health = h

While you could modify the mob's health directly in the attack() proc it's better to go through the other procs. It produces the same results but is better because it gives you a single place where the mob's health is modified (even though there can be many things in the code that cause changes to their health, there's only one place where it actually happens).

If you want to make certain players take double damage there's an easy way to do that - you can modify the take_damage() proc instead of changing every proc that deals damage. If you want to have side effects that occur when damage is done (ex: damage numbers, update on-screen health displays, etc.) you have a single place to add them. All of these benefits because you tunnel one procedure through another.

Then look at the reference; that's why it's there. It's no different from searching through this library's procedures.

That sounds like good advice because you already know what DM procs exist and what they do. To someone who doesn't know that stuff, they wouldn't know to look up the output() proc to see how you can call JavaScript functions from DM. They wouldn't even know that it was possible to call JavaScript functions from DM so they'd certainly not know the output proc is how it's done.

The library (the Interface library, that is) gives the procs better names so its capabilities are obvious to see and easy to use. The browser.JavaScript() proc calls a JS function (and it handles the formatting and parsing of parameters so you can pass numbers, strings, lists, and objects). The browser.URL() proc directs the browser to the specified url. While that's done using the browse() proc, it's not obvious from the reference that you can even do that with the browse proc (typically it's used to display some HTML content you've generated, not to direct the user to an existing web page).
Galactic Soldier wrote:
It's a slightly more ineffective way to produce the same results; tunneling one procedure through another. Maybe an improvement in conventional coding mannerisms (shouldn't matter, the other way of doing it is quite self-explanatory), but nothing more than that.

Forum_account wrote:
The Interface library works the same way =)

In other words, this library isn't needed or beneficial also since something of the same assent predates it. He also seems to be very fond of your library that in your words "works the same way"; could be some plagiarism involved.

Forum_account wrote:
Users don't have to remember all of the details of using winset, winget, browse, browse_rsc, output, etc.

Then look at the reference; that's why it's there. It's no different from searching through this library's procedures.

There is a difference between his and my library. With mine you create the object representing a control on the interface and you user the bind() proc to bind that object to the interface. With Forum_Account's you generate the code. Mine is easier to get started with and use. Forum_Account's offers more functionality.
In response to ExPixel
ExPixel wrote:
With Forum_Account's you generate the code.

I saw you said this at least twice already, but I have no clue what you mean by this.

I can't find any documentation for the Interface library, but it appears that all you need to do to "bind a control to a client" is make a variable with the appropriate type and initialize it by calling new(window, control, player).
Yep, all you have to do is this:

var/Label/label = new("window", "label", client)
label.Text("hello, world!")

// you could also do this:
label = new("window.label", client)

// or this:
label = new(client, "window.label")

The library's code was generated and it can also generate code from a .dmf file - it creates the control definitions for every control on a window. These steps aren't necessary though.
In response to Forum_account
Forum_account wrote:
Yep, all you have to do is this:

> var/Label/label = new("window", "label", client)
> label.Text("hello, world!")
>
> // you could also do this:
> label = new("window.label", client)
>
> // or this:
> label = new(client, "window.label")
>

The library's code was generated and it can also generate code from a .dmf file - it creates the control definitions for every control on a window. These steps aren't necessary though.

OH! I may have misunderstood the way your library works then.
It looks like the biggest difference is that you can use your library to create a single control object, then bind it to different clients as you need to change things on their interface. With my library each control object has an owner, so you'd create one instance of a control object per client (since it caches values, the cache is specific to a single client and can't be shared).