Derma Markup Language

Derma Markup Language, or DML, is an easy-to-use way to create Derma menus with markup similar to HTML. Compare the following two code snippets, and then decide for yourself which one is more conducive to menu creation.

[lua]local frame = vgui.Create(“DFrame”);
frame:SetSize( 500, 500 );
frame:Center();
frame:SetTitle(“My sad little derma frame”);
frame:MakePopup();
frame:SetBackgroundBlur(true);

local panel = vgui.Create(“DPanel”,frame);
panel:SetPos( 5, 25 );
panel:SetSize( 490, 470 );

local label = vgui.Create(“DLabel”,panel);
label:SetPos(5,5);
label:SetText(“I’m a sad label :(”);
label:SetFont(“ScoreboardText”);
label:SetTextColor( Color(255, 0, 0) );
label:SetExpensiveShadow(true);[/lua]

This transforms into:

<frame width="500" height="500" title="My happy DML frame" blur="true">
	<panel x="5" y="25" width="490" height="470">
		<label x="5" y="5" font="ScoreboardText" color="FF0000" shadow="true">
			I'm a happy label :)
		</label>
	</panel>
</frame>

DML eliminates a lot of the unnecessary steps required in making Derma menus, giving advanced developers an easier time with simpler tasks and allowing newer coders with any HTML experience to jump right into Garry’s Mod.

Other features include:
[ul]
[li]20+ different tags and counting[/li][li]Extensive documentation[/li][li]Simple addon install[/li][li]Little Lua required[/li][li]Easy to make new tags[/li][/ul]
For in-depth documentation on using and developing DML, check the Wiki: http://wiki.garrysmod.com/?title=DML_Tutorial (I will be updating this more in the coming days).
Also, make sure you read the top of the “dml.lua” file in lua/autorun.

To install:

SVN: http://dml.googlecode.com/svn/trunk/
Checkout to a folder in your addons.
I’m hesitating to put up a garrysmod.org download just yet because I want to release it first, find the first tirade of bugs, and then hand it out to the unwitting public.

Tag list:[ul]
[li]avatar – Display a player’s Steam avatar (AvatarImage).[/li][li]box – An item in a <combobox>.[/li] [li]button – Clickable text element (DButton).[/li] [li]column – Column name of a DListView.[/li] [li]combobox – Selectable list of text. (DComboBox)[/li] [li]frame – Usually your main container for all items (DFrame).[/li] [li]iframe – An HTML display (HTML).[/li] [li]img – Displays materials (DImage).[/li] [li]imgbutton – Displays materials clickably (DImageButton).[/li] [li]label – Shows text (DLabel).[/li] [li]listitem – Child of a DPanelList. [/li] [li]listline – Container for row text in a DListView.[/li] [li]lua – Runs a Lua script.[/li] [li]marquee – IE5 YEEHAWW[/li] [li]numslider – User can select numbers on a number line (DNumSlider).[/li] [li]option – Child of a <select>.[/li] [li]panel – Container for objects, similar to HTML <div> (DPanel).[/li] [li]panellist – Holds items, uses <listitem> for top-level child.[/li] [li]row – A single row of text in a <listline>.[/li] [li]select – Has options to choose from (DMultiChoice).[/li] [li]sheet – Allows tabbed pages (DPropertySheet).[/li] [li]spawnicon – Displays a model (SpawnIcon).[/li] [li]style – Emulates CSS. Still a WIP.[/li] [li]sysbutton – A button, except has little icons.[/li] [li]tab – A single tab of a <sheet>.[/ul][/li]
Sample DML:

This shows how you can incorporate Lua into your DML (through Panel events like Paint and through the markup itself).

[lua]function drawFrame()
– DML.This is (currently) the universal reference to the current object to paint.
local self = DML.This;
– draw code
end

function drawPanel()
– draw code
end

/* Here’s where we start the actual DML. */

– This creates a new DMLReader.
local dml = DML.New();

local mkup = [[
<frame width=“300” height=“300” title=“DML Example” color=“666666” Paint=“drawFrame()”>
<panel x=“10” y=“30” width=“280” height=“260” Paint=“drawPanel()”>
<numslider x=“5” y=“5” width=“270” min=“0” max=“600” convar=“sv_gravity” text=“Gravity”></numslider>
<combobox x=“5” y=“50” width=“130” height=“180”>
]]
– You can indeed use Lua in your markup! It does get a bit messy though. It’s not quite like PHP and HTML.
for _,v in pairs(player.GetAll()) do mkup = mkup … “<box>” … v:Nick() … “</box>”; end
mkup = mkup … [[
</combobox>
<button x=“5” y=“235” width=“130”>Slay</button>
<listview x=“140” y=“50” width=“135” height=“200”>
<column>Name</column>
<column>Frags</column>
]]
for _,v in pairs(player.GetAll()) do mkup = mkup … “<listline><row>” … v:Nick() … “</row><row>” … v:Frags() … “</row></listline>”; end
mkup = mkup… [[
</listview>
</panel>
</frame>
]];

– This reads in the markup.
dml:Read(mkup);

– This runs the markup.
dml:Open();[/lua]

This produces:

Yes!!

Fantastic job.

Or you could use DermaDes- uh, nevermind.

All joking aside, this is very cool and appears a lot easier than hand coding a UI. Could you put up a list of tags?

holy shit i just cried tears of joy

How would someone do, for example, frame:GetWide() now?
Or listview:GetSelected()?

:iiam:

This is an interesting concept, however you sacrifice a lot of freedom for simplicity. It is great for beginners however.

[editline]3rd January 2011[/editline]

Looking through your code I have found a potential problem. It doesn’t really make a difference in this case because generally you will only have a few instances of the DMLObject, but you should be placing all of your DMLObject methods in a metatable and use setmetatable instead of creating a new set of methods every DML.New call. As you can see from the following example, the way you are currently doing it will create many times more functions than needed, whereas using metatables will only create one set and share them among all of the instances of DMLObject.

[lua]local function newObjectNoMeta()
local obj = {}
function obj:Method()
– Do something
end

return obj

end

local a = newObjectNoMeta()
local b = newObjectNoMeta()
local c = newObjectNoMeta()
local d = newObjectNoMeta()

print(a.Method)
print(b.Method)
print(c.Method)
print(d.Method)

print("")

local meta = {}
meta.__index = meta

function meta:Method()
– Do something
end

function newObjectWithMeta()
local obj = {}

return setmetatable(obj, meta)

end

local e = newObjectWithMeta()
local f = newObjectWithMeta()
local g = newObjectWithMeta()
local h = newObjectWithMeta()

print(e.Method)
print(f.Method)
print(g.Method)
print(h.Method)[/lua]

Example output:


function: 006A4B98
function: 006A4BB8
function: 006A4BD8
function: 006A4BF8

function: 006A4C38
function: 006A4C38
function: 006A4C38
function: 006A4C38

Thanks for that. It’s now implemented.

You can still access the Derma objects via Lua. I’m currently working on a system such that you can do DML.GetByID(id) to find a specific element’s derma object.

I’ve updated the SVN. I significantly changed the file structure, and added an example (shown in OP).

Could you post a pic of what that example makes?

Already there. :eng101:

That menu is sexy.

In the first example what centers the menu?

I’m guessing that if you don’t include a x, y parameter then it will auto centre.

Very interesting addon.

This. This is just pure awesomeness.

Vexx was correct. All the elements have default values assigned for things like x, y, width, height. The default x,y is (0,0) and default width/height is 100/100. The frame is specially set to center if x or y aren’t specified.

Wow! I wish I had seen this closer to when you released this. A neat feature to add could be something along the lines of converting the dml language to Lua (even if it isn’t pretty) because any addon thinking to use this would have to package dml with it which isn’t prefferable.

But… but… :ohdear:

You forgot tooltip for DPropertySheet.AddTab

This seems like a really neat idea, and since I’m much more of a HTML coder than a Lua coder this would be right up my alley.