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

How to use Bedrock (Bedrock Documentation)

Started by oeed, 20 July 2014 - 01:21 AM
oeed #1
Posted 20 July 2014 - 03:21 AM
If you haven't already, read the post that briefly explains what Bedrock is. This is essentially the documentation.

Just a warning that this is a very, very, very large tutorial. In fact it's turned in to a 6,300 word, 17 paged monstrosity. It's designed to teach you Bedrock from the ground up and there are tons of things to cover. I highly recommend you do the first few spoilers. Some of the latter ones are things that not everyone needs to know or you might not need to know right now. Once you've got the basic idea you can simple pick the ones you want to read. I wouldn't skim read the first sections, they contain a lot of information about how Bedrock works, which is vital to understanding how to make your programs.

I haven't quite covered everything yet, I haven't be able to write some really advanced topics (custom objects, custom windows, scroll views, etc) due to time constraints. But I will add them soon. Some of the spoilers didn't want to do what they were supposed to either, so some formatting is a little off.

Getting StartedBefore you start coding there are a few things you should do.

First, make sure that HTTP is enabled on whatever emulator/version you are using. You can install it by copying and pasting the file off GitHub, but this method is far easier.

Second, ensure that you are happy with your editor. While using the built in edit will suffice, I recommend you use an external editor such as Sublime Text. If you must code in-game use a program such as LuaIDE. It will save you a lot of pain.

Finally, if you run in to any issues. Double check you haven't just made a silly mistake. Check in the common errors spoiler and see if your problem is one of those. If you are pretty sure it's a bit more complicated then create an Ask a Pro topic, do not PM me. I say this for two reasons, one, it'll probably consume a lot of my time if I'm getting 10 PMs a day asking for help, two, if it's publicly accessible others might be able to find the solution to their problem without having to ask anyone. Just a note on this: I will try to answer most of these, but if you see one and you think you know the answer please do reply, even if it might be wrong.

Let's get going!

The first thing you'll want to do it start a fresh computer and make a file for your program, I recommend calling it startup to save having to type it in a hundred times, but it doesn't matter.

You'll now want to enter this code:


local bedrockPath='/' if OneOS then OneOS.LoadAPI('/System/API/Bedrock.lua', false)elseif fs.exists(bedrockPath..'/Bedrock')then os.loadAPI(bedrockPath..'/Bedrock')else if http then print('Downloading Bedrock...')local h=http.get('http://pastebin.com/raw.php?i=0MgKNqpN')if h then local f=fs.open(bedrockPath..'/Bedrock','w')f.write(h.readAll())f.close()h.close()os.loadAPI(bedrockPath..'/Bedrock')else error('Failed to download Bedrock. Is your internet working?') end else error('This program needs to download Bedrock to work. Please enable HTTP.') end end if Bedrock then Bedrock.BasePath = bedrockPath Bedrock.ProgramPath = shell.getRunningProgram() end


local program = Bedrock:Initialise()

program:Run(function()
end)

Every time you make a Bedrock program all you essentially need to do is paste this code and run it. If it's not already installed it will download Bedrock, so you don't need to worry about that.

Let's look at next line. When you start your program you assign a variable, which can be called anything, but I personally call it ‘program', to the return value of Bedrock:Initialise() This loads all the APIs and makes a copy for your program. You only ever need to call this once at the top of your program. Lots of Bedrock functions use a colon ( : ) rather than a fullstop. The colon gives the function the thing that called it as well as the other arguments. See the below example for an example.


--high five the person
person:HighFive('left')

--this calls
function HighFive(receiver, hand)
--high five receiver with your left/right hand
end

If you run in to a problem when calling a function, especially if you get an ‘attempt to index' error, chances are you forgot to use a colon.

Now, the next line starts the program. In a normal program you have a while true do loop, that loop is within that function. As a result any code after program:Run will never be called, remember that! But what happens if you want to do something after the program starts, such as set a label's text? Well, fortunately there's quite a simple solution. Simple pass a function as an argument (which can either be written somewhere else and passed as a variable or as I have above. The code in the function will be called once all the buttons, etc. are on-screen and ready to be played with.

Note: You can not access any objects (buttons, labels, etc) before calling program:Run, so all code that changes them at startup must be called within the function given to program:Run

So, there you have it. A basic Bedrock program. If you try and run it chances are you'll get an error saying it can't find a view, but we'll get to that in the next section.

Views (Basics)Views, simply put, are like screens or windows. Each view has it's own objects on it. You can have as many or as little views as you like. However, you must have, at the very least, one. If you think about the iPhone's (and many other's) Settings app there are a number of views. The first view you see is the list of the various categories. When you click on the category button you are brought in to another view with a separate collection of objects on it. Once you get your head around what a view is, using them will be a lot easier.

Bedrock has a special file system that programs need to use. You now need to make a folder called ‘Views'. Note: For many ComputerCraft installations this is case sensitive, so make sure you use a capital V.

In the future I hope to make a program which allows you do make views using a drop and drop interface, similar to Xcode's Interface Builder. However, if you're reading this then chances are I haven't.

By default, if it exists, Bedrock will load a view called ‘main', so to keep things simple create a new file called ‘main.view' in the Views folder and open it. View files use the textutils.serialize format which is pretty much the same format as making a table in Lua, so there aren't any fancy things you need to do really.

If you've done everything correctly your computers files should look like this:


Here is a basic view file, copy this in for now.


{
  Children={
	{
	  X=2,
	  Y=2,
	  Name="HelloLabel",
	  Type="Label",
	  Text="Hello! I'm a Label!"
	},
	{
	  X=2,
	  Y=4,
	  Name="HelloButton",
	  Type="Button",
	  Text="Hello! I'm a Button!"
	}
  },
  BackgroundColour='white'
}

If you don't understand how Lua tables work I recommend you look for a quick explanation elsewhere, but they're fairly easy to pick up.

You'll see that the entire file is a table. In the one above there are two values of the main table, the BackgroundColour and the Children (or the objects in the view). The BackgroundColour is, obviously, the background colour of the view, not really any explanation needed. However, do note that the value (in this case, red) can either be the name of the colour (so basically just remove the ‘colours.' e.g. colours.lightBlue would be lightBlue, these are case sensitive) or the colours number (what you get when typing in colours.*** in the Lua prompt). When getting the BackgroundColour from an object (which we'll do later) it will always return the number, not a string if you gave it one.

Note: As I live in a place where ‘colour' is the correct spelling I use it over ‘color'. However, due to some metatable wizardry I've managed to make it so you can use either colour or color, so it's entirely up to you. Essentially, what it does is when ever you get or set a value with ‘Color' in the key name it will replace ‘Color' with ‘Colour'. So, technically there is only one value, but it acts as if there are two separate (yet always equal) values.

I'll also point out that when using Bedrock you can also use colours/colors.transparent, the label we have is transparent by default. This means that if we change the background colour of the view, or anything behind it, it will take that colour. The numerical value for transparent is 0.

Let's try running our program now. If you've done everything correctly you should now see something like this:

Buttons, Labels and Other BasicsAll objects (which, as stated before, are things on the screen such as buttons. I'll always call the objects.) have default values. For example, the default text colour for a button is light grey. So you don't have to set every value. If you want to know what properties a certain object has, the best way is to either visit the Wiki (if I've made it the link will be at the top of the post) or look at the object's code on GitHub, so for example, https://github.com/o...ects/Button.lua

Note: It's not a good idea to try and look at the code that is downloaded as the API. That file has all the files squished in to one and is minified. In other words, it's really hard to read. Just visit the GitHub repo, it'll save you a lot of pain. Do be aware, however, that the file that all objects are based off (their parent class) is actually in the API folder (Object.lua)

The type of an object is set using the Type value, to view the different types of objects you can use see the Objects folder in the GitHub repo.

Let's try changing the background and text colour of our button, pick and colours you like, just don't make them the same colour. See if you can figure it out on your own, but if you're having issues I've put the solution in the spoiler below.

SpoilerOpen main.view and add the following two lines under ‘Text="Hello! I'm a Button!"':

	  BackgroundColour='blue',
	  TextColour='white',

Make sure you have commas after each value.

Run your program and your button should have changed colours!

Extra

Note: I'll put extras in from time to time that have things that, while not vital, may be useful to know.

SpoilerIf you click a button you'll notice that by default it will change colour momentarily. These colours are ActiveBackgroundColour and ActiveTextColour.

You can also make a button toggle. Like an on/off switch. The on off buttons on the OneOS Settings program use this.

To do this add the follow to your button:

	 Toggle=false,
The boolean is the starting value. Every time someone clicks the button this will toggle.

To set the on/off colours simple set Background/TextColour for the off state and ActiveBackground/TextColour for the on state.

You'll notice that we didn't actually set the width or height of the label or button, yet it's sized correctly. In terms of height, 1 is the default for all views. But buttons and labels have a value called AutoWidth. What it does is when ever it's text changes it will automatically resize the object to the required size. However, if you want to choose the size of your button/label on your own you simple need to add the following values to your object.

	  Width=10,

Now, in the case of labels something interesting happens if you make the width smaller than it's content. So to see this, add Width = 10 to the label (you may want to set the button's Y value to 6 or higher).

If you did it correctly you should now see that the label's text wraps. Pretty cool, eh?


Another thing you can do with both buttons and labels is make the text align to the left, center or right. Now, with AutoWidth on you won't actually see it do anything, but lets look at another very thing you can do with Bedrock so we can.

In the past when you've tried to make something the width/height of the screen you've probably used term.getSize and set the width through that. It's clunky, needs code, and, too be frank, gets annoying. Fortunately Bedrock provides a snazzy way to do this, and if you've used CSS before you'll fell right at home.
In the case of making our Label the width of the screen we simple do:

	  Width="100%",
Remember that when doing this you need to put it as a string, not just a number.

Ta da! It's the width of the screen. You can also use this for the X & Y position, and naturally the Height, on any object that supports custom sizing (most do). This means that you can do something like:

  X="10%",
	  Width="80%",

This will give the text a 10% margin either side.

But what if, rather than a percentage margin you wanted a fixed width margin. Well, you can.

  X=5,
	  Width="100%,-10",
By simply adding a comma you can put a number, positive or negative, to alter the result. So, this would result in the label with a 5 pixel margin either side.

I use these frequently throughout OneOS, a good example of their use would be the First Setup program. https://github.com/o...p.program/Views


Now, back to our label centring. Once we've set the width to "100%" we can align the text using: (yes I know I'm using the American spelling)

	  Align="Center",

You can also use "Left" and "Right". By default Labels use Left and Buttons use Center. If you've done it correctly you should see something like this:

Getting and Setting Values With CodeIt's all good being able to set values statically using view files, but sometimes you just want to be able to get/set them using code.

Before we do this, take a quick look at your view file. You'll notice that each object actually has a name value. In the case of the Button it's Name="HelloButton". The name is used to get the button in code, rather than using a variable. You'll see it used very soon, it makes your code a lot easier read and write.

Note: In terms of naming, you can call your objects anything. You should always set a name though, even if you don't access it in code. You should try to make the name descriptive though, that way in your code you know what object your using. I personally have a few words describing it and then the object type, so for example, ComputerNameTextBox. But really, it's up to you.

Open up your main code file (the one the program:Run). At the moment the function given to program:Run should be empty. But lets add some code to it now. We want to set the label's text to something else.

program:Run(function()
program:GetObject('HelloLabel').Text = 'That was easy!'
end)
Remember to make sure the code is within (or called at some point by) the program:Run function, it won't work anywhere else.

Notice the use of the colon ( : ) here, were making the instance of Bedrock that is our program get the object with the name ‘HelloLabel'. If you were using variables to do this previously then this would basically be the same as your variable. You can now get and set values for your object. In this case we set the text, but you can set anything. Try changing the background colour. Hint: it's very similar to what we did earlier with the button.

If you're having trouble look in the spoiler.
Spoiler

program:Run(function()
program:GetObject('HelloLabel').Text = 'That was easy!'
program:GetObject('HelloLabel').BackgroundColour = colours.lightBlue
end)
Any value you change automatically tells Bedrock to redraw it, so you don't need to worry about touching drawing in Bedrock ever.

You may be asking yourself, "What if there are two or more objects with the same name?". Well, you should only do that in certain circumstances. The main one being when you have a number of almost identical objects that you want to be able to access all easily. For example, in the OneOS Settings program the colour buttons all have the same name. If I had separate names it'd require me to have special code for each button. However, if there is more than one object with the same name it will only return the first one it finds. It won't change all of them. For information about how to do this see the extra below.

Extra
SpoilerIt's not very complicated really. There's a function called GetObjects which returns a table of all the objects with that name. Here's an example.

for i, v in ipairs(program:GetObjects('HelloLabel')) do
--v is the same as program:GetObject('HelloLabel')
v.Text = 'That was easy!'
end

Getting a value is very easy too. In this case we're setting text of the label to the text of the button.


program:Run(function()
program:GetObject('HelloLabel').Text = program:GetObject('HelloButton').Text
end)

Object Events (Clicking Buttons)At the moment we have a button, but it's not actually doing anything when we click it yet.

Objects have a number of different events such as being clicked, loaded, having a key press, etc. However, most of them are handled internally so there are only two you'll have to deal with really. OnClick and OnChange. OnChange is only used by TextBoxes, so really there's only one you'll use often. There's also OnDrag and OnScroll, but you probably won't need to use them.

If you've used LÖVE2D before it's a fairly similar way of handling events.

First we get our button using GetObject, we then set OnClick to a function which will get fired each time it's clicked. If you want to can define this function else where and use the function name instead.


program:Run(function()
program:GetObject('HelloButton').OnClick = function(self, event, side, x, y)

end
end)
You'll notice that the function has a few different arguments given to it. The first, self, is the button. It basically saves you having to do GetObject again. It also means you can use the same function for multiple buttons and know what button to change. The remaining values are values from the event. As I'm sure you're familiar with, doing os.pullEvent() will return the event and a few values. In all functions in Bedrock that give something from a pullEvent the arrangement will be the same; self, event, arg1, etc. In our function side is which mouse button you used (1 for left, 2 for right, 3 for middle). The x and y values are the position where the mouse was clicked. However, these values are relative to the button. In other words, if you clicked the top left of your button, no matter where it is, x and y will both be 0. An example of this being used in OneOS is the bar at the top of the screen with the program names. Each program is just a single button. There is not ‘x' button, when the program is active I add a ‘x ‘ to the text. When you click on the button and the x value is 2 (where the ‘x') is it closes the program.

So, let's make our button do something. Within the function lets set our label's text to something. See if you can do it yourself. If you can't take a look in the spoiler below.

Spoiler

program:Run(function()
program:GetObject('HelloButton').OnClick = function(self, event, side, x, y)
program:GetObject('HelloLabel').Text = 'That was easy!'
end
end)

And that's about it for buttons. See how easy Bedrock is? Previously you would've had to spend ages writing your own APIs and messing around with hit detection then telling it and the label to draw, now you only need a single function for a button.

I previously mentioned that there are OnDrag and OnScroll events. I'm not going to write anything more about them really, but their use it very similar. If you want to use them just play around for a bit. I will point out that for scrolling there are dedicated Scroll, List and CollectionViews if your wanting for things like the Files icon scrolling, but they're a more advanced topic (there's probably a spoiler about them below).

Alert WindowsOne common task that you might want to do is make an alert windows. These are the windows that tell or ask your something, for example, a window like this:


Previously due to the reasonable difficulty of such a task you may have either been unable to do such a think or spent hours, even days, trying to get something like this working. Yet again, Bedrock makes this very easy. In this example we'll be opening it when the user clicks a button, but you could do it any time after program:Run has been called.


program:Run(function()
program:GetObject('HelloButton').OnClick = function(self, event, side, x, y)
program:DisplayAlertWindow(title, text, buttons, callback)
end
end)

These are the arguments you pass to the function, the title is show on the grey bar at the top of the window and the text is the message shown above the buttons. If the title is too long it will be cut off, so it should only be a few words. The text is wrapped automatically and should be more descriptive, but avoid making it too long, it will start to look a bit messy. The next argument, buttons is a table of the buttons shown. You can actually leave this blank, if you do a red close button will appear next to the title. The final argument is a function callback which passes the text of the button clicked. Here's an example:


program:Run(function()
program:GetObject('HelloButton').OnClick = function(self, event, side, x, y)
program:DisplayAlertWindow('Are you sure?', 'Are you sure you want to destroy everything?', {'Yes', 'No'}, function(value)
if value == 'Yes' then
--destroy everything
end
end)
end
end)

There is no set limit on the amount of buttons, but avoid having more than three. They might become cut off or make the window confusing.

Note: In all Bedrock views and windows the content is clipped, as it does in real OSs. This means that if, for example, your window is say 10 pixels wide but you have a button in the window that is 15 pixels wide you'll only be able to see 10 pixels of it.

So yea, that's about it. The buttons in the table are kinda backwards in terms of their order, but it's fairly straightforward.

Extra
SpoilerIf you try to click outside of a window the window will flash and nothing will happen. If you want to close the window for some reason in code (for example, a timeout) you can do something like this: (this uses a function which will be covered next)

program:Run(function()
program:GetObject('HelloButton').OnClick = function(self, event, side, x, y)
program:DisplayAlertWindow('Are you sure?', 'Are you sure you want to destroy everything?', {'Yes', 'No'}, function(value)
if value == 'Yes' then
--destroy everything
end
end)
--this code runs just after the window is shown, it does not wait for the window to close
program:StartTimer(function()
if program.Window then --program.Window is the current window, you should also use an if because the user might have closed the window
program.Window:Close()
end
end, 1) -- the 1 is the length of the time in seconds
end
end)

TimersIn the past if you've ever wanted a delay before something happens or want something to happen every X seconds you've either needed to use sleeps, which cause your entire interface to freeze, or a painful if statement. Bedrock puts an end to this with two (well kinda three) easy functions.

The first will run the function given after the time given. If you've used JavaScript before this is almost identical to the setTimeout function.

program:StartTimer(function()end, 1)
The first argument is the function to be run, you can either do it inline like above or give it the name of another function. The second argument is the time in seconds until it should be run. That's it!

The second function will do a function every X seconds. This is very similar to JavaScript's setInterval function.

program:StartRepeatingTimer(function()end, 1)
The arguments are the same as above, except this time it will happen again and again.

Extra
SpoilerThe repeating function can actually take the time value as a function, this is useful if you want to modify the interval at some point. Simple give it a function that returns a number. Do note that the new interval will only take effect once the timer starts again.

Custom Event Handling
SpoilerSome times you need to do something when an event, such as the peripheral attaching event, happens.

There is a simple function for this. This works by adding a function to a list of functions to be called when a certain event is fired. This means that you can register the same event more than once, although I don't really know why you would, but it does mean you can get raw key and click events that haven't been tampered with.

program:RegisterEvent('peripheral', function(self, event, side)end)
You can actually do this before program:Run as long as it's after Bedrock:Initialise.

As mentioned before, most Bedrock event functions also include self. In this case self is the same as ‘program'. For more information about these see the Object Events section.

An example of this being used is in Files, when you attach/disconnect a peripheral it will refresh the peripherals list.

Add and Removing Objects (Using Code)
SpoilerBy this stage you're able to have objects in your program using view files, but what if you wanted to add or remove an object part way through your program?

There are two easy functions to do such things.

To remove you simple use the code below.

program:RemoveObject(‘HelloButton')
The function takes one argument, the name of the button.

Extra
SpoilerIf you have multiple objects with the same name there is a function which will remove every object with that name.

program:RemoveObjects(‘HelloButton')
It's virtually identical but has an 's' on the end.

Now, adding objects is a little more complicated.

program:AddObject({
Y=8,
X=2,
Name="GoodbyeButton",
Type="Button",
Text="Goodbye"
})
As you see, there is only one argument, a table. You could copy and paste the table from a view and they would work in either. You can basically do anything you would do in a view file. Remember to set a name! If you don't it will default to the type, so if I left out the name in the example above the name would be ‘Button'

Menus
SpoilerI'm sure you've wanted to add a menu to your program at some point. Unfortunately they can be a really b*tch to get working and looking decent. Bedrock allows you to easily display a menu with, yet again, a single function. They behave identical to the OneOS menus (well, OneOS uses Bedrock menus, that's why), once open if you click anywhere else it will close the menu but not trigger anything else.

Unfortunately, menus are a little harder to do than most other things, although it's still exponentially easier than most doing it on your own.

There are two main ways to load what shows on the menu I recommend you use the first method as it's cleaner and uses less code, but pick whatever suits you.

First Way
This method involves making another view file, so create a new file in your Views folder. I call my menu views something like ‘optionsmenu' but it doesn't really matter, just make it clear. Also make sure the view file has the .view extension.

The easiest way to show a menu is to attach it to a button click, as I have below.


program:GetObject('HelloButton').OnClick = function(self, event, side, x, y)
if self:ToggleMenu('optionsmenu', x, y) then

end
end

You'll notice that the button is actually calling ToggleMenu. What happens is, when you click the button if you haven't already got another menu open it will open it, otherwise it will close the old one. You'll also notice that there is an if statement. The function returns true if the menu was opened, which means that your menu buttons are showing, but at this stage won't do anything. There are also x and y coordinates given, while not needed the menu will appear where you clicked, as apposed to just next to the button.

First though lets create the file which says what the menu has on it. If you haven't already, create a file called ‘optionsmenu.view' (or whatever you want to call it) in your Views folder (place it next to main.view).

You're then going to want to put this text in to it:

{
  Type="Menu",
  Children={
	{
	  Name="ViewModeMenuItem",
	  Type="Button",
	  Text="List View"
	},
	{
	  Name="HiddenFilesMenuItem",
	  Type="Button",
	  Text="Show Hidden"
	}
  }
}
This format should by now look fairly familiar. It's the same format you use for views, child objects and the AddObject function. However, Type must always be ‘Menu'. You also need a table called Children which will have the menu items in it. You do not and should not set the size or position of any menu child, however, you should set Name, Type and Text. I've just copied this example from the options menu in Files, so the menu items aren't really anything specific. In terms of naming convention, yet again it's up to you, but I personally have a few descriptive words and ‘MenuItem' at the end.

Let's look at the code to make these menu items do something. Within the if statement we wrote before you'll want to add a few lines such as the ones below which set the OnClick value of each menu button.

program:GetObject('HelloButton').OnClick = function(self, event, side, x, y)
if self:ToggleMenu('optionsmenu', x, y) then
if listMode then
program:GetObject('ViewModeMenuItem').Text = 'Icon View'
end

program:GetObject('ViewModeMenuItem').OnClick = function()
--Do the related stuff
end

program:GetObject('HiddenFilesMenuItem').OnClick = function()
--Do the related stuff
end
end
end

Note: Notice that I am still using program:GetObject, not self or any menu value. If you want to you can use program.Menu instead, but it's not necessary. However, this is why having unique names are so important, if you have something else called ‘ViewMode' then you'll end up with quite a nasty bug.

Now, the reason I'm using this example is because the menu items' text actually changes based on the settings (I have removed the if statement for the other menu item purely to keep the code shorter for the example).

You may have seen in OneOS that the menus also have separators (grey horizontal lines) between some items. It's very easy to add a separator, simply paste this between two menu items and it should work.

	{
	  ["Type"]="Separator"
	},

Second Way
I previously said that there are two ways to load menu content. This way is pretty much identical to the first way except rather than loading the menu items from a file you simply copy and paste the table from the file (or just use the same format) and replace the menu name with the table. For example:


if self:ToggleMenu({
  Type="Menu",
  Children={
	{
	  Name="ViewModeMenuItem",
	  Type="Button",
	  Text="List View"
	},
	{
	  ["Type"]="Separator"
	},
	{
	  Name="HiddenFilesMenuItem",
	  Type="Button",
	  Text="Show Hidden"
	}
  },
}, x, y) then

This way can get quite messy. However, the biggest advantage is that you can easily change the menu content dynamically. As a bonus you can also include the OnClick function as a table value.

Text BoxesText boxes are an essential part of many programs. However, due to the difficulty to code them people often use read(), which isn't ideal. With Bedrock you can easily make text boxes that the user can interact with as they would with a text box on their real computer.

You'll want to add a text box to your view or use AddObject. See if you can do it yourself as it is something you'll need to do a lot. I have put an example in the spoiler below, however.

Spoiler

{
X=2,
Y=2,
Width=15,
Type="TextBox",
Name="SearchTextBox",
Placeholder="Search...",
Active=true
}
If you take a look in the spoiler above you'll notice that I've actually got a placeholder. In most search bars you'll see greyed out text that says 'Search' or something similar. The text will automatically hide once the user has entered text. You can also set the text value so there is text in the box when it's loaded.

You will also notice that I've got Active set to true. This automatically selects the text box so the user doesn't have to click on it first.

To get text from a text box use the same way we used with labels and buttons previously.

If you want do so something each time the user presses a key, such as instantly update the search you can use the OnChange event. Similar to OnClick this will fire each time a key is clicked.

program:GetObject('SearchTextBox').OnChange = function(self, event, keychar)
--update the search
search(self.Text) --you'd obviously have to define search() elsewhere
end
The event may either by key or char, so key char will either be a number or string. In most cases you won't need to know what thi" chara…" is so you can just use self.Text.

Image View
SpoilerImage views allow you to easily display an image in your program. It is important to note that the images must be NFT format, which can be created using Sketch or NPaintPro. Files made in paint will not work (although I might look in to adding support for paint files).

There are three values you need to set in the objects table. The width, height and path of the image. If you do not set the size of the image it will only be 1 x 1 pixel. The path the image should just be a string, such as "/Images/myimage". I create a folder called ‘Images' to put my images in, but it's up to personal preference.


Thanks for trying out Bedrock. It might take a bit of getting used to, but I think you'll find it very useful. As mentioned at the top, I haven't quite finished, but those tutorials will come soon.

At this stage Bedrock is in beta. I'll try to avoid future updates that break things, but I don't really see myself changing much really. Bedrock is a culmination of PearOS, OneOS 1-1.1 and my work in Cocoa. It's pretty much my ultimate GUI API.

Anyway, please give any feedback about Bedrock itself on the topic in APIs & Utilities. This topic is strictly for tutorials/documentation.

A final reminder. I ask that if you have any issues you just can't solve you either post here, or if it's a large problem create an Ask a Pro topic. It's probably also a good idea to PM me with a link to the topic, as I don't really look in Ask a Pro very much and mightn't see it. It just makes the answers public and easy to find.

Enjoy!
Edited on 29 April 2016 - 08:05 AM
Win7yes #2
Posted 20 July 2014 - 08:00 AM
This is like… A GUI programming language xD
Looks very nice, I will use it for something tomorrow

Found out by reading that that this comment doesn't go here :P/>
Edited on 20 July 2014 - 07:56 AM
Awesomesause200 #3
Posted 20 July 2014 - 05:09 PM
This sounds like an amazing idea, I like it. However, I must be a pretty big noob, but I cannot seem to get the bedrock to start a program

I managed to get up to this far into the tutorial and then I get stumped:


local bedrockPath='/'
if OneOS then OneOS.LoadAPI('/System/API/Bedrock.lua', false)
elseif fs.exists(bedrockPath..'/Bedrock')then 
os.loadAPI(bedrockPath..'/Bedrock')else if http then print('Downloading Bedrock...')
local h=http.get('http://pastebin.com/raw.php?i=0MgKNqpN')
if h then 
local f=fs.open(bedrockPath..'/Bedrock','w')
f.write(h.readAll())
f.close()
h.close()
os.loadAPI(bedrockPath..'/Bedrock')
else error('Failed to download Bedrock. Is your internet working?') end 
else error('This program needs to download Bedrock to work. Please enable HTTP.') 
end 
end 
if Bedrock then 
Bedrock.BasePath = bedrockPath 
Bedrock.ProgramPath = shell.getRunningProgram() 
end


local program = Bedrock:Initialise()

program:Run(function()
program:GetObject('HelloLabel').Text = 'That was easy!'
program:GetObject('HelloLabel').BackgroundColour = colours.lightBlue
end)

Am I missing something here?
Win7yes #4
Posted 20 July 2014 - 05:35 PM
Do you get an error or nothing on screen appears?
Awesomesause200 #5
Posted 20 July 2014 - 09:33 PM
I got an error screen saying: "bedrock:2178: attempt to index ? (a nil value)"

Edit: Forgot to add the code for the Views/main.view program, I'll add it now

Spoiler
{
  Children={
	    {
		  X=2,
		  Y=2,
		  Name="HelloLabel",
		  Type="Label",
		  Text="Hello! I'm a Label!"
	    },
	    {
		  X=2,
		  Y=4,
		  Name="HelloButton",
		  Type="Button",
		  Text="Hello! I'm a Button!"
	    }
  },
  BackgroundColour=‘white’
}
Edited on 20 July 2014 - 07:37 PM
oeed #6
Posted 20 July 2014 - 10:57 PM
I got an error screen saying: "bedrock:2178: attempt to index ? (a nil value)"

Edit: Forgot to add the code for the Views/main.view program, I'll add it now

Spoiler
{
  Children={
	    {
		  X=2,
		  Y=2,
		  Name="HelloLabel",
		  Type="Label",
		  Text="Hello! I'm a Label!"
	    },
	    {
		  X=2,
		  Y=4,
		  Name="HelloButton",
		  Type="Button",
		  Text="Hello! I'm a Button!"
	    }
  },
  BackgroundColour=‘white’
}
I'll change that to a better error message.
theoriginalbit #7
Posted 21 July 2014 - 01:31 AM
I feel like I've read somewhere that you have a wiki, yes?
oeed #8
Posted 21 July 2014 - 02:10 AM
I feel like I've read somewhere that you have a wiki, yes?

You probably have. Not yet, but I'm thinking of putting more of a description of what each function does and leave this for a more detailed tutorial.
thijsmie #9
Posted 21 July 2014 - 02:32 PM
I believe there is a bug: the variable ProgramPath includes the name of the actual file, so if I have a program startup, it tries to load views from /startup/Views instead of /Views.
Win7yes #10
Posted 21 July 2014 - 07:17 PM
Bug: I did the basic view thing, running under OneOS, and then when I ran the application, it said
AppRedirect.lua:143: attemp to compare number with string expected, got number
If I remove the BackgroundColour='white' line it will run fine, but background is transparent.
Edit: Code of both, the main.view file and the program's main file
Main File (startup)
Spoiler

local bedrockPath='/' if OneOS then OneOS.LoadAPI('/System/API/Bedrock.lua', false)elseif fs.exists(bedrockPath..'/Bedrock')then os.loadAPI(bedrockPath..'/Bedrock')else if http then print('Downloading Bedrock...')local h=http.get('http://pastebin.com/raw.php?i=0MgKNqpN')if h then local f=fs.open(bedrockPath..'/Bedrock','w')f.write(h.readAll())f.close()h.close()os.loadAPI(bedrockPath..'/Bedrock')else error('Failed to download Bedrock. Is your internet working?') end else error('This program needs to download Bedrock to work. Please enable HTTP.') end end if Bedrock then Bedrock.BasePath = bedrockPath Bedrock.ProgramPath = shell.getRunningProgram() end

local program = Bedrock:Initialise()
program:LoadView("main")
program:Run(function()
program:GetObject("ShowBtn").OnClick = function(self, event, side, x, y)
program:DisplayAlertWindow("Prg.Msg","msg=Working on it...",{"Ok"})
end
program:GetObject("ExitBtn").OnClick = function()
--program:DisplayAlertWindow("Information","Closing...",{"Ok"})
sleep(1)
term.setBackgroundColor(colors.black)
term.clear()
term.setCursorPos(1,1)
OneOS.Close()
end
end)
View File:
Spoiler

{
  Children={
		{
		  X=15,
		  Y=7,
		  Name="ShowBtn",
		  Type="Button",
		  Text="Show Log"
		},
		{
		  X=15,
		  Y=9,
		  Name="ExitBtn",
		  Type="Button",
		  Text="Exit"
		}
	 },
  BackgroundColour="white",
}
Edit 2: Apparently is an OneOS and the AppRedirect.lua file related issue. What does the AppRedirect.lua file do?
Edited on 21 July 2014 - 08:56 PM
oeed #11
Posted 21 July 2014 - 10:54 PM
Bug: I did the basic view thing, running under OneOS, and then when I ran the application, it said
AppRedirect.lua:143: attemp to compare number with string expected, got number
If I remove the BackgroundColour='white' line it will run fine, but background is transparent.
Edit: Code of both, the main.view file and the program's main file
Main File (startup)
Spoiler

local bedrockPath='/' if OneOS then OneOS.LoadAPI('/System/API/Bedrock.lua', false)elseif fs.exists(bedrockPath..'/Bedrock')then os.loadAPI(bedrockPath..'/Bedrock')else if http then print('Downloading Bedrock...')local h=http.get('http://pastebin.com/raw.php?i=0MgKNqpN')if h then local f=fs.open(bedrockPath..'/Bedrock','w')f.write(h.readAll())f.close()h.close()os.loadAPI(bedrockPath..'/Bedrock')else error('Failed to download Bedrock. Is your internet working?') end else error('This program needs to download Bedrock to work. Please enable HTTP.') end end if Bedrock then Bedrock.BasePath = bedrockPath Bedrock.ProgramPath = shell.getRunningProgram() end

local program = Bedrock:Initialise()
program:LoadView("main")
program:Run(function()
program:GetObject("ShowBtn").OnClick = function(self, event, side, x, y)
program:DisplayAlertWindow("Prg.Msg","msg=Working on it...",{"Ok"})
end
program:GetObject("ExitBtn").OnClick = function()
--program:DisplayAlertWindow("Information","Closing...",{"Ok"})
sleep(1)
term.setBackgroundColor(colors.black)
term.clear()
term.setCursorPos(1,1)
OneOS.Close()
end
end)
View File:
Spoiler

{
  Children={
		{
		  X=15,
		  Y=7,
		  Name="ShowBtn",
		  Type="Button",
		  Text="Show Log"
		},
		{
		  X=15,
		  Y=9,
		  Name="ExitBtn",
		  Type="Button",
		  Text="Exit"
		}
	 },
  BackgroundColour="white",
}
Edit 2: Apparently is an OneOS issue and the AppRedirect.lua file used to I pressume redirect applications to the program tabs
OneOS actually has a different (out of date) version of Bedrock. I'll update it later this week. For now just use it standalone.
Win7yes #12
Posted 21 July 2014 - 11:08 PM
Question Time!
How can I make a box with a scrollbar and put text in it?
Or a better question:
How do ScrollViews work?
Edited on 21 July 2014 - 11:13 PM
Win7yes #13
Posted 22 July 2014 - 03:16 AM
No but I mean I left some things that made the program:Quit() fail to close and it just closed the Alert box. And Sorry :P/> I will make help posts in the tutorial
topic in the future

Oh I see, can you give some example code? (post in the tut. topic)

program:DisplayAlertWindow("Message", "Hello", {"Ok"}, function(value)
  if value == "Ok" then
    if program:Window then
	  program.Window:Close()
    end
  end
end)
Then I replaced the program.Window:Close() with program:Quit(). Code ended like this:

program:DisplayAlertWindow("Message", "Hello", {"Ok"}, function(value)
  if value == "Ok" then
    if program:Window then
	  program:Quit()
    end
  end
end)
Resulting in it not quiting the program because of an unknown reason. It would just close the alert window
PS: I reply just now because I saw your post on the APIs and Utilities section just now :P/>
oeed #14
Posted 22 July 2014 - 10:52 PM
Question Time!
How can I make a box with a scrollbar and put text in it?
Or a better question:
How do ScrollViews work?
Sorry for not replying sooner, I've been very busy with homework.
When I find the time I'll add a section about scroll views, for now take a look at the code for ListView and CollectionView. They do require you to make your own object, but it's not too hard. Make a folder called 'Objects' and create a file named something like "TextView.lua" and copy the code from one of those in to it.

No but I mean I left some things that made the program:Quit() fail to close and it just closed the Alert box. And Sorry :P/> I will make help posts in the tutorial
topic in the future

Oh I see, can you give some example code? (post in the tut. topic)

program:DisplayAlertWindow("Message", "Hello", {"Ok"}, function(value)
  if value == "Ok" then
	if program:Window then
	  program.Window:Close()
	end
  end
end)
Then I replaced the program.Window:Close() with program:Quit(). Code ended like this:

program:DisplayAlertWindow("Message", "Hello", {"Ok"}, function(value)
  if value == "Ok" then
	if program:Window then
	  program:Quit()
	end
  end
end)
Resulting in it not quiting the program because of an unknown reason. It would just close the alert window
PS: I reply just now because I saw your post on the APIs and Utilities section just now :P/>
When the function for an alert window is called the window has already closed, so it doesn't exist. However, you know that at some point there was one. Change it to something like this:

program:DisplayAlertWindow("Message", "Hello", {"Ok"}, function(value)
  if value == "Ok" then
    program:Quit()
  end
end)
Win7yes #15
Posted 22 July 2014 - 10:56 PM
I did change the code and it worked.
Lua.is.the.best #16
Posted 30 July 2014 - 03:27 AM
I found a error in the text.
In the future I hope to make a program which allows you do make views using a drop and drop interface

Edit: Misspelled (to) too, italicized it

Seems like this goes in a PM. xD
Edited on 30 July 2014 - 01:30 AM
Saldor010 #17
Posted 13 September 2014 - 02:54 AM
It's great that I can load a view, but how do I unload a view?
oeed #18
Posted 13 September 2014 - 06:07 AM
It's great that I can load a view, but how do I unload a view?

Well, you should be able to just load another. That should work. Why would you want to?
Saldor010 #19
Posted 13 September 2014 - 03:42 PM
It's great that I can load a view, but how do I unload a view?

Well, you should be able to just load another. That should work. Why would you want to?

I was going to use different views for different scenes of my program, but I don't need to anymore, I was able to find a work around.
AssossaGPB #20
Posted 12 October 2014 - 07:33 PM
I have my files set up just like yours from the first two spoilers, but it claims I need to call LoadView(). But if I call LoadView("main"), it claims that main.view doesn't exist, which it does.

Here is my file structure:

+ /
|-Bedrock
|-TestFile (the file from the first spoiler)
|+ Views
||-main.view (the file from the second spoiler)

The error is:
No Loaded view. You need to do program:LoadView first
or when I add program:LoadView("main"):
Bedrock:2006: The view: main.view does not exist.

Please help me, I'm so confused
Edited on 12 October 2014 - 06:07 PM
Lyqyd #21
Posted 12 October 2014 - 08:04 PM
Looks like the folder should be called "Views", with an "s".
AssossaGPB #22
Posted 12 October 2014 - 08:07 PM
Looks like the folder should be called "Views", with an "s".
Oops, I typed it wrong in the post. The folder is called Views.
Lignum #23
Posted 12 October 2014 - 09:14 PM
I have my files set up just like yours from the first two spoilers, but it claims I need to call LoadView(). But if I call LoadView("main"), it claims that main.view doesn't exist, which it does.

Here is my file structure:

+ /
|-Bedrock
|-TestFile (the file from the first spoiler)
|+ Views
||-main.view (the file from the second spoiler)

The error is:
No Loaded view. You need to do program:LoadView first
or when I add program:LoadView("main"):
Bedrock:2006: The view: main.view does not exist.

Please help me, I'm so confused
Bedrock doesn't seem to load views when they're in root. I've made a pull request which fixes this here, but it hasn't been merged yet. For now, just move your program's files into a directory that isn't root.
oeed #24
Posted 12 October 2014 - 10:30 PM
I've been working on a bug fix,it should be released today.
AssossaGPB #25
Posted 13 October 2014 - 02:48 AM
I have my files set up just like yours from the first two spoilers, but it claims I need to call LoadView(). But if I call LoadView("main"), it claims that main.view doesn't exist, which it does.

Here is my file structure:

+ /
|-Bedrock
|-TestFile (the file from the first spoiler)
|+ Views
||-main.view (the file from the second spoiler)

The error is:
No Loaded view. You need to do program:LoadView first
or when I add program:LoadView("main"):
Bedrock:2006: The view: main.view does not exist.

Please help me, I'm so confused
Bedrock doesn't seem to load views when they're in root. I've made a pull request which fixes this here, but it hasn't been merged yet. For now, just move your program's files into a directory that isn't root.
Ah ha, that would make sense, Thanks!

I've been working on a bug fix,it should be released today.
Ok, cool. Thanks

EDIT (Don't want to double post):
I finished reading the documentation and I am amazed at how useful and easy this is to use. I have a few questions though, like how would I do a multi-line textbox? Also how do I have multiple views showing at the same time like you did in your html browser? Also, when is documentation coming out on scroll bars/lists? I can't wait.

Thanks!
Edited on 13 October 2014 - 02:00 AM
cdel #26
Posted 15 October 2014 - 10:59 AM
is it possible to save the views in a different location besides the root directory?
EDIT: If not, is there a method I could use to "trick" it into thinking its aiming at the Views directory.

Sorry if this belongs in Ask a Pro. :P/>
Edited on 15 October 2014 - 09:05 AM
Lignum #27
Posted 15 October 2014 - 02:11 PM
is it possible to save the views in a different location besides the root directory?
EDIT: If not, is there a method I could use to "trick" it into thinking its aiming at the Views directory.

Sorry if this belongs in Ask a Pro. :P/>

Bedrock looks for the views in the Views folder located in the working directory of the program. There is a bug that causes Bedrock to not find the Views directory when the working directory is root. Either I'm misunderstanding your question, or you're confusing something.
AssossaGPB #28
Posted 15 October 2014 - 08:33 PM
With the Custom Event Handling, how do I get the parameters from the event? Like if it's modem_message how do I get the message, sender, etc?
Lignum #29
Posted 15 October 2014 - 09:00 PM
With the Custom Event Handling, how do I get the parameters from the event? Like if it's modem_message how do I get the message, sender, etc?
For example:

program:RegisterEvent("rednet_message", function(self, event, sender, message, protocol) --# You can get the return values as function parameters here.
   print("Received \"" .. message .. "\" from " .. sender)
end)
AssossaGPB #30
Posted 16 October 2014 - 02:13 AM
With the Custom Event Handling, how do I get the parameters from the event? Like if it's modem_message how do I get the message, sender, etc?
For example:

program:RegisterEvent("rednet_message", function(self, event, sender, message, protocol) --# You can get the return values as function parameters here.
   print("Received \"" .. message .. "\" from " .. sender)
end)
Ah, ok thanks!
cdel #31
Posted 16 October 2014 - 02:57 AM
is it possible to save the views in a different location besides the root directory?
EDIT: If not, is there a method I could use to "trick" it into thinking its aiming at the Views directory.

Sorry if this belongs in Ask a Pro. :P/>/>

Bedrock looks for the views in the Views folder located in the working directory of the program. There is a bug that causes Bedrock to not find the Views directory when the working directory is root. Either I'm misunderstanding your question, or you're confusing something.

I'm using bedrock for my git clients gui, I don't want the views or any local files to be visible.
oeed #32
Posted 16 October 2014 - 04:30 AM
I'm using bedrock for my git clients gui, I don't want the views or any local files to be visible.

As I'm getting close to releasing Quest I'm looking in to making a program to squish all the files in to one file which would include all the other files and folders. Either that or I'll update PkgMake.
cdel #33
Posted 16 October 2014 - 07:39 AM
I'm using bedrock for my git clients gui, I don't want the views or any local files to be visible.

As I'm getting close to releasing Quest I'm looking in to making a program to squish all the files in to one file which would include all the other files and folders. Either that or I'll update PkgMake.

Sorry just im a bit confused about your reply, am I able to just move the Views folder somewhere else rather than the root directory?
Win7yes #34
Posted 21 October 2014 - 09:22 PM
I'm using bedrock for my git clients gui, I don't want the views or any local files to be visible.

As I'm getting close to releasing Quest I'm looking in to making a program to squish all the files in to one file which would include all the other files and folders. Either that or I'll update PkgMake.

Sorry just im a bit confused about your reply, am I able to just move the Views folder somewhere else rather than the root directory?
You will need to make the directory, and move the Views folder AND the program to that directory.
spyman68 #35
Posted 14 December 2014 - 02:29 PM
I don't understand why it says view : main cannot be loaded. Could someone please help?
oeed #36
Posted 15 December 2014 - 01:00 AM
It was pointed out that some of the pieces of code were having issues (like the one above). I discovered that for some reason some of the quote marks had changed to 'fancy' quote marks, I've since fix this issue.
spyman68 #37
Posted 16 December 2014 - 02:11 AM
Could you try to explain the menus a little better? I was confused where I had to paste the code and such.
__Kiwi #38
Posted 30 December 2014 - 05:38 PM
I love this framework, but I have a question:
How can I create a "TextArea" ( multiline TextBox)? If I change the height of the TextBox object, then I can't use the enter key for jump a line.

(Sorry for my bad english)
SpencerBeige #39
Posted 16 February 2015 - 03:41 AM
could you plz shorten the syntax required to get bedrock?
oeed #40
Posted 16 February 2015 - 06:59 AM
Could you try to explain the menus a little better? I was confused where I had to paste the code and such.
I don't really have time to go in to much detail, but you call the function to show menus when you click a button.

I love this framework, but I have a question:
How can I create a "TextArea" ( multiline TextBox)? If I change the height of the TextBox object, then I can't use the enter key for jump a line.

(Sorry for my bad english)
Hmmm, yea I'll probably try to add that at some point, if I make Ink 2 I'll definitely have to.

could you plz shorten the syntax required to get bedrock?
These forums aren't powered by circa-1990's texting, so please just write a real sentence for goodness sake, honestly it just makes people think a lot less of you and will be less inclined to do what you ask, as in this situation.

So, no. It's a single line and every bit of it is required.
Edited on 16 February 2015 - 06:00 AM
SpencerBeige #41
Posted 19 February 2015 - 12:08 AM
Could you try to explain the menus a little better? I was confused where I had to paste the code and such.
I don't really have time to go in to much detail, but you call the function to show menus when you click a button.

I love this framework, but I have a question:
How can I create a "TextArea" ( multiline TextBox)? If I change the height of the TextBox object, then I can't use the enter key for jump a line.

(Sorry for my bad english)
Hmmm, yea I'll probably try to add that at some point, if I make Ink 2 I'll definitely have to.

could you plz shorten the syntax required to get bedrock?
These forums aren't powered by circa-1990's texting, so please just write a real sentence for goodness sake, honestly it just makes people think a lot less of you and will be less inclined to do what you ask, as in this situation.

So, no. It's a single line and every bit of it is required.
ok, i get it, you don't have you be rude. i was just thinking a bit of it wasn't required because throughout the line, you were testing for oneos api or something, so i was seeing if that was RLY required
oeed #42
Posted 19 February 2015 - 12:24 AM
ok, i get it, you don't have you be rude. i was just thinking a bit of it wasn't required because throughout the line, you were testing for oneos api or something, so i was seeing if that was RLY required

No, you still haven't got it. I know I am a little obsessive about these sort of things, but really, just learn to construct a sentence with words and capital letters. Until then I and most others aren't going to pay attention to you.
Elsys656 #43
Posted 06 March 2015 - 12:16 AM
Oeed I have a question about how to construct a view that lays out like this
{
Window
{
children={
scrollview
children={
buttons/labels/etc
scrollview aligned to 50% of x and y so the bottom left of the screen
children={
buttons/labels/etc
}
scrollview bottom right of the screen
children={
buttons/labels/etc
}
}
}
I have a view file set up like this the 2 bottom scrollviews objects are dynamically created.
Is it possible to have a scrollview inside a window that has an overall status pane or section on top of a child scrollview
with those dynamically created objects. Another way of looking at it would be how to go about modifying bedrock to accept nested views as one view.
The below will not load and errors out due to the Children=portion of the array.
Spoiler

{
Children={
{
X="1%",
Y=1,
Width="48%",
Name="reactorPane",
Type="Window",
Title="Reactor Status",
CanClose=false,
Children={
{
X="1%",
Y=1,
AutoWidth=true,
Name="reactorType",
Type="Label"
},
{
X="30%",
Y=1,
AutoWidth=true,
Name="rtotalStoredEnergy",
Type="Label"
},
{
X="1%",
Y=3,
AutoWidth=true,
Name="activeReactors",
Type="Label",
Text="Active Reactors:"
},
{
X="1%,+19",
Y=3,
AutoWidth=true,
Name="inactiveReactors",
Type="Label",
Text="Inactive Reactors:"
},
{
X="1%",
Y=5,
AutoWidth=true,
Name="averageFuelReactivity",
Type="Label",
Text="Fuel Reactivity:"
},
{
X="1%,+20",
Y=5,
AutoWidth=true,
Name="fuelUsedPerTick",
Type="Label",
Text="Fuel Used:"
},
{
X="1%",
Y=7,
AutoWidth=true,
Name="averageReactorTemp",
Type="Label"
},
{
X="1%",
Y=9,
AutoWidth=true,
Name="fuelPercentage",
Type="Label",
Text="Fuel Remianing:"
},
{
X="1%,+15",
Y=9,
AutoWidth=true,
Name="averageFuelPercentage",
Type="ProgressBar",
Value=0,
Maximum=100,
ShowText=true
}
}
},
{
X="1%",
Y=1,
Width="48%",
Name="turbinePane",
Type="Window",
Title="Turbine Status",
CanClose=false,
Children={
{
X="1%",
Y=1
AutoWidth=true,
Name="activeTurbines",
Type="Label",
Text="Active Turbines:"
},
{
X="1%,+19",
Y=1,
AutoWidth=true,
Name="inactiveTurbines",
Type="Label",
Text="Inactive Turbines:"
},
{
X="1%",
Y=3,
AutoWidth=true,
Name="averageRotorSpeed",
Type="Label",
Text="Rotor Speed:"
},
{
X="1%",
Y=5,
AutoWidth=true,
Name="rfTick",
Type="Label",
Text="RF/t:"
},
{
X="1%",
Y=7,
AutoWidth=true,
Name="ttotalStoredEnergy",
Type="Label",
Text="RF Stored:"
}
}
},
{
X="1%",
Y=4,
Width="48%",
Name="reactorButtonContainer",
Type="ScrollView"
},
{
X="1%",
Y=4,
Width="48%",
Height="20%",
Name="turbineButtonContainer",
Type="ScrollView"
},
{
X="10%",
Y=8,
Width="10%",
Height="10%",
Name="close",
Type="Button",
Text="Close"
},
{
X="20%",
Y=8,
Width="10%",
Height="10%",
Name="restart",
Type="Button",
Text="Restart"
},
{
X="30%",
Y=8,
Width="10%",
Height="10%",
Name="settings",
Type="Button",
Text="Settings"
}
},
BackgroundColour='white'
}
plato2000 #44
Posted 06 March 2015 - 11:54 PM
Hi, I'm trying to make a control system using Bedrock. I think I found a bug, but I have no idea where it could be.
The problem occurs here:

program:GetObject("Refresh").OnClick = function(self, event, side, x, y)
   x = tostring(cell.getEnergyStored()) .. " RF"
   program:GetObject("PowerStored").Text = x
  end
I've tried it with printing the value of x right there and that works, but when I try to set the value, it doesn't work. I can set the value to anything as long as I am not getting
cell.getEnergyStored()
in the same block.
Elsys656 #45
Posted 07 March 2015 - 07:51 PM
Just wanted to say I resolved my issues on the other hand Plato i'd create a function with no args and do all your value updates there then use a repeating timer in either your OnViewLoad method or in run depending on how many views you have. If you don't need to update that many things and want there to be a refresh button define x as local in the onclick. Program is likely getting variables confused.
oeed #46
Posted 07 March 2015 - 11:34 PM
Hi, I'm trying to make a control system using Bedrock. I think I found a bug, but I have no idea where it could be.
The problem occurs here:

program:GetObject("Refresh").OnClick = function(self, event, side, x, y)
   x = tostring(cell.getEnergyStored()) .. " RF"
   program:GetObject("PowerStored").Text = x
  end
I've tried it with printing the value of x right there and that works, but when I try to set the value, it doesn't work. I can set the value to anything as long as I am not getting
cell.getEnergyStored()
in the same block.
I doubt it's causing the issue, but don't use a variable name that's already declared (x).

So there's no error message, it just doesn't work?

Maybe use something to log or show what cell.getEnergyStored() is, even just doing this will probably help.

error(cell.getEnergyStored())

But nothing jumps out as being really wrong.

Elsys656 is right though, a timer might be a better option.
Edited on 07 March 2015 - 10:36 PM
Elsys656 #47
Posted 08 March 2015 - 05:44 PM
Sorry to bother you again Oeed I have my view displaying like I want however my Scrollview does not scroll it does display a scrollbar it's generated content using AddObject and in the OnUpdate event I have it set to call self:UpdateScroll()

Here's the relevant section when adding buttons I add a variable to the button Object named Index to keep track of which button is being clicked.
Spoiler

--getScrollview
local content = program:GetObject('content')
--add reactor buttons
for rbcindex=1, bigreactors.getReactorCount() do
content:AddObject({
X=2,
Y=rbcindex,
Type="Label",
Name="reactorLabel",
Text="Reactor "..rbcindex,
AutoWidth=true
})
local label=program:GetObject('reactorLabel')
local bgcolour = nil
if inTable(reactorStats.onlineReactors,rbcindex) == false then
bgcolour = "red"
else
bgcolour = "green"
end
content:AddObject({
X=2+label.Width+1,
Y=rbcindex,
Name="reactorButton",
Type="Button",
Text="Status",
BackgroundColour=bgcolour,
index=rbcindex
})
end
--turbine status buttons
--local tbc.index=1
for tbcindex=1, bigreactors.getTurbineCount() do
content:AddObject({
X=28,
Y=tbcindex,
Type="Label",
Name="turbineLabel",
Text="Turbine "..tbcindex,
AutoWidth=true
})
local label=program:GetObject('turbineLabel')
local bgcolour = nil
if inTable(turbineStats.onlineTurbines,tbcindex) == false then
bgcolour = "red"
else
bgcolour = "green"
end
content:AddObject({
X=28+label.Width+1,
Y=tbcindex,
Name="turbineButton",
Type="Button",
Text="Status",
BackgroundColour=bgcolour,
index=tbcindex
})
end
--end scrollview
I used to just call UpdateScroll after adding buttons this also "works" except the scrollview still doesn't scroll tried this in OnUpdate so it would call whenever changes were made to the content.
Spoiler

program:GetObject('content').OnUpdate = function(self)
self:UpdateScroll()
end
This sets a private variable (local inside program scope) inside the onClick handler. The buttons load and close the view just fine
Spoiler

function reactorClick(self, event,side,x,y)
reactorIndex = self.index
program:LoadView('reactor')
end
This portion is where I use reactorIndex the turbine handler/buttons all behave identically but set a different variable I didn't want to account for by other means setting name to the same thing across them all and checking a second variable to see what subtype the button was.
Spoiler

elseif loadedView == "reactor" then
updateReactor(reactorIndex)
program.Timers = {}
program:StartRepeatingTimer(function()updateReactor(reactorIndex)end, 5)

I would also like to load the objects from a file if possible dynamically creating the file on program run so it doesn't need to recreate objects all the time and I can just update their states. In my main.view update routine pretty much exactly like LoadView but without removing everything first. At the moment however more concerned with my first question.

By the way I tried switching to list views and it doesn't seem to propagate any click events even attached exactly as in the SaveFile dialog and still doesn't scroll
Edited on 08 March 2015 - 09:59 PM
roombascj #48
Posted 08 March 2015 - 09:05 PM
I am confused on how to use scroll views and scroll bars…
Elsys656 #49
Posted 10 March 2015 - 01:53 AM
I don't think you can use a Scrollview by itself I looked into the sources of other bedrock apps making use of scrollviews and they all define custom objects derived from scrollview that include a custom object based on a view. I have tried doing this and gotten fairly close just gotta define Height in all objects not sure which object it's referring to cause I have default height values set in my code and whatever objects of that type I create should just initialize with the default height value. (It doesn't do this so I must not be setting something on object creation haven't yet figured out what that is.)

More importantly I can't seem to find out how the structure of the Items Table should look except that I can guess something to this effect

YourcustomObject = {
Each base object defined in your onload function would require
{
Name=(whatever you named this subobject)
Whatever else you want to set the objects properties to
},
{
another object
}
more of these to match the number of elements in your custom object (more like an object structure)
}

Then set that table to Items of your custom Scrollview it should render but I'm doing something incorrect I'm guessing in my table I didn't define what type of object in my insert probably more like
{
Type=mycustomobject
Children={
define custom object
}
}
ill see if that format is more acceptable
Edited on 10 March 2015 - 01:04 AM
Elsys656 #50
Posted 12 March 2015 - 06:54 AM
Ok so I realized what had been done incorrectly and it's drawing now, not sure about the scrollbars exactly but it should. My problem is that my api that interfaces with peripherals is not returning control to bedrock… I need to somehow yield to bedrock to allow it to process events how should I do this? Apparently os.sleep was messing with the drawing functions. Scrolling is working now Yay. Yes button clicks are propagating properly as well.
Edited on 12 March 2015 - 08:46 AM
roombascj #51
Posted 14 March 2015 - 06:11 PM
Is there a function or way to make a object move around the screen or animate?
oeed #52
Posted 15 March 2015 - 12:40 AM
Ok so I realized what had been done incorrectly and it's drawing now, not sure about the scrollbars exactly but it should. My problem is that my api that interfaces with peripherals is not returning control to bedrock… I need to somehow yield to bedrock to allow it to process events how should I do this? Apparently os.sleep was messing with the drawing functions. Scrolling is working now Yay. Yes button clicks are propagating properly as well.
Yeah, you can't use sleep calls or things that yield anywhere.

Is there a function or way to make a object move around the screen or animate?
Yes, use the function 'AnimateValue'.


--	   value name   from  to  duration  callback
-- from, duration and callback can be nil
-- from defaults to the current value
-- duration defaults to 0.2
myButton:AnimateValue('Width', 10, 20, 0.5, function()end)
Edited on 14 March 2015 - 11:46 PM
roombascj #53
Posted 15 March 2015 - 12:44 AM
But i still don't understand how to use a scrollbar or a scroll view in a program.
Elsys656 #54
Posted 15 March 2015 - 03:57 AM
you need to create a custom object based on view lay the objects out like you want them to appear it needs to have a static height any events you should handle with those objects inside the ScrollView need to be defined inside that object or another file named the exact same in the APIs folder I found it easier to do it right in the custom object.


Inherit = 'View'

Width = 50
Height = 1
AssocButton = nil

OnLoad = function(self)
--[[this defines the program context so that the object can access your instance of bedrock... sometimes its better to make a new instance but that depends on the program.]]
local program = self.Bedrock

--[[I set my click events up here you would do the same for any other events you need to attach to objects inside your scrollview]]
--reactor click event
function reactorClick(self, event,side,x,y)
program.Timers = {}
program.reactorIndex = self.Index
program:LoadView('reactor')
end
--turbine click event
function turbineClick(self, event,side,x,y)
program.Timers = {}
program.turbineIndex = self.Index
program:LoadView('turbine')
end

--[[Here I set up the objects in my case some labels and buttons associated with those labels thus AssocButton :D/>]]
self:AddObject({
X=2,
Y=1,
Type='Label',
Width=12,
Height=1,
Name='reactorLabel',
Text='Reactor ',
Visible=false
})

self:AddObject({
X=14,
Y=1,
Width=6,
Height=1,
Type='Button',
Text='Status',
Name='reactorButton',
Visible=false,
BackgroundColour = "red",
OnClick = reactorClick
})

self:AddObject({
X=28,
Y=1,
Height=1,
Type='Label',
Width=12,
Height=1,
Name='turbineLabel',
Text='Turbine ',
Visible=false
})

self:AddObject({
X=40,
Y=1,
Height=1,
Width=6,
Type='Button',
Text='Status',
Name='turbineButton',
Visible=false,
BackgroundColour = "red",
OnClick = turbineClick
})

--[[Call OnUpdate to pull the variables that we didn't set here or any changed ones]]
self:OnUpdate('AssocButton')
end

--[[OnUpdate set variables to Objects like you would normally]]--
OnUpdate = function(self, value)
--[[value holds the type of object in this case AssocButton our custom type]]
if value == 'AssocButton' then
--check for nil values
--[[self is basically your current bedrock instance set these as normal and check for nil just because if your program passes an empty argument you'll be able to track it down easier]]
if self.AssocButton.objIndex ~= nil then
self:GetObject('reactorButton').Index = self.AssocButton.objIndex
self:GetObject('reactorLabel').Text = 'Reactor '..self.AssocButton.objIndex
self:GetObject('turbineButton').Index = self.AssocButton.objIndex
self:GetObject('turbineLabel').Text = 'Turbine '..self.AssocButton.objIndex
end
--check if reactor has nil values
if self.AssocButton.reactorVisible ~= nil then
self:GetObject('reactorLabel').Visible = self.AssocButton.reactorVisible
self:GetObject('reactorButton').Visible = self.AssocButton.reactorVisible
if self.AssocButton.reactorOnline == true then
self:GetObject('reactorButton').BackgroundColour = "green"
else
self:GetObject('reactorButton').BackgroundColour = "red"
end
end
-- check if turbine has nil values
if self.AssocButton.turbineVisible ~= nil then
self:GetObject('turbineLabel').Visible = self.AssocButton.turbineVisible
self:GetObject('turbineButton').Visible = self.AssocButton.turbineVisible
if self.AssocButton.turbineOnline == true then
self:GetObject('turbineButton').BackgroundColour = "green"
else
self:GetObject('turbineButton').BackgroundColour = "red"
end
end
end
end

Then set up a collection view object and also save it to the Objects folder next to your program (just like Views)



--[[The default values for a AssocButtonCollectionView yours would be named something else but its just like other objects in Bedrock you can set default values otherwise it would inherit whatever you don't set from ScrollView]]
Inherit = 'ScrollView'
UpdateDrawBlacklist = {['NeedsItemUpdate']=true}
Items = false
NeedsItemUpdate = false
TextColour = colours.black
BackgroundColour = colours.white

--[[this draws the object itself using bedrock drawing methods you could really draw anything you like here mines just a real basic blank pane]]
OnDraw = function(self, x, y)
  if self.NeedsItemUpdate then
   self:UpdateItems()
   self.NeedsItemUpdate = false
  end
  Drawing.DrawBlankArea(x, y, self.Width, self.Height, self.BackgroundColour)
end

--[[What to do on item update a scrollview takes an argument called Items that is a table of values you saw defined in the AssocButton object on update you can also add base objects here if you don't need a number of them]]
UpdateItems = function(self, value)
  self:RemoveAllObjects()
  local x = 1
  local y = 1
--[[a loop that iterates over all the tables inside a 2d table I set up to pass values to each sub-object in AssocButton]]
  for i, assocButton in ipairs(self.Items) do
   self:AddObject({
   X=x,
   Y=y,
   Height = x,
   Type = 'AssocButton',
   AssocButton = assocButton --[[Here you can see the type we defined earlier in AssocButton is used]]
   })
--[[My scrollview is very basic but you can change the positioning of items to have multiple "AssocButton" objects on one line or skip a line or lines using x and y values]]
  y = y + AssocButton.Height
  end
self:UpdateScroll()
end

--[[this forces the scrollview to initialize and pass its item array to my subObjects]]
OnUpdate = function(self, value)
if value == 'Items' then
  self.NeedsItemUpdate = true
end
end

–[[Do this for each value in your sub object wrap that in a table and pass it to your CollectionView]]
AssocButton.whatevervalue
AssocButton.whatevervalue

I know my explanation is probably close to clear as mud but it's all stuff I had to figure out from looking at OneOS code and Bedrocks source
Then in your view file under Type="yourcollectionview" position it as normal etc.
roombascj #55
Posted 15 March 2015 - 02:14 PM
Im still very confused on how to use them though.
Edited on 15 March 2015 - 06:35 PM
Elsys656 #56
Posted 15 March 2015 - 06:07 PM
I'm not re-quoting all that just because it will turn into a giant wall of text my fault for not spoiler tagging everything. Anyway the call to self:UpdateScroll() actually draws the object so you don't need to worry about that any objects you set values for should appear and scroll its basically a way to make tons of objects appear in a small space. That particular ScrollView is being used to list 4 reactor status pages and 56 turbine status pages on one screen. I'm releasing the program within the next half hour as I have 99% if not all the kinks worked out. My computer system itself is the only thing keeping the program from locking up occasionally… 56 turbines is quite a lag machine but the 1.3-1.4 mil rf per tick produced is pretty sick. Originally did all this cause on 1.6.4 AtomicScience is very broken, I was in the process of fixing it up but because of how it had been ported to mostly proprietary code it got to be more of a headache than it was worth.

Further completely unrelated note: At least I found some use for the Electromagnetic Glass I went to the trouble of making(its now keeping me from frying myself on my 32 MFR Drills)
Edited on 15 March 2015 - 05:10 PM
roombascj #57
Posted 19 March 2015 - 02:30 AM
Is there any way to put a text box inside of an alert window?
Edited on 19 March 2015 - 08:46 PM
cdel #58
Posted 22 March 2015 - 05:00 AM
I don't want my Views folder in "/" , how can I move it to "/directory" ?
roombascj #59
Posted 22 March 2015 - 07:58 PM
With the custom windows, can i run a program in them and how?
MKlegoman357 #60
Posted 22 March 2015 - 08:25 PM
I don't want my Views folder in "/" , how can I move it to "/directory" ?

I believe there's a program.ViewPath variable for that.
cdel #61
Posted 26 March 2015 - 02:16 AM
Thanks :)/>
cdel #62
Posted 26 March 2015 - 11:08 AM
I am trying to launch another bedrock program within another bedrock program I have already created, how would I acomplish this? currently it will only show the view loaded in the first program, not the view from the second, even though it is using program.loadView().
MKlegoman357 #63
Posted 26 March 2015 - 08:03 PM
I am trying to launch another bedrock program within another bedrock program I have already created, how would I acomplish this? currently it will only show the view loaded in the first program, not the view from the second, even though it is using program.loadView().

Code?
cdel #64
Posted 26 March 2015 - 10:36 PM
Sorry just scratched using bedrock, hence why I no longer have the code on hand.
MKlegoman357 #65
Posted 27 March 2015 - 05:49 AM
Well, it depends on how you want to run that program. Another Bedrock program should be self contained, so a simple shell.run should work. Is it something else, like a manager to run programs specifically made for your Bedrock "parent" program?
Rougeminner #66
Posted 28 March 2015 - 03:48 AM
When i launched OneOS V2 to look at the Bedrock code and i noticed that there where a lot more arguments in the table for small things like splash screens and buttons there where % signs and all sorts of things that i didn't read about in your guide when and if you get the can you explain more of those "Strange arguments"? if you could that would be GREAT if you a can't it will take longer but i will figure it out.

BEST API i have ever seen. Thanks

I am trying to launch another bedrock program within another bedrock program I have already created, how would I acomplish this? currently it will only show the view loaded in the first program, not the view from the second, even though it is using program.loadView().

It sounds like you are wanting to make the equal to an HTML Iframe. is this correct?
cdel #67
Posted 28 March 2015 - 04:15 AM
Well, it depends on how you want to run that program. Another Bedrock program should be self contained, so a simple shell.run should work. Is it something else, like a manager to run programs specifically made for your Bedrock "parent" program?

I was using dofile, which luanches in the same environment I believe, hence why they conflicted.
roombascj #68
Posted 03 April 2015 - 04:17 PM
How do i use open file windows and save file windows?
Monthkiller #69
Posted 14 April 2015 - 01:51 AM
Uhh, just a question, but is it normal for Bedrock refusing to run programs via shell.run?
Because i've been trying to do that, and says No such program when i try to run and glitches the display


program:GetObject('InkApp').OnClick = function(self,event,side,x,y)
  shell.run('/sys/Programs/Ink/program')
end
oeed #70
Posted 14 April 2015 - 05:11 AM
Uhh, just a question, but is it normal for Bedrock refusing to run programs via shell.run?
Because i've been trying to do that, and says No such program when i try to run and glitches the display


program:GetObject('InkApp').OnClick = function(self,event,side,x,y)
  shell.run('/sys/Programs/Ink/program')
end
Yeah that won't work. Bedrock controls drawing the entire screen. You could quit the program or pause it somehow though.
Monthkiller #71
Posted 14 April 2015 - 11:55 AM
Uhh, just a question, but is it normal for Bedrock refusing to run programs via shell.run?
Because i've been trying to do that, and says No such program when i try to run and glitches the display


program:GetObject('InkApp').OnClick = function(self,event,side,x,y)
  shell.run('/sys/Programs/Ink/program')
end
Yeah that won't work. Bedrock controls drawing the entire screen. You could quit the program or pause it somehow though.

Ok i'll try using that or try wrapping the function that program:Run runs. Thanks for the info
Edit 1: Wrapping works, still broken.
Edit 2: Got it working, but i need to redraw the screen when exiting.
Edited on 14 April 2015 - 07:38 PM
oeed #72
Posted 15 April 2015 - 01:22 AM
Edit 2: Got it working, but i need to redraw the screen when exiting.

What do you mean? Why do you need to redraw if it's exited?
puzzletime #73
Posted 30 April 2015 - 11:32 PM
Can I override draw events to make custom widgets?
Rougeminner #74
Posted 05 July 2015 - 05:18 AM
How can i use the transparency?
oeed #75
Posted 05 July 2015 - 06:52 AM
How can i use the transparency?

As in make something completely see through? Simply use colours.transparent instead of, for example, colours.grey.
Rougeminner #76
Posted 12 July 2015 - 05:31 PM
I will now take said survey: does this answer make me feel stupid: Yup! could I have probably found this information out myself:Yup! could I have probably had a lick of commonsense and guessed that the answer would have been that simple: Yup! :D/>

Thanks oeed
Edited on 13 July 2015 - 05:59 AM
Rougeminner #77
Posted 13 July 2015 - 07:57 AM
Is there a wiki on Bedrock… there are somethings that just need documentaion and not a tutorial. like how to turn off bedrock without turing off the computer?
MKlegoman357 #78
Posted 13 July 2015 - 08:10 AM
Is there a wiki on Bedrock… there are somethings that just need documentaion and not a tutorial. like how to turn off bedrock without turing off the computer?

I think it's:


program:Quit()

…to quit a program, if that's what you mean.
oeed #79
Posted 13 July 2015 - 10:14 AM
Is there a wiki on Bedrock… there are somethings that just need documentaion and not a tutorial. like how to turn off bedrock without turing off the computer?

MKlegoman357 has the solution there for Bedrock.

Bedrock did have terrible documentation though. We will be having much better documentation for Silica, I'm about to start it as we speak. The code is also very heavily commented, I'd guess maybe about a sixth of all lines are comments. Bedrock had about 4 comments.
Rougeminner #80
Posted 13 July 2015 - 05:00 PM
Cool! i can't wait for the computercraft release for Silica is out its a whole new level for GUI framework that i didn't think was possible.

Thanks MKLegoman
Edited on 13 July 2015 - 03:03 PM
oeed #81
Posted 16 July 2015 - 06:14 AM
If you wanted to get started with using Silica you can already do so. The framework is not entirely complete, but the majority of function is there.

The docs are on GitHub: https://github.com/oeed/Silica/wiki/Getting-Started

I'm still writing documentation, it'll take a few weeks for it all to be done, but let me know if something isn't explained well enough and I'll change the pages to be more clear.
flaghacker #82
Posted 16 July 2015 - 01:26 PM
The OO system in Silicia looks really good! It feels like a better Java :)/>. Is there going to be a way to use the language without the gui stuff too?

The xml interfaces are similar to JavaFX and android, good job!

Never, ever, ever define functions in the properties table!

I'm sorry for my destructive nature, but what would go wrong?
Waitdev_ #83
Posted 31 July 2015 - 03:17 PM
can we have screenshots for what it does?
MKlegoman357 #84
Posted 31 July 2015 - 05:08 PM
can we have screenshots for what it does?

Ever used OneOS? If I'm not mistaken, the whole GUI was built using this. Also Sketch and other in-OneOS programs. It's a GUI framework designed to help in creating GUI-centric programs.
Edited on 31 July 2015 - 03:09 PM