ID:985467
 
Updated screen shots and info in posts below.

This post has old documentation. It'll be updated in due time.
- Part of the documentation is relevant so I have not removed it.

I'm giving a sneak peak of this so I can get some feedback of what people would like implemented. It is usable in it's current condition. I'll release it officially once I better document it and polish it.

https://dl.dropbox.com/u/17935054/Table/ MDDrawMapControls_src.zip

Latest screenshot:


I've tried making this as flexible and easy to use as possible. I've set this up to work like objective-c.

To update a cell you set up a callback function for a specified table. When you tell the table to reload it's data it will call the function below for every visible cell. The call back function gives you the table, and index of the cell along with the cell being updated.

proc/cellReloadedForPlayer(MDTable/table, MDTableCell/cell, index, mob/m)
var/MDCellPlayer/_cell = cell
var/mob/player = table.data.values[index]
_cell.cellBack.name = player.key
_cell.text.setText(limit(player.name, 15))
_cell.text2.setText(limit(player.key, 15))
_cell.img.icon = icon('MDIcons.dmi', "[index % 8 == 0 ? 8: index % 8]")
_cell.img.name = _cell.cellBack.name


The "limit" function is just for keeping the text from being too long.

proc/limit(_string, length)return copytext(_string, 1, length)


You can also set up a callback function for a specific table for when a cell is clicked on. Multiple Tables can share the same callback function. In the callback function when you click on a cell the table, cell, and index of the cell are returned.

mob/proc/rowSelectedForTable(MDTable/table, MDTableCell/cell, index, mob/m)
if(table == m.playersTable)
var/MDCellPlayer/_cell = cell
world<<"\icon[_cell.img] [_cell.text.value]([_cell.text2.value])"


Tables can be any size and can be positioned anywhere. You can texture the table and cells or you can set them up to have gradient backgrounds or make it so they have no background. You can also specify a color for the table borders or not give them one.

Here is a table using a gradient background:

mob/proc/createPlayerTablesWithData(MDData/data)
playersTable = new(data)//table.setDataWithMDData(data)
playersTable.setCustomCell(/MDCellPlayer)
playersTable.setCallBackFunction(/mob/proc/rowSelectedForTable)
playersTable.setCellCallBackFunction(/proc/cellReloadedForPlayer)
playersTable.setTablePosition(_x = 14, _y = 1, _px = 0, _py = 0)
playersTable.setTableHeightInPixels(310)
playersTable.setTableWidthInPixels(150)
playersTable.setTableCellWidthInPixels(0)//# <= 0 sets the cellWidth to the width of the table
//playersTable.setTableCellHeightInPixels(20)
playersTable.setTableCellPaddingInPixels(5)
playersTable.setTableCellHeightAutomaticallyToFitXCells(7)
playersTable.setTableStyle(MDTABLESTYLEGRADIENT)
playersTable.setTableColorFlags(_rFlag = TRUE, _gFlag = TRUE)
playersTable.setCellStyle(MDTABLESTYLEGRADIENT)
playersTable.setCellColorFlags(_gFlag = TRUE)
playersTable.setTableBorderColor(rgb(0, 0, 0))
playersTable.setCellBorderColor(rgb(0, 0, 0))
playersTable.drawTable()


Next I set up that table to automatically update every time a player is added to it by adding a callback function to the MDData:

var/MDData/players = new(list())

world/New()
..()
players.setCallBack(/proc/refreshPlayersTab)

mob
Login()
..()
world<<"[src] logs in!"
name = "\[Player Name\]"

createTable1WithData(data)
createTable2WithData(data2)
data.setOwner(src)
data2.setOwner(src)

createPlayerTablesWithData(players)

players.add(src)

Logout()
world<<"[src] logs out!"
players.remove(src)
del(src)

proc/refreshPlayersTab()for(var/client/c)c.mob.playersTable.reloadDataIfNeeded()


Every time a player is added or removed from the MDData object the callback function is called which updates everyone's playersTable table.

You can also create custom cells, take a look at MDCustomCells.dm to see how they are set up.

You can customize the font text with these values(so far):
        fontSize = 12
alignment = MDTEXTALIGNLEFT// MDTEXTALIGNCENTER, MDTEXTALIGNRIGHT
color = "#000000"
font = "Rockwell"
weight = 900


If you want to know what constants there are look in MDConstants.dm

I've added in MDWindows. They are great for making popup messages, alerts, menus, etc... They are reusable. The window backgrounds are cached for quick reuse.

Here is a code example for a MDWindow that passses a cell object when a cell is clicked on:

mob/proc/createWindowForObject(MDTableCell/_cell)
if(open_windows["Test"])return
var/_msg = "No Cell Found!"
if(_cell)_msg = "Would you like to modify the cell at index [_cell.index]"
var/MDYesNoMessageWindow/window = new(_msg, _width = 200, _height = 100, _x = 10, _y = 9, _px = -50, _py = -38)
window.setStyle(MDSTYLETEXTURE)
window.setColorFlags(_rFlag = TRUE)
window.setTexture(icon('MDTextures.dmi', "3"))//, icon('MDTextures.dmi', "2"))
window.setBorderColor(rgb(0, 0, 0))
window.draw("Test")
window.yesButton.setObjectToPass(_cell)
window.noButton.setObjectToPass(_cell)
window.yesButton.setCallBack(/proc/testWindow)
window.noButton.setCallBack(/proc/testWindow)


When they press yes or no the following code is executed:

proc/testWindow(MDYesNoMessageWindow/_window, MDObject/_object, MDCellGraphic/_cell, mob/m)
if(_object == _window.yesButton)
world<<"Yes!"
del(_window)
if(_cell)
var/text = _cell.text.value
_cell.table.data.values[_cell.index] = "Test"
world<<"Modified cell [_cell.index] from \"\icon[_cell.img] [text]\" to \"\icon[_cell.img] [_cell.table.data.values[_cell.index]]\""
_cell.table.reloadCellAtIndex(_cell.index)
else if(_object == _window.noButton)
world<<"No!"
del(_window)


The way it's set up to work when you click on a cell is as follows:

mob/proc/rowSelectedForTable(MDTable/table, MDTableCell/cell, index. mob/m)
if(table == m.table1)
var/MDCellGraphic/_cell = cell
m.createWindowForObject(_cell)


Please post comments, suggestions, likes, dislikes, etc... Thanks!


Added an example of how to use this for an inventory system. The inventory automatically updates when you add and remove items from it.

In the screen shot the table on the top right are items you can add to your inventory by clicking on then. The table in the top left is your inventory. If you select an item in your inventory it'll remove that item from your inventory.

The download link is the same as the one in the first post.


Added/Edited the textures for the inventory example.
Set the style of the top right table to MDTABLESTYLENONE.
Fixed a couple bugs.
Looks pretty interesting based off the screen shots. I'm guessing this is all on-screen object based, rather than interface based, and if so that is good.

What about if say, the inventory has more items than it has room to show, though? or what if the player list does? I'd assume ^ V etc will move through them, but with multiple areas to work with I'm curious about how you've handled that.
In response to Toddab503
You are able to download the source from the first post and see first hand how it all works in demo.dm. It uses on-screen objects. I'd thought I'd make it for people to use for when the flash client comes out. The ^ and v are for scrolling the bottom left table. You would have to add something in to scroll the inventory. I'm going to work on a scroll bar in an update. It's easy to have the table scroll though which you can see in the demo.dm? It's easy to set up what each cell clicked on does for different tables. There is an example of how that works in demo.dm.

Added in "MDWindows" You can use them for popup message, alerts, character creation screens, etc...
Fixed a bug where if someone else executes a piece of code which tells another player's table to reload data it would not reload properly. Updated the project files for the download link.
Eliminated the use of "usr". It would cause problems when a player tried to update another player's table. Added mob/m to the callback function which returns the "owner" of the table.
Grabbed some Marble Textures from the internet and added them in to show it doesn't matter what size the texture is.

Made it so you can scale textures.(You don't have to though)

Made it so you can add borders to tables, cells and windows.

Added in a inside vertical padding for tables

In response to Mikeytdan
Looking good. Nice improvements so far. That text is too close to the border in the alert box, though. I imagine that could be fixed with a little padding, though, assuming its compatible.
Pretty impressive effort. I'll try to utilize this in HexGame for my Lobby and let you know how it goes.

If your gung-ho on adding features, I'll be doing a player registration screen, a login screen, an active player list, and an active game list, plus a few buttons for creating and joining a game which you already have covered.

If I end up adding anything of my own, I will certainly try to integrate features where it makes sense and share those with you.

This type of project is huge for reducing development time so my hats off to you for sharing it.
In response to Toddab503
That is a window, they don't use padding. All you would need to do is move it down a few pixels. I'll be sure and do that in the next update. It's an easy fix. Thanks for the input. :)
In response to PopLava
Thank you for your comments! I appreciate that you are going to try and use this. :) I'll gladly include anything you would like to contribute. I eventually want to make a lot of premade systems such as a nice inventory, login, save system, etc... using this and provide the files to everyone for use.

If you have any questions, concerns, requests please let me know!
Added an important fix to MDTable.reloadIfNeeded()
- Added an _index parameter. If you're deleting an object from a list and want to call reloadIfNeeded so you're not updating the table if you don't need to you'll want to pass the index of the cell that you are deleting. EX: MDTable.reloadIfNeeded(_index)

On top of that, when removing data from a MDData object the callback function now returns the index of the object removed.

EX: mob/proc/updateInventory(mob/m, _index)

If there is no owner set for the MDData object no mob will be passed back so avoid that parameter.

I also moved the text down a little on the yes/no window. I updated the screenshot for it on this thread.
While playing around with the library, I noticed you haven't added solid background color yet and I ended up adding it while messing around. Here's the code changes in case it's useful.

Demo.dm
var/_msg = "Would you like to modify the cell at index?"
var/MDMessageWindow/window = new(src, _msg, _width = 300, _height = 100, _x = 1, _y = 9, _px = -50, _py = -38)
window.setStyle(MDSTYLESOLID)
window.setBorderColor(rgb(255, 0, 0))
window.setBackgroundColor(rgb(0, 123, 223))
window.draw()


MDConstants.dm
...
#define MDSTYLESOLID 4


MDWindow.dm
MDWindow
var
...
backgroundColor

proc
setBackgroundColor(_rgb)
backgroundColor = _rgb

draw(_key = FALSE)
...
if(!_i)
...
else if (style == MDSTYLESOLID)
_i = drawBlank(width, height)
_i.SwapColor(rgb(0,0,0,0), backgroundColor)
In response to PopLava
Thanks! I'll add it in right away! :)

I'll update it for MDTable as well. I'm going to work on mixing MDWindow with MDTables so there is no need to update things in both places all the time.
Cool. :)
In response to PopLava
Messed around with adding custom borders. I tried integrating with the textures but couldn't get it figured out before having to pack up and leave. I also rushed this post a little bit so integration isn't perfect. Example is adding an all new function called drawBorder which would replace drawNonSolidRect(). Hopefully I got everything covered here.

Demo.dm
    var/_msg = "Would you like to modify the cell at index?"
var/MDMessageWindow/window = new(src, _msg, _width = 300, _height = 100, _x = 5, _y = 9, _px = -50, _py = -38)
window.setStyle(MDSTYLESOLID)
window.setBorderWidth(1,5,15,25)
window.setBorderColor(rgb(255, 0, 0))
window.setBackgroundColor(rgb(0, 123, 223))
window.draw()


MDWindow.dm
MDWindow
var
...
topBorderWidth=1 // default borderWidth is 1
bottomBorderWidth=1
leftBorderWidth=1
rightBorderWidth=1

proc
setBorderWidth(top,bottom,left,right)
topBorderWidth = top
bottomBorderWidth = bottom
leftBorderWidth = left
rightBorderWidth = right

draw(_key = FALSE)
...
if(!_i)
...
// DRAW BORDER
...
else if(style != MDSTYLENONE && borderColor)
_i.drawBorder(borderColor, topBorderWidth, bottomBorderWidth, leftBorderWidth, rightBorderWidth)
//_i.drawNonSolidRect(borderColor)


MDIconAddOns.dm
icon/proc
drawBorder(_rgb, topBorderWidth, bottomBorderWidth, leftBorderWidth, rightBorderWidth)
DrawBox(_rgb, 1, bottomBorderWidth, Width(), 1) // BOTTOM BORDER
DrawBox(_rgb, 1, 1, leftBorderWidth, Height()) // LEFT BORDER
DrawBox(_rgb, Width(), 1, Width()- rightBorderWidth, Height()) // RIGHT BORDER
DrawBox(_rgb, 1, Height(), Width(), Height() - topBorderWidth) // TOP BORDER


[edit] - Looks like we need to (or not) account for default border width because you get a 1 width difference between top/left/right/bottom borders. Could be by design though. :)
Sitting here mulling over the design and I'm wondering if a partial redesign is in order. Sucks to consider it and it sucks to suggest it, so, take it lightly. I went to add a Button type which is what brought this to light.

Seems like you (we (BYOND)) would like to see this support buttons, lists, dialogs, tables, windows, labels, and etc.

Technically, everything is a series of rectangles overlapping other rectangles until finally, some text goes on top.

A quick example...
Object
generic events
Click()
text
Rect
Common Attributes
background
border
size
position
Label
Button
Click()
handle animating button (?)
Dialog
OK
OKCancel
YesNo
etc
Window
New
Create Minimize, Maximize/Restore, Close Buttons using defaults
List
Table
Input
Output
Bar
etc

Essentially, the mdwindow type should merge with the root (object) type and everything could inherit from it. You aren't far off.

I beleive this would make additions easier along with the eventing.

Instead of calling the project Table, it could become DrawMapControls or something like that.

Just an idea.
When I said I wanted to merge them I was going for something along the lines of what you just said. Also, It's named Table because that's what I was originally making till it evolved into something bigger. DrawMapControls isn't a bad name. I'm going to try and combine them tonight.
Page: 1 2 3