Movatterモバイル変換


[0]ホーム

URL:


Docs.rs

Modulechapter_1

Source
Expand description

What is Conrod?

§A Brief Summary

Conrod is a portable, 2D,GUI library for theRust programming language.

It provides an immediate-mode API that wraps a retained-mode widget state graph. This allows us toexpose a simple, robust and reactive interface while approaching the performance of traditional,retained GUI frameworks.

We provide a set of primitive and commonly useful widgets, along with aWidget API that allowsfor designing new, custom widgets composed of unique logic and other widgets.

Widgets are instantiated using the “Builder” aka “Method Chaining” pattern within an update loop.In this sense, we can think of a Widget and its builder methods as a function with a highlyflexible and readable set of arguments.

§Screenshots and Videos

If you have an awesome looking GUI made with conrod, please send us a screenshot and we’ll add it here :)

Here’sa youtube demo of the all widgets example.

Here’sanother youtube demo of conrod being used to create a basic synth editor.

A multimedia timeline widget.

timeline

Theall_piston_window.rs example.

all_widgets.rs

Thecanvas.rs example.

canvas.rs

§Feature Overview

  • Reactive andImmediate API. Produce the UI from your application state in one place, rather than as a separate entity spread across callbacks, instantiation, updates and drawing.
  • AWidget trait to simplify the composition and design of widgets.
  • Scrolling that is opt-in, generalised and easy-to-use. Call.scroll_kids(true) on a widget and it will become a scrollable container for its children.
  • Powerful layout and positioning:
    • Placement -.middle(),.top_left_of(CANVAS),.mid_right_with_margin(20.0), etc.
    • Alignment -.align_left(),.align_top_of(LABEL), etc.
    • Relative -.down(20.0),.right_from(BUTTON, 40.0),.x_y_relative(20.0, 42.0), etc.
    • Absolute -.x_y(6.0, 7.0)
    • Draggable pop-up / floating canvasses -.floating(true).
    • WidgetMatrix andPositionMatrix for instantiating a grid of widgets.
  • **Theme**s for unique style and layout defaults.
  • widget_ids! macro for easily and safely generating unique widget identifiers.
  • Generic over events and graphics backends - compatible with:
  • Provides a collection of commonly useful widgets.

§Available Widgets

The widgets that are provided by conrod can be broken into two sets:primitive andcommonuse.

§Primitive Widgets

Primitive widgets are the fundamental graphical components in any conrod user interface. They are aspecial set of widgets from which all other widgets may be composed. For example, aButton widgetmay be composed of oneRectangle primitive widget and oneText primitive widget. ADropDownList may be composed ofnButton widgets, and in turnnRectangle primitivewidgets andnText primitive widgets.

When drawing the widget graph to the screen, conrodonly draws the primitive widgets. This allowswidget designers to create custom widgets by simply instantiating other widgets, without having todirectly write any graphics code themselves. This also greatly simplifies the caching of commonwidget state like text, positioning and styling as the primitive widgets take care of all of thisautomatically.

The following are the primitive widgets provided by conrod:

If conrod is lacking a primitive widget that you require, please let us know! There are currentlyplans to allow for a user to design their own primitive widgets, however these will likely remainlow priority until requested.

§Common Use Widgets

Common use widgets are simply widgets that are commonly required by GUIs. There is nothing specialabout these widgets in the sense that they could just as easily be implemented in an externalcrate by third-party users. However, their usage is common enough that we choose to distribute themwith conrod itself.

The following are the common use widgets provided by conrod:

The following are planned, but not yet implemented:

If you notice that we’re missing important widgets, or if you have a widget that you feel wouldmake a nice addition to conrod, please let us know by leaving anissue orpull request!Be sure to checkissues with the widgetlabelfirst, as your desired widget may have already been requested.

§“Immediate Mode”

§What is it?

The term “Immediate Mode” describes a style of user interface API.

In an immediate mode GUI, widgets are instantiated using functions in anupdate ordraw loop.This is quite different to the more traditional “retained mode”, where widgettypes areconstructed during thesetup stage.

Immediate mode encourages a less stateful, more data-driven design as the user interface isinstantiated as aresult of the application state every frame or update. On the other hand,retained user interfaces tend to work the other way around, driving the application by sendingevents or triggering callback functions upon user interaction.

§Why use it?

Immediate mode tends to be the easier style to use for highly dynamic interfaces and those thatrequire frequent synchronisation with application state. This is because immediate widgets handlechanges in application state at the same place in which they are instantiated (during the updateor draw stage). While retained interface logic is often divided up between instantiation, updating,drawing and event handling, immediate interfaces aim to consolidate all UI related logic within oneplace.

Historically, due to their statelessness and frequent re-instantiation, immediate mode interfaceshave been known to pay the price of performance for their convenience. Although retained interfacescan be more tedious to maintain and synchronise with application state, they are often less CPUintensive as the majority of their state remains untouched following the application’s setup stage.

§Is Conrod Immediate or Retained?

Conrod aims to adopt the best of both worlds by providing an immediate mode API over a hidden,retained widget state graph. From the user’s perspective conrod widgets tend to feel stateless, asthough they only exist for the lifetime of the scope in which they are instantiated. In actuality,each widget’s state is cached (or “retained”) within theUi’s internal widget graph. This allowsfor efficient re-use of allocations and the ability to easily defer the drawing of widgets to astage that is more suited to the user’s application. As a result, Conrod should be able to providethe convenience of an immediate mode API alongside performance that approaches that of traditional,retained GUIs.

§The Builder Pattern

The “Builder Pattern” describes the process of “building” a type by chaining together method calls.Conrod uses this pattern within its API for widget instantiation. This pattern is perhaps easiestto grasp with an example.

Let’s say we have aButton widget. We want to make sure that a user may instantiate it withspecific dimensions, position, color, label, label font size and label color. A naiive constructormight look like this:

Button::new(dimensions,            position,            color::RED,"DONT PRESS",            label_font_size,            label_color,            || do_stuff(),            BUTTON_ID,&mutui);

The problem is that most of the time users will just want theButton to choose defaults straightfrom theUi’sTheme, rather than specifying every parameter for every instance of aButtonthemselves. We want parameters to beoptional. Perhaps then, we should make optional parameterstake anOption?

Button::new(Some(dimensions),Some(position),None,"DONT PRESS",None,None,Some(|| do_stuff()),            BUTTON_ID,&mutui);

Although the user no longer has to think about the values for parameters they don’t care about,this is still extremely verbose and theNone parameters seem quite ambiguous.

In some languages, this problem might be solved using a combination of features called “namedparameters” and “default parameters”. If rust had these features, the above might look like this:

Button::new(dimensions=dimensions,            position=position,            label="DONT PRESS",            react=|| do_stuff(),            id=BUTTON_ID,            ui=&mutui);

Certainly an improvement in conciseness and readability. Although these features are not availableto us in Rust, there is a way in which we can emulate their behaviour - This is where the builderpattern comes in.

By moving each parameter out of thenew function args and into their own methods, we can treatmethods almost as though they are named parameters as in the above example. Here is what the abovemight look like using the builder pattern:

Button::new()    .dimensions(dimensions)    .position(position)    .label("DONT PRESS")    .react(|| do_stuff())    .id(BUTTON_ID)    .ui(&mutui);

This is in fact the method of widget instantiation used by conrod, though with some slightdifferences in method naming (best to check the examples directory for a proper demo).

Although this certainly seems like the nicest solution from an API perspective, theattentive rustacean may notice that this requires extra work for the widget designer compared tothe previous examples. Previously, all work for widget instantiation was done within thenewfunction. The builder pattern implementation introduces a few differences worth noticing:

  1. A method must be implemented onButton for every optional parameter.
  2. TheButton::new function must return some type that can be treated as a set ofOptionarguments which can be set as it is passed from builder method to builder method.
  3. There must be some method that indicates the end of building and the instantiation of the widget.

In Conrod, we are of the opinion that, in the common case, the extra work on behalf of the widgetdesigners is worth the benefits gained by the users. However, we also make a significant effort toaddress each of the above points best we can in order to reduce the workload of widget developers:

  1. We provide abuilder_methods! macro which reduces the boilerplate of builder methodimplementation.
  2. In Conrod, widgets are treated as a set of arguments to their state, rather than containingtheir own state themselves. This suits the immediate mode style of conrod, where widget state ishidden and stored within theUi.
  3. All Conrod widgets must take a unique identifier and a mutable reference to theUi. Weconsolidate this into a single.set(ID, &mut ui) method, which we also use as the indicationmethod to stop building and instantiate the widget within theUi.

All of these points will be covered later in more detail within the widget implementation sectionof the guide.


[8]ページ先頭

©2009-2025 Movatter.jp