This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Encreedem's profile picture

Graffiti v1.7.2 - The first IDE for GUIs

Started by Encreedem, 06 July 2013 - 05:27 PM
Encreedem #1
Posted 06 July 2013 - 07:27 PM
Graffiti v1.7.2 - The first IDE for GUIs


I'm not sure whether the term "IDE" is correct so I'm just going to explain it using this Wikipedia article:


"A graphical user interface builder (or GUI builder), also known as GUI designer, is a software development tool that simplifies the creation of GUIs by allowing the designer to arrange widgets using a drag-and-drop WYSIWYG editor. Without a GUI builder, a GUI must be built by manually specifying each widget's parameters in code, with no visual feedback until the program is run."


And that's pretty much it! (except for the drag-and-drop part, CC isn't really made for that)
Feel free to post bug reports, suggestions, ideas and questions.

I'm always happy when I'm able to improve this program! :D/>

Note: I'm not working on this program anymore. It might or might not be incompatible with newer CC versions.

Motivation-o-meter:
A simple bar showing the possibility whether I'm working on this program or school's keeping me busy.

low………….high
| - - - - - - - - - - |
| - - - - - - - - - - |

Features:
  • Create an unlimited amount of windows.
  • Add objects to those windows (see "Supported Objects")!
  • Easily change the design and attributes of each object.
  • Switch between windows using only one function.
  • Use an API to interact with the windows that have been created with the editor.
Supported objects:
  • Button
  • Text
  • Variable
  • ProgressBar
  • Input
  • List
  • CheckBox
  • RadioButton
  • Slider
  • Panel
  • ScrollView
More details are in the instructions below. (currently: "Complete tutorial for Graffiti v1.7")

Download & Changelog
v1.7.2: reMpHkBb

Older versions
Spoilerv1.7.1: YE2WetaX
  • Bugfix: Graffiti crashes when you use it via a monitor and try to change certain attributes.
v1.7: A5SXV8fZ
  • Added CheckBox object.
  • Added RadioButton object.
  • Added Slider object.
  • Added DropDownList object.
  • Added converter.
  • Added color theme "Fire".
  • Added "load" attribute to some objects and removed the "getVariableValue" and "getProgressBarValue" functions.
  • Improved editor GUI.
  • Implemented "mouse_drag" support for objects and the editor.
  • Changed the event handling of buttons: The user-function with the button's objID attribute (instead of the param attribute) as its name gets called now.
  • Added a list editor and removed the old way of setting the elements of a List object.
  • Renamed "elements" attribute of the List object to "Items" (Just trying out whether it looks better that way)
  • Renamed most tables to have an uppercase first letter.
  • Bugfix: Graffiti crashes after writing something into an Input-object.
  • Bugfix: The move- and scale-pixels of a ProgressBar object have an incorrect position when it is facing up.
  • Bugfix: The Input object isn't reading correctly when it is inside a container.
  • Bugfix: The program crashes when you try to load a non-existent window.
v1.6.2: igxw4tWP
  • Bugfix: The ScrollView wan't scrollable in edit mode.
  • Added "GraffitiData" folder which contains all data for Graffiti.
  • Windows get saved separately now.
  • Added Settings-file.
  • Added multi-language support.
v1.6.1: 9JUUk7Dp
  • Added "toggle" function type for buttons.
  • Added ScrollView container (a container with a vertical and/or a horizontal scroll bar).
  • Improved the save-file.
v1.6: 6d5CeVPN
  • Added container objects.
  • Added color themes.
  • Renamed almost everything from "screen" to "window".
  • Renamed the "Slider" object to "ProgressBar".
  • Renamed most "show" functions to "draw".
  • Completely changed event handling and displaying of the objects.
  • Removed AddOn support.
  • Bugfix: Elements of List-objects couldn't be changed. (This time it does work!)
v1.5: CtnKvYW9
  • Included the GraffitiAPI into the main program (i.e. the file doesn't exist anymore: use os.loadAPI("Graffiti") instead of "GraffitiAPI")
  • Fixed a bug where input objects acted strange when the program got used as an API.
v1.4: RJBDx5Q5
  • Added advanced computer support.
  • Removed the automatic adaption of objects to the screen size after making it more complicated and realizing that it didn't do what I wanted anymore.
v1.3: T0nyRBcJ
  • Added an API
  • Added the attributes "horizontalAlignment" and "verticalAlignment" to the editor. They allow you to automatically move/scale certain objects when the screen-size changes. (More details under instructions/Editor/Design below)
  • Bugfix: Lists with enabled "isMultiselect" attribute couldn't be changed.
  • As usual, more bugfixes.
v1.2: r41PQguw
  • Included AddOn support.
  • Bugfix: The elements of the list-object couldn't be changed. (Fixed in v1.3)
  • More bugfixes
v1.1.1: ssiVGXct
  • The direction of a slider can be changed in "Design"-mode now. (You have to click exactly on the same x- or y-coordinate)
  • Improved the input-object. Now it shouldn't matter what kind of keyboard you use.
  • Added a "set parent" button. It determines which window will be shown when the "Back"-button gets pressed.
  • Bugfix: The "message"-attribute of the list wasn't shown when using the editor.
  • Lots of annoying bugfixes.
v1.1
  • Added a screen-editor with (almost) full touchscreen support!
  • Added a new object: List
  • Improved the Input-object (Now it also supports upper-case letters! Wooho!)
  • Probably much more but I forgot what it was.
  • Bugfixes
v1.0: gCRkvMyu
  • Initial release
API
Note: You can load Graffiti as an API since Version 1.5! The API file itself is outdated!
v1.1: http:JACwSMXk
  • Same as the v1.4 update.
v1.0: FkjkihWr
  • initial release

Bugs and planned features

Progress
Next (planned) version: 1.8
  • Lots of cleaning
  • Bugfixes: 0%*
* This value will never change.

Screenshots
SpoilerThis is what the objects look like:
[attachment=1413:2013-12-15_21.28.29.png]

Usage examples:
Ghosty: (more informations somewhere below)
[attachment=1295:2013-08-01_23.23.19.png]

Login window:
[attachment=1414:2013-12-15_21.05.51.png]

Here's how I've been using the program:
  • Overview over the energy in the base.
  • Security window (controls the important stuff in the base)
  • Using AddOns: Sending rednet-messages and files to other computers.

Videos
Object overview
Spoiler[media]http://www.youtube.com/watch?v=FebXgbxbhN8[/media]

Editor tutorial/demonstration
Spoiler[media]http://www.youtube.com/watch?v=urxOzGyaXTY[/media]

Official AddOns and programs which use the API
Warning: I haven't tested these programs with newer versions of Graffiti. Make sure that you have the correct version before using one of them. (No, I don't know which version they need.)
Note to myself: This is obsolete… make some new stuff.Instructions
Partially moved/copied to GitHub.

Complete tutorial for Graffiti v1.7
SpoilerGetting Started
Firstly you have to download and install Graffiti. I recommend you to always download the newest version which you can find under the "Changelog" section above or on pastebin and GitHub.
Use an advanced computer and download Graffiti. The easiest way to do this is to enable the http API and enter "pastebin get <replace with pastebin code> Graffiti".
Press enter and after a few seconds a message should appear telling you whether Graffiti has successfully been downloaded.

Now you have to run Graffiti with the parameter "edit".
Example: Graffiti edit (Of course you have to replace "Graffiti" with something else if you downloaded it with another name).
[attachment=1432:2014-01-11_17.12.20.png]

Press enter and now you should see the setup. It allows you to specify following settings:
  • Language (right now only "en-US" is supportet)
  • Color Theme
  • Show/Hide data folder (the data folder will be in the root directory by default and contains all data for Graffiti including the languages, color themes, settings, logs and your projects)
Warning: Due to a bug in version 1.7 you can't skip the setup. It only consists of two windows so it shouldn't be a problem.
Warning 2: Due to another but in version 1.7 the options "Show Data Folder" and "Hide Data Folder" are swapped. Choose "Hide Data Folder" if you want to show it. This will be fixed in the next version!

[attachment=1434:2014-01-12_22.44.08.png]
[attachment=1435:2014-01-12_22.44.20.png]

After finishing the setup you should see a blank screen with four buttons in the edges. Before you continue I would recommend you to close Graffiti and restart it with the parameter "edit" (just like you did before). That way the data folder will be created and the setup won't appear again. For now there is no better way of saving everything. I guess I'm just lazy…

The Window Manager
Exept for the setup, you will always see the window manager first when you start Graffiti in edit mode. As the name suggests you will be able to manage your windows. That includes…
  • creating new windows,
  • editing their content,
  • renaming and deleting existing windows,
  • setting a parent (choosing the window that should be shown after pressing the integrated "back" button) and
  • setting the startup window (the window that will show up first when starting Graffiti normally).
Most of these parts should be self-explanatory (if not, please write a post or contact me via pm).
Note that before creating or renaming windows you have to specify a name in the "Input" field above.

[attachment=1433:2014-01-11_17.49.16.png]

Create your first window by entering a name in the (depending on the color theme you are using) gray "Input" field above and press the "New" button. Now select the window in the list to the left and press the "Edit" button. This will bring you to the next editor:

The Window Editor
This is probably one of the two most important parts and therefore very long. If you don't like reading then I'm surprised that you even got that far and I would recomment you to try the "design" part out for yourself (it shouldn't be very difficult but I can't really tell because I created the program) and skip to the "coding" part.

Note: You can use Graffiti with the computer or with an adjacent monitor. If the latter then some features might not be available and some might work differently than on the computer itself! All of those differences will be explained below.

The editor allows you to do the following things:
  • Create new objects,
  • Move and (depending on the object) scale them.
  • Remove objects.
  • Edit the attributes of existing objects.
  • Enable and disable the default buttons "Back" and "Refresh" by clicking on them.
  • Go back to the window manager using the "Options" button.
Creating new objects
Just click on an empty pixel. A list of objects should appear. Click on one of them to add them to the window.
Yep, that's it.

Moving and scaling objects
Click an object to select it. You will see a pixel in the upper left corner of this object which I call the "Move"-pixel. Depending on the object you might also see a second pixel in the lower right corner. I'm calling this one the "Scale"-pixel. It shouldn't be too hard to guess what they do. You can either…
  • click one pixel and then click somewhere else to set the new position/size of the object, or
  • drag a pixel.
Please note that you have to complete every move- and scale-action. Assuming that you are using the default color theme, this will be indicated by a green pixel instead of the magenta or pink "Move" or "Scale" pixel.

"Options" List
This list allows you to access extra features. As for 1.7 they are called "Attributes" and "Delete". Again, they should be self explanatory.
If you are using Graffiti directly via a computer then you can simply right click an object to access this list.
Otherwise, if you are using it via a monitor then you need to click a selected object anywhere except the marked pixels (which means that you basically need to doubleclick a non-selected object).

Deleting objects
… should be obvious after reading how to open the "Options" list.

Attributes
After selecting "Attributes" in the "Options" list you will get to Graffiti's attribute editor. Again, as with the previous editors, the purpose of this one should be fairly obvious.
The attribute editor hasn't improved very much since version 1.0 but it should be easy to use nontherless. Just click an attribute to edit it.
First of all, there are different types of attributes:
  • text
    • After clicking it you can either directly enter a new value or, if you use Graffiti via a monitor, a yellow pixel will appear which indicates that you have to go to the computer and enter the new value.
    • Usage example: the "object ID" attribute or the text of the "Text" object (creative, right?).
  • number
    • Just like the text but only numbers will be accepted.
    • Usage example: Setting the maximum size for certain objects.
  • list
    • Goes through a list and selects the next item each time you click the attribute.
    • Usage example: Changing what a button should do when it got clicked.
  • bool
    • Simply changes a value from true to false, or vice versa.
    • Usage example: Set whether an "Input" object should show the input or treat it like a password. (I mean that it shows stars instead of text, if that makes more sense.)
  • table
    • Switches to the list editor which allows you to edit tables. The list editor itself should be self explanatory so I'm not going to explain it. You can, however write a post or contact me via PM if you do want me to write instructions for it.
    • Usage example: Editing the items of a "List" or "DropDownList" object.
The Default Buttons
There are currently 4 default buttons:
  • Quit (upper right, always shown)
  • Back (upper left, toggleable)
  • Refresh (lower right, toggleable)
  • Options (lower left, only shown in editor mode)
The default buttons "Back" and "Refresh" can be toggled on and off by clicking them in edit mode.
The "Back" button switches to the parent window that has been set in the window manager. If no parent window is set then nothing will happen.
The "Refresh" button simply redraws the window, causing all objects to be updated.

Objects
Additionally to the description, I'm also writing what each object returns if the user interacts with it.
Note: While I'm trying to keep all lists as accurate as possible, the objects that are described here might not be up to date with newer versions than 1.7.

Button
The "Button" object does something when the user clicks it.
Attributes:
  • Object ID
    • Used to identify an object. In this case it's used to call functions or switch windows when it got clicked and it will be returned by Graffiti's "pullEvent" function if it has been loaded as an API.
  • Text
    • The text of the button. It is always centered and automatically trimmed if the length of the text is longer than the button's width.
  • Function type
    • Determines what should happen if the button gets clicked. Those function types are available:
      • "function" calls the function in the "UserData" table which has the button's object ID as its name. Example: If the button's name is "Testbutton" and it got clicked then the function "UserData.Testbutton" will be called.
      • "toggle function" is the same as "function" with the difference that the button will be toggled each time it got clicked. It will also return the new state of the button (again, more explanations in the "Code" section below).
      • "switch" is the only type that accesses the "Window" attribute instead of the button's ID. If the button got clicked then the specified window will automatically be shown if it exists.
  • Window
    • The name of the window that should be switched to if a button with a "swich" function type gets clicked.
Graffiti.pullEvent returns
  • "button_clicked" event
  • its ID
if the button gets clicked.

Text
The "Text" object is the simplest one of all. It only displays text and therefore it has only one attribute:
  • "text"
Variable
The "Variable" object is similar to the Text object with the only difference that its text gets assigned dynamically (i.e. a function which returns the text gets called each time the object gets drawn).
  • Object ID
    • It doesn't really have any use for this object but I didn't remove it in case that I needed it later. (Yes, that's an excuse for my lazyness.)
  • Load Function
    • This attribute exists for all objects that have a dynamic text or content. As I mentioned above the Variable object gets its text from a function. The "Load Funciton" attribute needs to be the name of the function and the function itself needs to be in the UserData table.
ProgressBar
The "ProgressBar" object is similar to the Variable object but instead of text you can only specify a number between 0 and 100 and the ProgressBar will automatically display it in form of a beautiful, colored stripe. It has the same attributes as the Variable object:
  • Object ID
  • Load Function
    • It may only return a number between 0 and 100 but it should at least not crash if the number is negative or bigger than 100.
Input
The "Input" object is basically like the TextBox of Windows (the OS). You click it and then you can enter something.
  • Object ID
    • This attribute can be used to get the text that has been entered. The text will always be saved in the table "ObjectData.Input" with the Object ID as the key.
    • Example: If the user enters "Hi there!" into the Input object with the ID "Testinput" then the table "Input" inside the table "ObjectData" will contain the key "Testinput" with the value "Hi there!".
  • Message
    • If the user runs Graffiti via a monitor then he has to go to the computer after touching the Input object. The message will be displayed there. (Which means that this attribute is useless in case that you only intend to use it via the computer itself.)
  • Is password
    • Determines whether the input should be replaced by stars. The text in the ObjectData.Input table isn't affected by this attribute.
Graffiti.pullEvent returns
"text_changed" event, objID, text
  • "text_changed" event
  • its ID
  • the entered text
when the user enters something.

List
The "List" object contains a table of items and displays them in form of, you guessed it, a list. You can also select one or more items depending on the "Is multiselect" attribute.
  • Object ID
    • Used to identify a list after throwing an event because the item selection has changed.
  • Items
    • The list/table of items that should be displayed. It can be edited using the List Editor which can be accessed via the Attribute Editor.
  • Is multiselect
    • Determines whether only one or more items can be selected at once.
Graffiti.pullEvent returns
  • "selection_changed" event,
  • its ID,
  • the key of the selected/deselected item,
  • whether the selected item has been selected or deselected (true means selected and it will always be returned if "Is multiselect" is set to false)
when the user selects any item.

CheckBox
The "CheckBox" object is very simple and probably everyone already knows what it does. You click it and the little X to the left gets toggled. You can access its state (whether it's checked or not) under "ObjectData.CheckBox.<CheckBox ID>".
  • Object ID
  • Text
  • Checked by default
    • Determines whether… you won't believe it: the CheckBox will be checked on startup.
Graffiti.pullEvent returns
  • "checked" event,
  • its ID
  • whether it is checked now
when the user clicks it.

RadioButton
The "RadioButton" object has similarities with the CheckBox. The main difference is that each RadioButton has a group. In this group only one RadioButton at a time can be checked. If the user clicks one of the RadioButtons then this one will be checked and all the other ones will automatically be unchecked. This object is useful if you want to have the simplicity of a CheckBox but more options than just "true" and "false".
  • Object ID
    • Used to save its state under "ObjectData.RadioButton.<ID>". Therefore you have to give each RadioButton a unique ID. I might implement a feature which gives each object a unique ID automatically.
  • Text
  • Group
    • Only one RadioButton per group can be checked.
  • Checked by default
    • The RadioButton will be checked on startup if this attribute is set to true. If more than one RadioButton per group has this attribute set to true then the last one will be checked.
Graffiti.pullEvent returns
  • "radio_changed" event,
  • its ID
when the user clicks it.

Slider
The "Slider" object is a simple bar with a cursor (I honestly don't have a better description) which points at a number between the minimum and maximum value of the Slider object.
  • Object ID
  • Minimum Value
    • The smallest possible number which will be selected when the cursor is all the way to the left.
  • Maximum Value
    • The biggest possible number which will be selected when the cursor is all the way to the right. The length of the slider is the difference between the maximum and the minimum value and will automatically be adapted if one of the attributes get changed.
Graffiti.pullEvent returns
  • "slider_changed" event (This one might change in a later version.)
  • its ID
  • its current value
when the user clicks it.

DropDownList
The "DropDownList" object has similarities to the List object, referring to the attributes. The only difference is that, instead of displaying all objects, it only shows the selected object. When the user clicks it, the list expands and he can select one of the shown items.
  • Object ID
  • Items
  • Load Function
    • All attributes are equal to the List attributes.
Graffiti.pullEvent returns
  • "selection_changed" event
  • its ID
  • the key of the selected item
when the user clicks it.

Containers
Containers are a special form of the object. You can interact with them just like with any other object but you can also create objects inside of them. You should also be able to nest containers (place containers inside of other containers) up to 255 times. As for version 1.7 those are available:

Panel
The "Panel" object is the most simple container and the base for every other container. It simply is a box which can contain objects, automatically moves them if it gets moved and prevents them from appearing outside of its border. You can use it to limit the size of objects which change their size automatically, to emphasize one or more objects or simply for astethic purposes.

ScrollView
The "ScrollView" object can have 0 to 2 scrollbars which the user can use to view content which is outside of its borders. It's probably easier to understand than I can explain it. Everybody has already used scrollbars before.

Using them in the editor:
As I mentioned above, each ScrollView can have 0, 1 or 2 scrollbars. Enabled scrollbars will be shown normally. Disabled ones will be hightlighted (by default: lime). Simply click a scrollbar to en- or disable it.
To move its content, simply click on one of the arrows of a scrollbar (the ScrollView needs to be selected).

Man, I wrote much more than I expected… Have some fun experimenting with all the objects.
Now, lets get to the interesting part.

Writing a program with Graffiti
There are two ways of writing a program with Graffiti:

1) Directly editing Graffiti to add functions and variables
In my opinion this way of coding is becoming obsolete and I might remove it in a later version. For now it should still work and if you want to use this way then I would recommend using it for small and simple programs which only you are going to use.

2) Writing a program that uses Graffiti as an API
Yes, you can also load Graffiti as an API. Neat, right? It has the following advantages over the other mentioned way of writing programs:
  • You keep a better overview over all functions and variables if you work on more than just one project (the current project can be changed in the settings file which you can find under "GraffitiData/Graffiti.cfg").
  • It also makes it easier to share programs because you would have to give others only your program and they could download Graffiti by themselves without having to change anything.
  • The API provides the function "pullEvent" which allows you to get any kind of event. Except for the Text and Variable objects as well as containers, most objects throw events when the user interacts with them (see "Objects" section above). By editing Graffiti itself you can only get "button_clicked" events.
  • If you find a bug or have problems with your program then it's much easier for me to help you because you won't have to specify any changes or the code that is at a certain line number.
  • Definitely more, but I can't think of any other ones right now.
Basically there shouldn't be many differences except for event handling and access to temporary data. I simply don't think that it's a good idea to edit Graffiti itself but for now I'm still going to explain how to do it.

Using Graffiti by editing it
Start by editing Graffiti (enter "edit Graffiti" or use an editor like Notepad++ or another one of those nice editors). Now you will have scroll a bit down past all those variables, settings and color themes until you reach the "UserData" section. I really recommend that you only edit the "UserData" table!
You can include variables and two types of functions into the table:
  • Those which get called when a button gets clicked and
  • those which return a value when an object gets loaded.
A function which gets called when a button gets clicked needs to have the button's "Object ID" as its name.
Example if the button's "Object ID" attribute is "test" or "toggleTest": (you can also find some in the program itself)

function UserData.test()
  sleep(1) -- that way the button will be green for one second
end
-- or
UserData.toggleTest = function(state)
  rs.setOutput("front", state)
end

Note: The argument "state" is only necessary if the button can be toggled (this can be changed by editing the "Function type" attribute) and it is used to determine whether the button has been toggled on or off. If the button can't be toggled then the state will always be "true".

Making a function which returns a value for an object when it's getting drawn:
As I mentioned in the "Objects" section, you can dynamically assign the values of certain objects like the Variable, ProgressBar, List or DropDownList objects by specifying their "Load function" attribute. Just like with the buttons, the function in the UserData table needs to have the same name as the one that was specified in the attribute.
Example if a ProgressBar object has the "Load function" attribute "getRandomNumber": (again, an example is in the program)

function UserData.getRandomNumber()
  return math.random(100)
end
-- Another example for the "Variable" object
function UserData.getTime()
  return textutils.formatTime(os.time(), true)
end

Using Graffiti as an API
There are three things that you need to know if you want to use Graffiti as an API:
  • How to control your windows,
  • how to acces information about objects and
  • how to handle events.
First of all, start by loading Graffiti as an API by entering…

os.loadAPI("Graffiti") -- "Graffiti" is the name of the program, you might need to specify a path.

Controlling the windows
Those functions are available:
  • drawWindow(windowID)
    • If you specify the windowID argument then this window will be drawn and set as the current window.
    • If you don't specify this argument then the window will simply be redrawn.
  • getCurrentWindow()
    • Returns the ID of the current window.
  • clearScreen()
    • Has the same function as the "clear" program.
Accessing object data
Most objects save temporary data in the "ObjectData" table (that's why it's useful to give every object its own ID).
Warning: The ObjectData might not contain any information about an object if the user didn't interact with it.
Example: All buttons that can be toggled save their state under "ObjectData.Button.<object ID>"
More examples:
  • Input: The text that the user entered.
  • List and DropDownList: A table containing the keys of the selected Items (careful: The table might not exist if the user didn't click it. Always check whether it's null before you try to access it!)
  • CheckBox: A boolean value indicating whether the CheckBox is checked or not. (Again, it might be null. Last warning!)
  • RadioButton: Contains the ID of the currently selected RadioButton. The key is the "group" attribute. Also make sure that each RadioButton has its own unique ID per group.
  • Slider: An integer representing the currently selected value.
If you named your program "Graffiti" then you can access them that way:

os.loadAPI("Graffiti")
local btnTestState = Graffiti.ObjectData.toggleTest or false
rs.setOutput("front", btnTestState) -- example

Note: You can, of course, access the UserData table and insert functions which can be used for the feature which I've explained in above ("Making a function which returns a value for an object when it's getting drawn")

local function getRandomNumber()
  return math.random(100)
end
Graffiti.UserData.getRandomNumber = getRandomNumber


Handling Events
Getting events from Graffiti is very similar to getting events from the os.pullEvent(). The difference? Here:

Graffiti.pullEvent("requested event")
Simply replace "requested event" with a certain event (They are listed in the "Objects" section) or leave it empty to get every event.
Note: Graffiti's pullEvent function will only return custom events and not the ones which os.pullEvent would return.
Note 2 (Important!): The "quit" event gets thrown when the user presses the quit button. It ignores the "requestedEvent" attribute, therefore it can always be thrown!

Here's an example about how to get input from any button. Read the "Objects" section if you want to know more about the different event types and the returned parameters.


os.loadAPI("Graffiti")
local finished = false
Graffiti.drawWindow("main") -- "main" is just an example, you can name it however you want.
while not finished do -- Loops until the user presses the quit button.
  -- Waits until the user clicks any button or the quit button.
  --(The "quit" event can always be returned even if you specify a requested event!)
  local event, objID = Graffiti.pullEvent("button_clicked")

  if (event == "quit") then -- If the user pressed the quit button, stop the loop.
	finished = true
  elseif (event == "button_clicked") then -- If he clicked a button, check the ID of the button to see which one has been clicked.
	if (objID == "Testbutton") then
	  -- Code that does stuff when a button got pressed goes here.
	elseif (objID == "anotherButton") then
	  -- Code that does stuff when another button got pressed goes here.
	end
  end
end
Graffiti.clearScreen()
os.unloadAPI("Graffiti")

Graffiti 1.7 paths and object accessing via code
SpoilerPlease note that I've originally written these instructions for pastebin due to the fact that the CC Forum was down when I tried to access it. Therefore the formatting might not be very good.

How paths work:
First of all, remember the following:
  • Each object is a table inside a window or other container, which are a tables too.
  • Each object has its own ID, which is automatically generated upon its creation.
  • Each object inside its container has a unique ID. That means that objects which are in different containers can have the same ID, but…
  • Each object has its own unique path.
Before describing what they are, I'll give you an example.
A path is a table and it can look like this:
{1}
(The 1 is the ID of the object.)
or like this
{1, 1}
(The first number represents the ID of the object's container, the second number is, again, the ID of the object)
… or like this
{1, 1, 1}
(In this case the object is inside a container inside another container inside the window.)
Of course the number can be anything, depending on how many objects you have.
Example:
If you have a "ScrollView" container with the ID 2 which contains an empty panel with the ID 3 then an object that gets created in there would have the path {2, 3, 1}.

How do I find out the path of my object?
Just look inside the window-file.

But how does that help me access my objects?
I'm glad you asked, here's another answer which is way too long:

The ID of an object is also the key under which it has been saved inside its container.
That means that an object with the ID 2 can be accessed via "Container.Children[2]". ("Container" is just an example. Don't look for it inside Graffiti's code.)
The "Container" can either be a window or a container-object like the Panel or ScrollView objects. Therefore, if you nest containers then you can use the path to access an object through several containers via the appropriate key inside the "path"-table. I really hope that made sense. Otherwise here's another exapmle:

YAY! AN ACTUAL CODING EXAMPLE! (Also, in case of TL;DR)
We've got a window which contains:
  • A button (ID: 1, path: {1})
  • A Panel (container) (ID: 2, path: {2}) which contains
    • another button (ID: 1, path: {2, 1})
We can access the first button using the following code:
local button1 = Windows.Children["yourWindowName"].Children[1]
or
local button1_viaApi = Graffiti.Windows.Children["yourWindowName"].Children[1]
… if you use Graffiti as an API.

If you want to access the second button then you need to acces it the following way:
local button2 = Windows.Children["yourWindowName"].Children[2].Children[1]

Now that you know how to acces objects, let us try to edit them via your code.
Example: Changing the Items of a List or DropDownList object.

os.loadAPI("Graffiti")
local list = Graffiti.Windows.Children["TestWindow"].Children[1]
local listNested = Graffiti.Windows.Children["TestWindow"].Children[2].Children[3]
list.Items = { "Item 1", "Item 2", "Item 4" }

Due to the fact that "list" is actually a reference, the Items will be changed.
You can, of course, also write the following if you only want to access it once:
Graffiti.Windows.Children["TestWindow"].Children[1].Items = { "Item 1", "Item 2", "Item 4" }

API (1.6+)
SpoilerMost of it stayed the same so I'll just write the new stuff here and you can go to the "1.3 - 1.5" help if you need more information.
1) You can refresh the window by calling "drawWindow()" without any parameters.

2) New function: Graffiti.pullEvent([optional] requestedEvent)
It's pretty much the same as "os.pullEvent()" with the only difference that it will only return custom events that get triggered by the user when interacting with any object. It returns the event type, the object ID and, depending on the event type, some extras.
I recommend you to use this function instead of "getInput()".

Here's the list of custom event types:
  • "quit": The user clicked the quit-button. Returns no extra parameters. (Important note: You might not like it but this event can always get returned, even if you specify another event type)
  • "button_clicked": The user clicked a button. Returns "true" (because the state won't change).
  • "button_toggled": The user toggled the state of a button. Returns whether the button got toggled on or off.
  • "text_changed": The user entered something into an Input-object. Returns the text that the user entered.
  • "selection_changed": The user clicked an element of a list. Returns the text of the selected element.
Here's the updated example code:


os.loadAPI("Graffiti")

Graffiti.setVariableValue("newVariable", "couldBeAnything")
Graffiti.setSliderValue("testSlider", 87) -- percent.

local quit = false
while not quit do
  local eventType, objectID, toggleState = Graffiti.pullEvent("button_toggled")
  if (eventType == "quit") then
	quit = true
  else
	print("Button clicked: " .. objectID)
	print("Toggle state: " .. toggleState)
  end
end

API (1.3 - 1.5)
SpoilerUsing the API is extremely easy. Create a GUI using the normal editor but you only need to follow the "Design" and "Attributes" part because the "Coding" part will be done in your own program.

Here's an example of how you could use the code:

os.loadAPI("Graffiti")

Graffiti.setVariableValue("testVariable", "variable-value")
Graffiti.setSliderValue("testSlider", 87)

local monitorSide = "right"
local input = ""
local currentScreen = "mainScreen"

while input ~= "quit" do
  input, screen = Graffiti.getInput(monitorSide)
  currentScreen = (screen == nil) and currentScreen or screen
  print("Selected list-item: " .. GraffitiAPI.selectedItems["testList"])
  print("User input: " .. GraffitiAPI.userInputs["testInput"])
  print("Pressed button: " .. input) -- "param"-value of the pressed button.
end

Basically, you've got these 4 functions:
  • setVariableValue(varID, value): Determines which variable should display a certain value.
  • setSliderValue(sliderID, value): Determines how much a certain slider is filled.
  • showScreen(screen): Shows the window with the given name.
  • getInput(monitorSide): Lets the user interact with everything and returns two variables: param and currentScreen; param is the param-attribute of the button that has been pressed and currentScreen is the window that you have to show if you make changes to the screen.
Additionally you have access to following tables: (look at the other instructions for more details)
  • userInputs
  • selectedItems

AddOns (1.2+)
SpoilerTo use the AddOn, all you have to do is place it in the same directory as the program. You can start the editor and the AddOn-objects get displayed in the object-list.

If you want to create a new AddOn then you can use this template: http://pastebin.com/94gAtudt
Here's an example. Unfortunately it's broken It SHOULD work now: http://pastebin.com/8KBu57Kp

How to make an AddOn
1) Define your objects
If you looked at the example then you should have seen the object-definition right at the beginning of the file. Basically you can put it wherever you want but I still recommend putting it at the top of your file.
Add an object by writing <object>. On the next lines you should add the parameters objectID and objectType (everything needs to be on a separate line!) by entering something like this:

objects = [[
  <objects>
	<object>
	  objectID=testID
	  objectType=Button
	</object>
  </objects>
]]

Depending on the objectType you will need some extra-attributes:

Button
  • defaultWidth (optional, default: 15)
  • defaultHeight (optional, default: 3)
  • text
Variable
  • none, just don't forget to set the objectID
Input
  • message
List
  • elements (separate each element with a ";". The example "Hi;there!;How are you?;I'm fine." should be valid.
  • isMultiselect
Custom
  • canScale
  • canClick
  • defaultWidth (only if canScale or canClick is set to true)
  • defaultHeight (only if canScale or canClick is set to true)
2) Handle events
Before I start, you need to know that there is a useful table called systemInfo which the AddOn will always get when it gets called.
The systemInfo contains the following fields by default (some of them can be empty depending on the reason why the AddOn gets called):
  • x: The x-coordinate of the object.
  • y: The y-coordinate of the object.
  • width: The width of the object (Empty if neither clickable nor scaleable).
  • height: The height of the object (Empty if neither clickable nor scaleable).
  • maxX: The horizontal size of the monitor.
  • maxY: The vertical size of the monitor.
  • selectedItems: The selected elements of all lists (more information in the editor-tutorial).
  • userInputs: The values of all input-objects.
The main program can send two different kinds of events: Show and Click along with the parameters "objectID" and the systemInfo
If you use my template then one of the two methods should be called automatically.

Show will be called when you need to display a variable or a custom object. All neccessary informations (like x and y coords) will be in the systemInfo.

Click will be called when a button or a custom object with enabled canClick-attribute gets clicked.

3) Save your new AddOn
The file-name has to end with ".add"
Yep, thats it.

Editor (1.1+)
SpoilerThere are 3 steps: Design, Attributes, Coding (not the best step-names but meh…)
Note: You don't necessarily need to finish one step to continue with the next one. I'll just explain it like that to make it easier to understand.
Note 2: The "Design" and "Attribute" part are very easy to understand. However, I recommend you to look at the "Coding"-part since you need to follow some rules to make your program work.

Step 0: Start the program
Start it using the parameter "edit". If the name of your program is "Graffiti" then you should enter "Graffiti edit".
You should now see something like this:
– image removed to make space for the ones in the newer instructions –

Step 1: Design
This is probably the easiest part. Add objects to your main-screen, make a new one, add objects to the new one and so on.

First you need to select the "Design"-mode (just touch the text). It should now be orange and you can touch the "edit screens"-button.
Now you will see a list of all your screens as well as the Buttons "New", "Edit" and "Delete". I guess each function is self-explanatory.
The mainScreen-screen will be shown as soon as you start the program normally, therefore i would recommend you to select it and press the "edit"-button (if you haven't changed it yet).

To create an object you have to right-click the position where it should be. A list should pop up:
– image removed to make space for the ones in the newer instructions –
Touch the object that you want to add and it should be displayed. You can do that as often as you want as long as there is still space on your screen. Simple, right?

Delete: If you created an object which you don't like then you can press the "options"-button in the lower right corner, select "Delete" and press the "last screen" button. This will change your mode to delete-mode and any object that you touch will be removed.

Editing your objects is almost as easy as creating or deleting them. When you touch one in "Design" mode then you will see one or two pixels with another color (depends on the object). The one on the left is for moving your object. The one on the right is for scaling (works only with buttons and sliders). Simply click one of them (it should turn white) and press the pixel for the new position/scale.

1.3 feature: horizontalAlignment and verticalAlignment
Each attribute can either be left/top, right/bottom or stretch. Press the green/red pixel at the end of the gray lines of an object to change one of the attributes.
Left and top won't change the design when the screen size changes. Right and bottom will move the objects and "stretch" won't move the objects but it changes its scale.
Example for the horizontalAlignment attribute: Left pixel red and right pixel green: horizontalAlignment is "right". Both are green: "stretch". Otherwise it's "left".

Step 2: Attributes
You don't know what I'm talking about? Well, every object that you've added to your window has certain attributes (look at my v1.0 instructions to see them all). The button has the default-attributes "objType", "x" and "y" as well as some special ones: "width", "height", "text", "funcType" and "param". To edit an attribute which can't be changed in the "Design"-mode, you have to press the "options"-button, select "Attributes" and press the "last screen" button.

– image removed to make space for the ones in the newer instructions –

If you want to change an attribute all you have to do is click it. Depending of the attribute it will either automatically change to another value (e.g. "direction"-attribute of the slider from "right" to "up") or a yellow pixel will appear. When this is the case then you have to go to the computer and enter a value for the attribute.

Example:
If the attribute is "isMultiselect" (a list-attribute) then you can touch it and it will switch between true and false.
If the attribute is "param" (a button-attribute) then you have to enter the name of your function or screen (depending on the "funcType"-attribute)
Important: Don't change the "elements"-attribute of the list-object until you have read the instructions. It's a bit more complicated than I want it to be but I can't change it for now.

Step 3: Coding

If you've done everything right in the previous 2 steps then this shouldn't be hard for you.
Basically you can do these 4 things:
  • Add values for your variables.
  • Add values for your sliders.
  • Create arrays for your lists.
  • Create functions for your buttons.
If you have read the v1.0 instructions then most of that shouldn't be a problem. Otherwise I'll give you an overview of what you have to do to make your code work:
When the screen finished loading then two functions get called: "getVariableValue(varID)" and "getSliderValue(sliderID)".

You can return a certain value depending on the object ID. This value will then get displayed on the screen. Note that the variable-value can be anything while the slider-value has to be a value between 0 (empty) and 100 (full).

Creating the function for a button is almost as easy as creating a normal one. Instead of "function myFunction() CODE end" you have to write "function userFunctions.myFunction() CODE end"

It's almost similar with the list. Instead of "myList = { }" you have to write "userLists.myList = { string1, string2 }".

Example:


function getVariableValue(variable)
  if (variable == nil or variable.objType ~= "Variable") then
	return
  end

  variableID = variable.varID
  if (variableID == "testVariable") then
	return "Variable";
  elseif (variableID == "Time") then
	return textutils.formatTime(os.time(), true)
  end

  return ""
end

local randomValue = 50

function getSliderValue(slider)
  if (slider == nil or slider.objType ~= "Slider") then
	return
  end

  sliderID = slider.sliderID

  if (sliderID == "testSlider") then
	return 87;
  elseif (sliderID == "randomSlider") then
	return randomValue
  end
end

function userFunctions.setRandomValue()
  randomValue = math.random(100)
end

userLists.testList = { "hi", "there" }

No editor (1.0)
(Not as simple as using the editor but if you insist on using the older version…)
Spoiler1) Create your screen(s)
Note: I don't know why I used the name "screen" instead of "window" in the code. I just did.
There is an array called "screens" inside the program (should be at line 91).
There are already two example-screens which should show you how to use it.
SpoilerThe screen array:

screens = {
  mainScreen = {

  };
}

And here's the example:

screens = {
  mainScreen = {

  };

  subScreen = {
	parentScreen="mainScreen";

  };

  superSubScreen = {
	parentScreen="subScreen"
  }
}

You just need to write "arrayName = { };" inside the screens-array. All your objects are going to go into this array.
If you are going to nest your screens (in this case: link from one screen to another) you can write "parentScreen=screenName;" inside your array. That way you will get redirected to the parentScreen when the "back"-button gets pressed. Otherwise you will always get back to the mainScreen-screen.
You always need the mainScreen! It's the one that gets shown when the program starts!


2) Add objects to your screen(s)
It get's a bit more complicated here but it's not hard to understand.

Each object has at least those 3 attributes:
Object type (objType)
x-coordinate (x)
y-coordinate (y)

There are the following 5 object types and their extra attributes:

Button
  • width
  • height
  • text
  • funcType
  • param
The function type (funcType) can either be "function" or "switch"
"switch" changes the screen to the one that you've selected with the param-attribute.
The param-attribute has to be a string.

"function" calls the function that you've specified in the param-attribute.
The param has to be the actual function, not a string.
Here's an example:
Spoiler

screens = {
  mainScreen = {
	{ objType="Button", x=2, y=4, width=25, height=3, text="call function!", funcType="function", param=doSomething };
	{ objType="Button", x=2, y=9, width=25, height=3, text="switch to subScreen", funcType="switch", param="subScreen" };
  };

  subScreen = {
	parentScreen="mainScreen";
	
  };
}

function doSomething()
  randomValue = 5
end

Text
  • text: The text that you want to show. Nothing else.
Variable
  • varID
The variable ID (varID) itself doesn't do anything. When the screen finishes loading, a function "getVariableValue" gets called. Here you can set a certain value which will get displayed. You can find the function after line 130 (it depends on the size of the screens-array).

Example:
Spoiler

function getVariableValue(variable)
  if (variable == nil or variable.objType ~= "Variable") then
	return
  end

  variableID = variable.varID
  if (variableID == "testVariable") then
	return 42;
  elseif (variableID == "Time") then
	return textutils.formatTime(os.time(), true)
  end

  return ""
end


Slider
  • length
  • direction: either "left", "up", "right" or "down"
  • sliderID
The direction-attribute is optional and will be "right" by default.
sliderID is like varID of the variable-object. The only difference is the name and the fact that the function "getSliderValue" gets called.
In the getSliderValue-function you have to return how much the slider is full in percent (a value between 0 and 100).

Example:
Spoiler

function getSliderValue(slider)
  if (slider == nil or slider.objType ~= "Slider") then
	return
  end

  sliderID = slider.sliderID

  if (sliderID == "testSlider") then
	return 87;
  elseif (sliderID == "randomSlider") then
	return randomValue
  end
end

Input
  • inputID
  • message
  • isPassword
The input-object is probably the best and at the same time the worst object that I've implemented.
Why is it the best?
It actually works. That makes me happy

Why is it the worst?
It's not user friendly.
It only supports lower case letters and numbers. That makes me sad.

I know, I know… you will probably say something like "Encreedem! Why can I only use lower-case letters and numbers!? If i use a password with 4 digits the number of possible combinations would get reduced from 2,1267647932558653966460912964486e+37 to only 4722366482869645213696!!!!1! How can you do this!?"

What? You didn't calculate the number of possible combinations before? Well, now you know it.
The reason is that it's currently not possible to determine if the user holds down the Shift-key. I could probably find a way around it but it will need some time.

Whatever… let's get back to the attribute-explanations:
As soon as the user touches the input-object, it gets yellow and he can go to the computer and enter something. The result will be saved in the "userInputs"-array with the inputID as the key.

"message" is the text that will be displayed before the user can enter something.
I don't know if this attribute is optional. I'ts up to you to find it out. (To make it simpler: if "print(nil)" throws an error then not including "message" will do the same).

isPassword is the attribute that makes the object non-user friendly. If it's set to true it will display a "*" instead of the actual letter or number (on the computer as well as on the monitor). The value inside the userInputs-array will still be the actual input of the user.
This attribute is optional and will be "false" by default.

Example:
Spoiler

screens = {
  mainScreen = {
	{ objType="Input", x=2, y=2, inputID="randomInput", message="Please enter something.", isPassword=false }
  };
}

function doSomething
  userInput = userInputs[randomInput]
end
Edited on 01 September 2014 - 06:56 PM
Zudo #2
Posted 07 July 2013 - 04:13 AM
How do you input text on a monitor?
Encreedem #3
Posted 07 July 2013 - 06:46 AM
How do you input text on a monitor?

You touch the input-object, go to the computer, write something and press enter. The result gets displayed on the monitor.
Zudo #4
Posted 08 July 2013 - 04:07 PM
How do you input text on a monitor?

You touch the input-object, go to the computer, write something and press enter. The result gets displayed on the monitor.

Ok, now what we need is wireless keyboards! :)/>
Encreedem #5
Posted 09 July 2013 - 12:53 PM

Ok, now what we need is wireless keyboards! :)/>

Indeed! :lol:/>
I guess all you need are about 40 pressure plates, signs, lots of redstone and a guy who would stand on the Alt-, Ctrl- or Shift-"Key" for you.
Encreedem #6
Posted 12 July 2013 - 03:51 PM
Alright guys. I realized that making a program which helps you to create a GUI is nothing great since there are already lots of them in this forum.
However, I haven't seen any programs with a touchscreen-supporting editor so I decided to make my program a bit more unique by adding one.
Zudo #7
Posted 13 July 2013 - 01:30 AM
Keep working on it! Don't give up because it's already been done!
lesander #8
Posted 13 July 2013 - 11:58 AM
Wouldn't a qwerty keyboard be easier to use?
Hoppip #9
Posted 14 July 2013 - 02:26 AM
This is really nice, very easy to use and I learned a lot of Lua from this. Did you move the screens code to "screens.sav"? I can't find it anywhere in the code!
Encreedem #10
Posted 14 July 2013 - 08:01 AM
Keep working on it! Don't give up because it's already been done!

I don't know what made you think that I would give up on this (I guess my last post sounds a bit depressive) but I can assure you that I'll keep working on this program.


Wouldn't a qwerty keyboard be easier to use?

Yeah, I forgot that this could cause problems since I'm reading the keys instead of the characters. I found an easy solution for this problem and it will be in the next update.


This is really nice, very easy to use and I learned a lot of Lua from this. Did you move the screens code to "screens.sav"? I can't find it anywhere in the code!

Thanks! It's great to hear that it actually helps other people. And yes, you can't use the old way of creating the "screens" anymore. The editor saves everything inside the "screens.sav" file.
Mandrake Fernflower #11
Posted 14 July 2013 - 07:23 PM
It looks like a white board or graffiti program. I would just call it Graffiti
Encreedem #12
Posted 15 July 2013 - 02:55 AM
It looks like a white board or graffiti program. I would just call it Graffiti

Sounds interesting. I'll think about it. Thanks for the suggestion!
Encreedem #13
Posted 17 July 2013 - 04:45 AM
The next update (1.2) is almost out and I woud be happy to hear some feedback about a new feature: AddOns
Background: My program is great if you want to use it like it is but it has almost no compatibility with other useful programs.
The idea: An AddOn file would contain objects. The user would be able to add the objects to the screen (using the normal editor) and use it like any other object. Basically that means that you can create a program with a GUI without having to make the GUI!
Example: You declare a button in your AddOn-file, the user adds it to the screen and when he touches it then my program will tell the AddOn that the button has been pressed.
Here's an actual example before I the post gets too long: http://pastebin.com/8KBu57Kp

Edit: BTW guys, I've added a video turorial for the editor. The link is in the original post.
pazzesco #14
Posted 20 July 2013 - 01:32 PM
A GUI can be half the battle depending on the application, and this looks pretty neat. Keep up the good work!
Encreedem #15
Posted 20 July 2013 - 06:01 PM
Thanks man! (or woman, just in case)
I'll keep working on this as long as other people use it.
Encreedem #16
Posted 23 July 2013 - 05:47 AM
Graffiti v1.3 is out!
I've added an API and changed the editor a little bit. It's easier to adapt the objects to changes of the screen size now.
Not sure why I added AddOn and API support but I've created a section in the OP where the differences between those 2 features are explained.
Links and details are in the changelog.

Edit: Yay! 1000 views! :lol:/>
Mitchfizz05 #17
Posted 25 July 2013 - 05:58 PM
This looks truly amazing!
1+

One quick question though: Does it have to be a GUI for a monitor? Like, without editing the API?
Shnupbups #18
Posted 25 July 2013 - 06:10 PM
I love this idea and it looks really cool! If there's a computer version with compatibility for left and right clicking, I'll definitely use this!
Encreedem #19
Posted 26 July 2013 - 03:52 AM
Yay! Positive feedback :lol:/>
I've already mentioned in the OP that I didn't even know that advanced computers have touchscreen-support (actually, when I started with this program I had no idea what they were good for) and event handling caused lots of confusion when I experimented with the possible features.
I learned a lot about Lua while writing this program and I think that it wouldn't even be too hard to implement computer-support in the 1.4 update. Although you shouldn't expect support for left and right mouse click handling in the near future.
NeptunasLT #20
Posted 27 July 2013 - 03:22 PM
Not bad, i kinda Like it and its very helpful and you dont need LUA Skills. :)/>
Encreedem #21
Posted 28 July 2013 - 07:03 AM
This looks truly amazing!
1+

One quick question though: Does it have to be a GUI for a monitor? Like, without editing the API?
I love this idea and it looks really cool! If there's a computer version with compatibility for left and right clicking, I'll definitely use this!

Wow, I didn't realize how useful terminal-support is before I made the 1.4 update (made the text bold so that everyone can see that this post is about the 1.4 update). Thanks for the suggestions again!
Now the program will automatically look for a monitor and display it on the computer if it doesn't find one.
Right click support is implemented for the editor. When you right click on an object then you can change its attributes or delete it without having to change the edit-mode.
Encreedem #22
Posted 01 August 2013 - 05:40 PM
Can you believe that I've been looking for a bug for about 5 hours just to realize that there were two typos?
Whatever, Graffiti v1.5 is here and it comes with a major change:
Removed the GraffitiAPI file and put it into the main-program (Graffiti) because there was way too much redundancy.

Also, pazzesco allowed me to include the API into his program GHOSTY. You can find the necessary save-file and the program in GitHub.
NOTE: This program is neither a replacement nor an update of "GHOSTY". It is completely independent of the original.

Edit: There's a high possibility that I've messed my program up by combining Graffiti with GraffitiAPI. It would be really awesome if anyone who uses this program posts any bugs that he/she finds. Don't worry, I won't bite.
UMayBleed #23
Posted 01 August 2013 - 05:46 PM
Great work!
lifewcody #24
Posted 03 August 2013 - 11:39 AM
Thank you for the easyness
Encreedem #25
Posted 04 August 2013 - 02:11 PM
Thank you for the easyness

I'm not sure whether you mean Graffiti or Ghosty but you're welcome either way. I always try to make the usage of my programs as simple as possible and it's great to hear that this is the case.
Encreedem #26
Posted 07 August 2013 - 06:03 PM
I haven't really worked on this program since the last update. That is because of two reasons: I'm running out of ideas and I'm getting tired of all those bugs (You know what I'm talking about if you have any experience in coding.). I'm soon going to make a decision that is important to me:
1. I will either keep working on this program just as usual OR
2. I will add some finishing touches, fix some bugs that should have been fixed a long time ago and start working on another (possibly bigger) project. I won't say what it is right now because I have no idea whether it will work out or not.

I almost gave up on asking for opinions but I guess I'll try again: Does ANYONE want to see more features for Graffiti or do you like it the way it is and it doesn't really matter if I add more features?
I really don't want to beg for posts. I'm just asking whether I should stop working on this program or not.

… and sorry if I sound depressive again. Believe me, I'm not. For some reason I think that my thread is quieter than any other one, even though I guess that about 24 replies in one month (even if most of them are from me) are not bad. :D/>
BeforeU #27
Posted 10 August 2013 - 11:41 AM
Its look nice . Clever idea
Dave-ee Jones #28
Posted 11 August 2013 - 03:08 AM
Really nice program…very useful.
When you say "easily customizable" it really isn't THAT easy. I didn't realise you had to completely modify the whole program, I thought it was kind of like an API type thing. You should convert it to that.
Encreedem #29
Posted 11 August 2013 - 04:16 PM
Really nice program…very useful.
When you say "easily customizable" it really isn't THAT easy. I didn't realise you had to completely modify the whole program, I thought it was kind of like an API type thing. You should convert it to that.

I have to ask you to be more specific because I don't know what your problem is. With "easily customizable" I mean that you can create, modify and delete any object with only a few clicks. I also created the API since version 1.3 and I even included it into Graffiti since version 1.5.
That means:
  • If you want to run the program then you have to enter "Graffiti"
  • and if you want to load the program as an API then you have to write
os.loadAPI("Graffiti")
in your code.

You can find the instructions on how to use the API in the original post. You can also see a usage example on GitHub where I implemented Graffiti into Ghosty at line 280.

I hope that I all issues are resolved now, otherwise you should tell me what part of the program you had to change to make it work. After that I can hopefully release a version which has greater compatibility with other programs to allow you to use Graffiti without having to change the code.

Edit: Quote and example added.

Edit 2: Issue resolved.
Edited on 14 August 2013 - 05:58 AM
TcG #30
Posted 02 September 2013 - 05:53 AM
When I was browsing in the forum I found this, and I think it's awesome!
I hope you will implement the features you've planned and fix some bugs (The program breaks if you try modifying Text Inputs).
Encreedem #31
Posted 04 September 2013 - 06:32 AM
I'm glad to hear that you like it. Don't worry, I haven't really stopped working on this program, I'm just cleaning it up, making changes that I should have made a long time ago and I'm also implementing some useful features. Most of it is already done and I guess that version 1.6 should be out in less than a week (if nothing goes wrong…).
Also, thanks for the bug report. I think I've already fixed it and it will be in the 1.6 update too.
Mograph #32
Posted 11 September 2013 - 05:02 AM
Really like this program, its great for building layouts for a touch-screen GUI got it up and running. One thing I cant figure out is how to ensure that a button toggles to green once touched.

If my code is like this. I click a button and it turns off bundled cable.

function userFunctions.powerOff()
	currentColors = rs.getBundledOutput("left")
		if allActive == false then
				rs.setBundledOutput("left", colors.combine(currentColors,rsColor,steamColor,lavaColor,fuelColor,farmColor))
                allActive = true
		else
				rs.setBundledOutput("left", 0)
                allActive = false
		end
end

But I cannot get the button I click to remain green.

Any ideas?
Encreedem #33
Posted 11 September 2013 - 10:18 AM
snip

Toggling buttons is currently not possible because of the way how the objects get drawn. Right now the "solution" I'm using is to have two buttons which change the value of a variable-object.
I will try to include that feature as soon as I released the 1.6 update (which is hopefully very soon).
Mograph #34
Posted 11 September 2013 - 12:19 PM
Thanks for the reply. I did notice if I add in a "sleep(2)" in my functon before the "end" that the button will turn green for the 2 seconds before the function finishes, No idea if this is useful for you to know or not.

Having buttons that toggle is a really useful thing,

Happy to help you test things as this program is a really good one.
Encreedem #35
Posted 12 September 2013 - 05:15 PM
Thanks for the reply. I did notice if I add in a "sleep(2)" in my functon before the "end" that the button will turn green for the 2 seconds before the function finishes, No idea if this is useful for you to know or not.

Having buttons that toggle is a really useful thing,

Happy to help you test things as this program is a really good one.

I already know it but it's still nice that you are trying to help. The problem with the buttons is that they were not meant to be toggled when I first wrote the program. The idea was that a button stays green as long as something was running to show the user that something is happening in the background after he pressed a button.

Version 1.6 has a completely different way of drawing buttons and it should allow me to easily make buttons that can be toggled. However, I already fixed very many bugs but there are still some left that are driving me insane…

Please be patient. Version 1.6 will come, it will be awesome and after that implementing this feature won't take long. :D/>
Encreedem #36
Posted 16 September 2013 - 05:16 AM
It's finally here! The update that at least one person (me) was waiting for: Graffiti v1.6!
Before I try to explain why it took basically forever I'm just going through the changelog:

Added container objects
This change messed my whole code up. Implementing containers meant that I had to change the way objects get displayed. And while I was on it I also made a big step into OOP. "What could possibly could go wrong?" was the wrong question.

Added color themes.
I thought this could be useful. You can find the settings at line 32. Changing and customizing it should be self explanatory.

Renamed almost everything from "screen" to "window".
Renamed most "show" functions to "draw".
I should have done that a long time ago. I was a CC noob when I started writing this program, therefore most names were inaccurate or simply bad.

Renamed the "Slider" object to "ProgressBar".
Thanks to the widget API of thomasbouge I realized the Slider-object isn't really a slider.

Completely changed event handling and displaying of the objects.
Instead of the getInput() function you can now use Graffiti.pullEvent(). Right now it returns the event type, the object ID and, depending on the event type, additional parameters.

Removed AddOn support.
AddOns simply caused lots of trouble because Graffiti can't use the shell when it gets used as an API. Also, I don't think that anybody used it. Tell me if you want that feature back.

Bugfix: Elements of List-objects couldn't be changed. (This time it does work!)
Yep, that's it.


Bugs
The ProgressBar-object gets messed up when you set the direction to "up".


More
The API usage changed a bit (as described above). I will write some instructions later.

Edit: Forgot to mention why I added containers:
I already like them really much but I'm actually planning to include ScrollBars and tabs for containers. Now that I've done most of the hard work these features should theoretically be easy to implement.
Also, I'm already working on the toggle feature for buttons.

Edit 2:
I still don't know much about GitHub but I guess that you can add any bugs that you find to the "issues" page.

Edit 3:
Why can't I change the title correctly? I want to write "The first IDE for GUIs!", not "The First Ide For Guis!"
44shades44 #37
Posted 03 October 2013 - 06:58 AM
HOLY MOTHER OF MUFFINS I LOVE THIS PROGRAM!!!!
Dude… This is epicness in a .lua file…

I understand that you are a busy man, but I was messing around with the OpenPeripherals Terminal Glasses about 2 minutes before I found this… And i couldn't help but wonder the possibilities of combining the two! A fully customizable HUD… (I wouldn't imagine this would be a big job considering your skills, I'm not very good at LUA and I had a little go to no avail.) But that'd be a great feature.

Once again, thankyou for the epic program. Glad you exist :D/>/>

So After Two hours or so of messing around with this, i've discovered 1 small bug.
When resizing panels, you can make them 1 thick pixel vertically (ike this: ——-) but not horizontally,
like this:
||
||
||
Still Loving the program.

Edit: Better english

On another note, the .sav file is quite poorly set out. Do you reckon that you could make it in this kind of format:
Spoiler

{
 ["mainWindow"]={
  ["showRefreshButton"]=false,
  ["objType"]="Window",
  ["parent"]="Crafting",
  ["children"]={
   [1]={
	["y"]=2,
	["objID"]="MainPanel",
	["path"]={
	 [1]=1,
	},
	["x"]=2,
	["canScale"]=true,
	["children"]={
	}
	["width"]=14,
	["isContainer"]=true,
	["objType"]="Panel",
	["absoluteX"]=64,
	["absoluteY"]=8,
	["height"]=5,
   }
  }
 }
}
Just a Thought, I'm converting my .sav file to this format because sometimes it's quicker to make a slight code change than to remove a variable or something and replace it with text and set all the text data in it using this method rather than clicking about with delete and attributes.

Edit: I Just realized that The coding to do this would probably be fairly intense… But I'll leave the comment here anyway.

Edit2: Sorry if the code looks whacky, the edit function is screwing me around.
44shades44 #38
Posted 04 October 2013 - 03:57 AM
Okay, I can kind of see why you didn't do that now, I'm nearly finished this now and it is 815 Lines.
Perhaps if rather than "Graffiti.sav", you made a folder "Graffiti saves" with one .sav file per window?
And perhaps a windows.sav for the window data (parents and refresh button) for each window.
This would increase the amount of stuff it stores on the computer, but eh.
Just another Idea.
Encreedem #39
Posted 04 October 2013 - 09:09 AM
Heh, didn't think that this program would get any more attention since I haven't done anything with it for about 2 weeks. I guess I'm too awesome. :P/>/>/>

I understand that you are a busy man, but I was messing around with the OpenPeripherals Terminal Glasses about 2 minutes before I found this… And i couldn't help but wonder the possibilities of combining the two! A fully customizable HUD… (I wouldn't imagine this would be a big job considering your skills, I'm not very good at LUA and I had a little go to no avail.) But that'd be a great feature.

I already considered doing this some time ago but I don't know much about the way the glasses work, therefore I'll just add it to the "Planned Features" list. Don't expect it too soon though. Graffiti is conservative and whenever I try to implement new features or change it, it gets upset and fills itself with lots of bugs… and there are still too many that need to be fixed. :(/>/>/>

Once again, thankyou for the epic program. Glad you exist :D/>/>/>

Erm… thanks, I guess?

Edit: Totally forgot the second comment.

Perhaps if rather than "Graffiti.sav", you made a folder "Graffiti saves" with one .sav file per window?
And perhaps a windows.sav for the window data (parents and refresh button) for each window.

Sorry, but I won't change that part because of 2 reasons:
1) The "save" and "load" functions are very simple methods that have always worked. I don't like changing working code.
2) I don't want anyone (including myself) to look at the Graffiti.sav file. Graffiti should be the only thing that interacts with it. Having to read and edit it has a chance of breaking it, which means that I just have to write an awesome and bug-free program so that you don't even need to look at the saves.

Don't get me wrong, I like the idea of changing the save-file so that it's easier to read but I'll just refer to point 1 again.

Aaaand the post is going to be even longer because I forgot to give you an answer to another question/suggestion:

So After Two hours or so of messing around with this, i've discovered 1 small bug.
When resizing panels, you can make them 1 thick pixel vertically (ike this: ——-) but not horizontally,
like this:
||
||
||
Still Loving the program.

"It's not a bug, it's a feature!"
This is intended so that you won't make an object 1x1 by accident and making it unscalable (referring to point 2 mentioned above). I guess that you tried to make a simple line. If this is the case then I can happily tell you that Line-objects are going to be in the next update. (Which is, as usual, going to need its time. Some "small changes" seem to cause more bugs than what I expected.)

I hope I didn't forget anything and all questions have been answered.

Edit 2: Finally added some instructions for 1.6.
44shades44 #40
Posted 05 October 2013 - 03:33 AM
Thanks for your fast reply. :D/>
Last night (I'm from Australia) I got really in depth with the .sav file using Notepad++.
I've fully ordered it into a readable structure, and I think I actually prefer to do it this way. So i'll just use replace to replace space with nothing and hope that works. The biggest advantage so far that I've discovered is better customization of windows. Using the program alone, one of the worst things was I didn't really know what I planned to do, so i set out my window (a todo list) on mainWindow… but then I wanted to add a links page with links to my other windows, so i scrapped the whole .sav file, and remade the todo list on a new Window called Crafting, and the links page on mainWindow. Then I wanted to add a log in page… but that would have to be mainWindow, editing the .sav made this very easy.
Merhaps my little lua skills could make a program that changes the .sav into a readable format (or vice versa) by adding a return before every [ or something.

Heh, didn't think that this program would get any more attention since I haven't done anything with it for about 2 weeks. I guess I'm too awesome.
To the former: Two weeks isn't very long in programming talk. To the latter: True.

I already considered doing this some time ago but I don't know much about the way the glasses work, therefore I'll just add it to the "Planned Features" list. Don't expect it too soon though.
I understand, It would almost be a separate program, use Graffiti on a Monitor then use a separate program to load up the .sav file and interpret the "$$" commands used to control the glasses. But yeah, that'd require a lot of experience with the glasses (or a tonne of trial and error and bugs).

Sorry, but I won't change that part because of 2 reasons:
1) The "save" and "load" functions are very simple methods that have always worked. I don't like changing working code.
2) I don't want anyone (including myself) to look at the Graffiti.sav file. Graffiti should be the only thing that interacts with it. Having to read and edit it has a chance of breaking it, which means that I just have to write an awesome and bug-free program so that you don't even need to look at the saves.
I understand the changing working code, If i knew much LUA, I'd be glad to help. As I said above, the .sav file is, in my opinion, very handy to have access to, and I don't know if you did it intentionally or not, but I find it very easy to understand when it is in my format but anyway, I understand.

"It's not a bug, it's a feature!"
Oh I get it lol.

I've made a bit of progress on the program thingy, and i've got some questions (I'm a pretty big LUA noob). But i'll ask you later all in one big batch.
Blade88 #41
Posted 05 October 2013 - 12:48 PM
i think it is a good program ;P ^^

i will test it on my server
Encreedem #42
Posted 10 October 2013 - 09:49 AM
The biggest advantage so far that I've discovered is better customization of windows. Using the program alone, one of the worst things was I didn't really know what I planned to do, so i set out my window (a todo list) on mainWindow… but then I wanted to add a links page with links to my other windows, so i scrapped the whole .sav file, and remade the todo list on a new Window called Crafting, and the links page on mainWindow. Then I wanted to add a log in page… but that would have to be mainWindow, editing the .sav made this very easy.

– snip snip snip –

I understand the changing working code, If i knew much LUA, I'd be glad to help. As I said above, the .sav file is, in my opinion, very handy to have access to, and I don't know if you did it intentionally or not, but I find it very easy to understand when it is in my format but anyway, I understand.

I was bored so I looked at your suggestion and implemented a feature which makes the save-file more beautiful and readable. Honestly, it was far easier than I thought it would be. As always the new features will be in the next update.

I've made a bit of progress on the program thingy, and i've got some questions (I'm a pretty big LUA noob). But i'll ask you later all in one big batch.

1) Sure, feel free to ask. I'd be glad if I can help.
2) Everybody says it. Now I can finally say it too: "It's Lua, not LUA!" :P/>
3) It doesn't matter whether you are a Lua noob or not. Practice makes perfect! I knew almost nothing about Lua when I started writing Screens (the old Graffiti). If you want to contribute to this program then feel free to send me your code and I will take a look at it.

I'm also thinking about your suggestion regarding making a save-file for every window. Considering the fact that I would like to make Graffiti like Visual Studio (just realized that I never mentioned that) it would actually make much sense.

Your suggestions and explanations how you are using this program help me very much in my attempt to make Graffiti more user-friendly. Thank you. :D/>
44shades44 #43
Posted 11 October 2013 - 03:15 AM
I was bored so I looked at your suggestion and implemented a feature which makes the save-file more beautiful and readable. Honestly, it was far easier than I thought it would be. As always the new features will be in the next update.

Woohoo :D/>

2) Everybody says it. Now I can finally say it too: "It's Lua, not LUA!" :P/>

Close enough :P/>

Your suggestions and explanations how you are using this program help me very much in my attempt to make Graffiti more user-friendly. Thank you.

Any time.

I'm gonna be busy with school for the next month (ish) but I'll continue finding bugs/improvements for you when I can ;D.
Encreedem #44
Posted 15 October 2013 - 04:15 PM
I wanted to implement some other features before I release it but I think that it is awesome enough already. Here's the 1.6.1 update: 9JUUk7Dp
Changelog:
- Added "toggle" function type for buttons.
- Added ScrollView container.
- Improved the save-file.
- Bugfixes

Known bugs:
- The progress bar can't be moved or scaled correctly when it faces up. (I still have no idea why this is happening. Still working on it…)

Notes:
Most of the testing went into the containers and the progress bar. There might still be bugs therefore I'm not giving up on asking you guys to report them.

Edit:
Hmmm… I just realized that the ScrollView wouldn't be easy to use because you can't scroll while editing it. I'll find a way around that.
Edited on 17 October 2013 - 12:31 PM
Encreedem #45
Posted 02 November 2013 - 02:07 PM
Here's one minor update (1.6.2) before version 1.7 comes out: igxw4tWP

Changelog:
Bugfix: The ScrollView wan't scrollable in edit mode.
It's not the most beautiful solution but you can scroll the ScrollView by clicking one of the arrows when its selected (which means that you have to click twice to move the scrollbar once).

Added "GraffitiData" folder which contains all data for Graffiti.
I think this is one of the most important changes. Graffiti automatically creates a folder called "GraffitiData" which currently stores all saves, logs, language files, and the settings file.
As far as I know Graffiti is not able to determine where it is (I mean its path) if it's getting used as an API. This is why the folder will be in the root directory "/" by default. You can, however, change the variable "root" to the path which should contain the "GraffitiData" folder.

Windows get saved separately now.
I thought that this could be useful if you wanted to use e.g. a login-window in other projects too. The disadvantage: The "Graffiti.sav" file doesn't work anymore. I'm planning to include an automatic conversion to newer versions so that this won't happen again.

Added Settings-file.
As I mentioned above Graffiti automatically creates a folder which contains all files. For now the settings file allows you to change the project (or save) that you are working on, the color theme (right now there's "Default" and "Windows CC"), whether the "GraffitiData" folder should be hidden or not and the language (more details below). Just ignore the "root" option. I didn't realize that having this option wouldn't make much sense because Graffiti wouldn't know where the settings file is if it doesn't know the root-path.

Added multi-language support.
This feature is not really finished because I still have to make the text of all buttons in the editor-window changeable. Right now I only included "en-US" but if you want to make your own language-pack then you can easily make a copy of the default language file ("GraffitiData/Language/Graffiti.en-US.lang"), change the text and adapt the language in the settings file.


Bugs :(/>
  • The List object can't be used correctly when it's inside a ScrollView container.
  • The Variable object seems to act strange inside containers (again! :angry:/> )
  • The ProgressBar object is still messed up when it's facing up.
  • The GraffitiData folder can't be hidden by changing the settings file. (You can do it manually if you want)
I really hope that those are all bugs but I'm pretty sure that there are more. There are always more…
I hope that you like this update and I'm sure that the 1.7 update…
  • will be awesome.
  • will take forever.
One last point before I finally stop writing: I'm already working on the next video. The last one is from version 1.1! That would finally be one less point of my "Things that I should have done a long time ago." list.
44shades44 #46
Posted 05 November 2013 - 12:35 AM
Added "GraffitiData" folder which contains all data for Graffiti.
I think this is one of the most important changes. Graffiti automatically creates a folder called "GraffitiData" which currently stores all saves, logs, language files, and the settings file.
As far as I know Graffiti is not able to determine where it is (I mean its path) if it's getting used as an API. This is why the folder will be in the root directory "/" by default. You can, however, change the variable "root" to the path which should contain the "GraffitiData" folder.
Weeeeeeeeeeeeeeeee :D/>

Sorry I haven't been on in a while, the server I was using this program on went down D:

Looking forward to 1.7
Encreedem #47
Posted 15 December 2013 - 04:19 PM
I really wanted to add some other features but I think it's finally time for the 1.7 update. This time I actually focused on adding code instead of changing the existing one (I added more than 1000 LOC).
As usual here's the detailed changelog:

Added CheckBox object.
Added RadioButton object.
Added Slider object.
Added DropDownList object.
Fun fact: It took me hours to change Graffiti so that I could easily add new objects. I never added those objects until now. ._.

Added converter.
The converter should automatically change existing files so that Graffiti won't crash after an update. It doesn't mean that a program will work perfectly after an update. The converter is still very small and I will try to make it better over time.

Added color theme "Fire".
Inspired by the color theme of GravityScore's LuaIDE. I think it looks much better than my "Default" theme but I'm open for suggestions if you think that it could look even better.

Added "load" attribute to some objects and removed the "getVariableValue" and "getProgressBarValue" functions.
By specifying the load-attribute you can simply add a function inside the "UserData" folder which returns the value that the object should have (I hope that makes sense, I'll write some instructions later).

Improved editor GUI.
Pretty much everything on the front-end looks better now.

Implemented "mouse_drag" support for objects and the editor.
You can now move and scale objects by clicking and dragging one of its edges instead of having to click every time. I have to improve the performance while an object is getting dragged but it works for now.

Changed the event handling of buttons: The user-function with the button's objID attribute (instead of the param attribute) as its name gets called now.
Instead of writing

function userFunctions.objectParam()
  ...
end

you have to write

function UserData.objectID()
  ...
end

Added a list editor and removed the old way of setting the elements of a List object.
Another change to the front-end of Graffiti which I really like.

Renamed "elements" attribute of the List object to "Items" (Just trying out whether it looks better that way).
I'm not sure whether this change is good or bad. I simply think the name "Item" makes more sense than "Element".

Renamed most tables to have an uppercase first letter.
I simply needed to do that.

Bugfix: Graffiti crashes after writing something into an Input-object.
Bugfix: The Input object isn't reading correctly when it was inside a container.

Bugfix: The move- and scale-pixels of a ProgressBar object have an incorrect position when it was facing up.
Yes, I finally fixed the bug that I couldn't fix for a very long time. I wrote "absolutey" instead of "absoluteY".
I don't hate this bug because of the mistake itself but because of the fact that the ProgressBar had no problems with the other 3 directions…

The program crashed when you try to load a non-existent window.
Another one of the features that should have been implemented a long time ago.

TL;DR: Lots of awesome changes.

As usual, I really hope that everyone who uses Graffiti likes this update and I hope you have fun making GUIs! :D/>


EDIT: I was a bit tired when I wrote this. Here is some detailed information:

As I mentioned above, all table names have been modified. Additionally I completely changed the ones I didn't like. One of those changes includes the "userFunctions" table which contains (as you might have guessed) all of your functions which get called after a button click. I renamed the table to "UserData" because I simply wanted to have only one table for all user-related functions and variables.

The table "userLists" has been modified in the following way: It's gone.
Instead of writing something into the userLists-table you can assign the items of a List object in two ways:
  • Use the list editor: By changing the Items-attribute of a List (or the new DropDownList object) you automatically get into the ListEditor-window.
  • Specify the "load" attribute: You can insert a function, which returns the value that an object should have, into the "UserData" table. The load attribute of the object should be the name of the new function.
Example:

-- Variable objects
function UserData.getTime()
  return os.getTime()
end

-- List or DropDownList objects
function UserData.getListItems()
  return { "Listitem 1", "Listitem 2", os.getTime() }
end


A note to the new converter:
Right now the only change the converter would make is changing the "children" attribute of all containers to "Children". That way I simply prevent Graffiti from crashing on startup. The update might still cause some less serious issues. One of them is that the windows don't get loaded properly (a.k.a. "at all").
For now I would simply recommend to recreate the windows if necessary.

Now to the last (and most annoying) point: The new video.
I'm sorry but I'm still preparing everything. I wanted to wait for 1.7 because this is the update which mostly changed the front-end of Graffiti's editor. Making a video before the update would simply make no sense in my opinion.

I hope I mentioned everything now, otherwise I'll make this post even longer! ^^
Edited on 16 December 2013 - 09:27 AM
Encreedem #48
Posted 16 January 2014 - 01:50 PM
Hey Guys! I remembered that I didn't write any instruction for version 1.7, so I somehow felt obligated to say that I've finally added some instructions which include pretty much everything you have to know to use Graffiti.
(Actually I got reminded by a guy called "Віталій Ноуль" on YouTube)
I hope that this helps everyone who's using Graffiti and that nobody minds the fact that I kinda keep necroing this thread on a regular basis. ^^
apoc123 #49
Posted 18 February 2014 - 12:52 AM
Awsome program pls keep the features and updates coming
surferpup #50
Posted 18 February 2014 - 03:03 PM
Very cool. Nice IDEa.
Encreedem #51
Posted 19 February 2014 - 02:07 AM
Hey, I just realized that this project apparently can't die and that it's still great to hear compliments! ^^
Of course I'm still working on Graffiti but I'm also a little bit busy at the moment, therefore the next update will take longer than the other ones. On the positive side: It will be awesome.

Also: YAY, over 50 posts! Don't you guys have anything better to do!? :D/>
FlashingLight #52
Posted 06 March 2014 - 03:04 PM
When i make a button, i click on it, click attributes and then whenever i click on a button id or button text it gives me an error: 3447:assertion failed.
Pls fix this if you can.. :)/>
TechMasterGeneral #53
Posted 06 March 2014 - 05:18 PM
I for some reason.. can't figure out how to get the gui's i made working… it won't even draw the screen correctly… maybe i'm calling the functions wrong…. if you can help that would be great.
Encreedem #54
Posted 07 March 2014 - 08:51 AM
When i make a button, i click on it, click attributes and then whenever i click on a button id or button text it gives me an error: 3447:assertion failed.
Pls fix this if you can.. :)/>
This bug has already been reported and I fixed it. I just forgot to upload a new version.
Here it is: YE2WetaX (It's only a version which prevents Graffiti of crashing because of this bug. Other features or bugfixes are not included.)

I for some reason.. can't figure out how to get the gui's i made working… it won't even draw the screen correctly… maybe i'm calling the functions wrong…. if you can help that would be great.
Of course I can help. I just need more info e.g.
  • Are you using the newest version?
  • Did you create the GUI using the graphical editor, your code or by editing the save-file?
  • Can you send me your code and window-files? I'll take a look at them if you want.
I planned to do this about 6 months ago but I'm making a video right now in which I will explain how to make your GUI and how to use it. Until then, if you haven't already done that, you can check out the instructions at the bottom of the original post.

I hope I could help everyone, otherwise feel free to post again or pm me.
TechMasterGeneral #55
Posted 07 March 2014 - 02:58 PM
When i make a button, i click on it, click attributes and then whenever i click on a button id or button text it gives me an error: 3447:assertion failed.
Pls fix this if you can.. :)/>
This bug has already been reported and I fixed it. I just forgot to upload a new version.
Here it is: YE2WetaX (It's only a version which prevents Graffiti of crashing because of this bug. Other features or bugfixes are not included.)

I for some reason.. can't figure out how to get the gui's i made working… it won't even draw the screen correctly… maybe i'm calling the functions wrong…. if you can help that would be great.
Of course I can help. I just need more info e.g.
  • Are you using the newest version?
  • Did you create the GUI using the graphical editor, your code or by editing the save-file?
  • Can you send me your code and window-files? I'll take a look at them if you want.
I planned to do this about 6 months ago but I'm making a video right now in which I will explain how to make your GUI and how to use it. Until then, if you haven't already done that, you can check out the instructions at the bottom of the original post.

I hope I could help everyone, otherwise feel free to post again or pm me.
I'm using 1.7 and i made the windows with the graphical editor…
here is the link to the window files… i just can't figure out how to get it to implement…
https://copy.com/zt0IKpBaS1DUzGtF