GithubHelp home page GithubHelp logo

cc-ru / wonderful Goto Github PK

View Code? Open in Web Editor NEW
8.0 8.0 1.0 520 KB

It's wonderful... The GUI library, I mean. :crystal_ball: :sparkles:

License: Apache License 2.0

Lua 100.00%
gui opencomputers minecraft lua

wonderful's Introduction

wonderful

A wonderful GUI library for OpenComputers

Features:

  • Multi-monitor setup support. Any setup will be supported.
  • Advanced event system. Allows to implement and override behavior of any element.
  • Layouts. Why calculate the position yourself if the computer can do it just as well, and even better?
  • Customization and extendability. To modify a component, just extend from another one. Inherit from the base class wonderful.element.Element if you want to implement it from scratch.
  • Buffered rendering. The library only issues GPU calls for the parts that changed since the previous update, and packs them together beforehand.
  • OOP. I mean, proper OOP. Multi-inheritance, getters and setters, and more — thanks to the lua-objects library.

Documentation

The manual pages and API reference are available on doc.fomalhaut.me.

Current state

The library consists of 4 parts, each packaged separately:

  • wonderful-common, common utilities used by other parts
  • wonderful-buffer, the render buffer
  • wonderful-core, the GUI core
  • wonderful-std, the provided-by-default collection of something (hopefully widgets).

As for now, only common and buffer got their 0.1.0 releases; other parts have yet to be released.

Visit the issue tracker for the list of tasks.

The project is certainly comatose.

Installation

Want to tinker with the library nonetheless? Here's how to install wonderful.

  • On your opencomputer, fetch the code (you may directly run git clone there, for example, or download the code manually).
  • Install hpm if you haven't already: pastebin run vf6upeAN. Despite it's no longer maintained, I still use it for installing.
  • Run the following commands:
# hpm install -ly ./common
# hpm install -ly ./buffer
# hpm install -ly ./core
# hpm install -ly ./components
# hpm install -ly .

Development and contributing

I use the GitHub issues to manage the work. I also have the GitHub project. The "To do" list there is ordered; things at the top should probably be done first. Though there are also things worth doing anytime, and the documentation is a notable example.

Contributing code to the library can be difficult, as most things are basically undocumented, only having a LuaDoc. You need to understand how the most of the codebase works by reading the source code, although there are a few examples to help you out. If you want to ask questions about the library, feel free to reach out to me:

  • On the IRC: fingercomp at irc.esper.net
  • On the OpenComputers forums
  • By opening an issue here and stating the question

I highly appreciate documentation contributions. Creating a new manual page, updating the pages that already exist, or fixing a simple typo — it doesn't really matter how small or big a contribution is.

License

The code is licensed under the Apache License, Version 2.0. All examples are available under the Unlicense (see the examples directory).

wonderful's People

Contributors

fingercomp avatar grandmaster8 avatar leshainc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Forkers

igortimofeev

wonderful's Issues

The documentation

I believe the documentation is as important as the code itself. Especially for complex projects like this one. They should be comprehensive, organized, yet fun to read.

  • Introduction
  • Feature list
  • Reference; in-code documentation
  • Glossary (to be consistent)
  • Quickstart
  • Tutorial
    • Documents
    • Components and Layouts
    • Rendering
    • Component Attribute System
    • Buffer
    • Extending
  • Maintainer's Guide (how things work, explained from the maintainer's point of view)
    • How Buffer Works
    • Render Cycle
    • ...

Rename wonderful-components to wonderful-std

  • Define the wonderful.std module to be used for "standard" things there. For example, wonderful.std.event for the events provided by the library (Focus, KeyDown, etc).
  • Move wonderful.component to wonderful.std.element.
  • Move wonderful.signal to wonderful.std.event.signal.
  • Don't use the notion of "components" (meaning "classes that inherit from wonderful.element.Element") anymore. Instead, use "element" to refer both to the classes and to their instances.

Implement an immediate-mode "buffer"

Such a buffer would inherit from the Framebuffer class, but directly issue GPU instructions rather than storing the cell data. One could use it as a lightweight alternative to the usual framebuffer, as it would work well for small GUIs while consuming way less RAM.

#24 has to be done first, though.

Use explicit getters to access all fields

For example, replace uses of LeafNode.parentNode outside that class with LeafNode:getParent().

Though the basic idea is simple, it requires changing a ton of the code, and is very error-prone. But this kind of thing is better to be done earlier than later.

Expected advantages:

  • Increased perfomance when switching from Foo.__getters:bar to Foo:getBar(). __getters are implemented using metamethods, so, when an object is flattened by calling object:optimize(), they aren't added to the object table. Which means that every access to the getters requires traversing the inheritance tree.
  • Errors detected earlier. node.parent (expected node.parentNode) returns nil all the time. This hides the real error, as node.parentNode can also return nil if the node has no parent (is a root node). I've already spent a few days debugging such problems.
  • Makes it explicit that all fields of a class are considered implementation details, and aren't supposed to be accessed directly by the external users, but via the means of getFoo and setFoo methods.
    • Also makes it easier to preserve the invariants.
  • Behavior of getters that have side-effects is made less suprising.

Expected disadvantages:

  • Decreased perfomance when switching from Foo.field (just a table index) to Foo:getField() (usually 2 table indexes, and a call). I don't think the added overhead here are too high to be ignored, but if it does become a bottleneck, the field could just be accessed directly.

Rewrite the buffer

I see there are some people interested in this project, so I'm going to create a few issues that track what has yet to be done before we can push the 0.1.0 version of the library core and start building components.

The buffer, as it is right now, is pretty much useless. If I change the same block twice (e.g., set a green cell to blue and back to green) and flush the buffer, the block still gets marked as dirty and is redrawn.

We need to find a way to store the two states of the buffer that doesn't consume too much memory and is fast. And apply it when rewriting the buffer.

Post-render

After the library finishes rendering the children of a component, run the component's postRender method, which allows to make additional changes.

I think there could be some cases where this feature would come in handy.

Tracking of components

I'm talking about "hardware" components here, like GPUs and screens.

  • Don't crash if there's no output device.
  • In case the user specifically set a device address for a document, and it became unavailable, don't render the document.
  • If an automatically-set device becomes unavailable, switch to another one.

Perfomance concerns

If you run the position.lua example, you will be sure to notice one peculiar thing. That is, the program is slow. And this is one of the simpliest programs. Unless we make it fast enough to be usable, it's pointless to add new features.

A list of things certainly worth optimizing

  • Flatten the instruction tables. They aren't really CPU-intensive, but they do eat quite a lot of RAM, I suppose.
  • Optimize the Framebuffer:flush method. It's rather huge, and we need to make it faster. How? The comment at the top of buffer/src/buffer/init.lua explains that. See #22.
  • Make getter methods explicit. OOP-library-provided getters are funny, but they make use of metamethods, which are quite slow. It's also unobvious that access to some fields may trigger side effects. See #31.
  • Don't rerender things that don't need to be rerendered. Pretty self-explanatory, isn't it? And there's already a similar thing for element composition: we mark the elements that need to be recomposed.

Non-renderable tree support

An element has to be inserted to a document tree before it can accept children, because it doesn't have a stacking context. A dirty solution is to create a temporary stacking context in the non-renderable tree root and merge it when the root is inserted to another tree.

Transfer issues here

I started doing this a few months ago, but I was still using Trello to manage the tasks. But there's already an issue tracker here. I think it's better to keep the to-do list in one place and publicly accessible, hence the issue.

Scrolling

I had been working on this for a week, and it had turned out to be a much more difficult issue than I had thought. I hope I'll manage to deal with it somehow.

It's also important to mention that @LeshaInc demanded that every Element has to support scrolling its children.

Make the Wonderful class an event target

...So that we could add event handlers that don't correspond to any single document. For example, we may want to stop the whole event loop if ^C is pressed (on any keyboard).

Remove LeafElement

It has no purpose. It just complicates things. Why did I think it was a good idea?

Of course, other leaf-node classes should also be removed.

Box layout

  • Base functionality
  • Reverse order
  • Child alignment
  • Wrap

Mouse gestures

Implement a system that records mouse movements and allows to analyze them. We could use this to do drag-and-drop, scroll through a feed, or, when swiped to the right, show a menu.

Built-in widgets

What users want to get the library and use it right away. We need to provide the bundle of built-in widgets.

  • Buttons of various types
  • Text input areas
  • Labels
  • Menus
  • And other things like this.

Until the wonderful-core gets its 0.1.0 release, avoid doing this, as the API is really unstable.

Hotkeys

Or an easier way to match a key combination in key event handlers.

Show parent classes in the documentation

Nowhere in the docs inheritance information is mentioned, which is, obviously, very confusing. At the very least, we need an "Inherits from" section. If possible, the subclasses should also list methods they inherited, and overriden methods.

Shadow children

Allow elements to declare shadow children. Such children are contained in a separate tree, which can only be retrieved by the element. The shadow children should also receive events; during dispatch the shadow element tree is processed as if it were prepended to the child node list.

This allows to define elements that compose other elements. For example, a button could be defined as a composition of a rectangle, and a label on top of it.

Debug mode

Implement the debug mode, which activates argument checks for most functions. It has to be togglable to avoid hurting the perfomance.

Rewrite the attribute system

There's the style engine, and there's also the attribute system. They do the same thing, and I see no point in keeping that. Here are some particular problems of the style engine:

  • The code is awful. And unmaintainable. Well, it was the first attempt at making a language parser for me, but still.
  • The API is awful. Actually, it's almost non-existent.
  • Strange and inconsistent typing system.
  • I also believe it eats an enormous amount of memory. And processing power.

Well, we can get rid of the styles. It will be easier for me (less features to implement), but I still want to have some kind of attribute states that could be switched.

Layouts failed, try again

At some point I hope I'll be making GridLayout. The major question here is, how am I going to insert children? Of course, the children list is always linear and ordered, as we have to traverse the tree somehow. But that list shouldn't be exposed.

For GridLayout, we want to use layout:insert(row, column[, rowSpan, columnSpan[, rowStretch, columnStretch]]) or something. We could make the optional parameters element attributes, even though I'm not fond of that idea... what about the row and column, then?

All right, then. function Element:insert(...) self.layout:insert(...) end it is. Is it?

But how should we move elements to other layout cells? Therefore, no. A huge, heavy, unconditional no. Even if we could do something about this concern, proxying is a hack — an unacceptable hack. We already have enough hacks in the code.

So, anyway, this is how I've come to realize that the current layout system makes no sense. I'd like to make layouts nodes of the document tree, as it's done in such major GUI toolkits as Qt and GTK+.

To make life easier, I want to keep scrolling magical and applied to every non-leaf element as it is right now. Doing a ScrollView means making some element be treated specially. Perhaps there's no point to allow users to override the scroll view, but I just don't like additional restrictions.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.