Giter Site home page Giter Site logo

natinusala / borealis Goto Github PK

View Code? Open in Web Editor NEW
252.0 252.0 78.0 9.2 MB

Hardware accelerated, controller and TV oriented UI library for PC and Nintendo Switch (libnx)

License: Apache License 2.0

Makefile 2.67% C 0.27% C++ 91.36% Meson 0.72% Shell 0.16% Python 4.83%
controller cpp cpp-library cross-platform gamepad glfw gui hacktoberfest homebrew library meson nanovg nintendo-switch opengl touch tv ui yoga-layout

borealis's People

Contributors

bernardogiordano avatar bylaws avatar ckurtz22 avatar d3fau4 avatar emretech avatar fincs avatar jon-dez avatar natinusala avatar nicholemattera avatar p-sam avatar thelukeguy avatar werwolv avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

borealis's Issues

New Class: Progress bar as dialog popup

Hello there :)

I've been working with borealis to build a GUI for SMM, and I would like to add a progress bar layout while the program is executing something (std::async). I tried different things but it seems I can't use brls::Dialog as a class template to do this. So I was wondering maybe this could be interesting to have a kind of template to display anything (like a progress bar) in the style of brls::Dialog::open().

But if you have a better idea to display a popup progress bar (a bit like tinfoil for example) with what's already existing, it would be great too!

Cheers

Reimplement Button

To be done:

  • Add icon support, ideally can be placed anywhere around the label
  • Add setBorderVisibility calls in onFocusGained and onFocusLost next to setShadowVisibility (setBorderVisibility must be implemented in View)
  • Ensure all button styles are implemented for both states (enabled / disabled)

Finish splitting platform code entirely

  • swkbd (remove lib/platforms/switch/swkbd.cpp from meson.build, move and adapt current swkbd file to switch_keyboard impl)
  • specify somewhere that frame pacing should be handled by each platform's vsync

Segfault when Sidebar has no child

There is a segfault when borealis tries to render a sidebar with no children.
Unsure if this is intended, but a quick fix is trivial.

// File: library/lib/sidebar.cpp

View* Sidebar::getDefaultFocus()
{

    ...

// Line 43
    View* toFocus{ nullptr };
    if(this->children.size() != 0)
        // Try to focus last focused one
        toFocus = this->children[this->lastFocus]->view->getDefaultFocus();

    ...

}

Reimplement ThumbnailFrame (now EditView / EditFrame)

Self explanatory. If you have a better name please don't hesitate to tell me.

Make it in two parts: one EditView view that's just the content, so that people can use it in their own AppletFrames, as well as a standalone EditFrame that's AppletFrame + EditView for convenience.

Reimplement LayerView

There should be two modes:

  • always preserve alls views in memory
  • free views and reallocate them when switching (the same way TabFrame works)

TabFrame should also be changed to use the new LayerView internally, using free / allocate mode.

Reimplement notifications + framerate counter

A concept of "layer" must be introduced, to allow adding stuff below and over activites without hardcoding them in Application.

A layer has a "draw" method and is simply resized to fullscreen when the window gets resized (like activities are). A "ViewLayer" layer must be done, which takes a "root" view and handles layout, etc... the same way the activities work. When a ViewLayer is resized, its view is resized and a layout pass must be done.

The current activities stack must be moved to its own layer. When the window is resized it must resize all layers, which will in turn resize all activities, running a layout pass on each one of them.

Notifications and framerate counter should be on their own layer too. They of course have to be reimplemented using the new layout system.

Notifications should be able to be placed on any corner of the screen. As as for the dialogs, notifications should be both easy to use and extensible - users should be able to post simple text notifications as well as custom views if they want fancy / custom stuff.

Depends on #150 to animate notifications, as well as #154 for the actual framerate counter.

To do list:

  • Introduce layers
  • Add ViewLayer
  • Move activites stack to its own layer, out of the Application code
  • Reimplement notifications and framerate counter in an "HUD" layer
  • Add an outline around the notifications (see on HOS, it's very subtle)

get selected value from SelectListItem and block exit button

Hello!
is there any way to get a value from any listitem?
if i cant get the value could you make public unsigned selectedValue;?
also i need block "+" because when i start the system update i can exit from the app.
(I don't know if borealis already has that options.)
thanks!

Use fmt to format the XML errors

Right now, all XML errors are generated by concatenating strings with the + operator. We have fmt in the library, so might as well use it instead.

Actually, a global "sprintf"-like function to format to a std::string would be useful, provided by brls in the utils.

Reimplement ListItem

Pretty self explanatory. The "valued" list items with a "value set" callback should be renamed to SettingListItem, with their value type as prefix (BoolSettingListItem...).

One issue is to figure out how to handle spacing between ListItems when putting multiple ones in a vertical Box. The same separator must be used when two items are close to each other, which means we need a way for an item to be aware of its surroundings.

An okay solution would be to add a "ListItemGroup" view that handles spacing between the items, the same way a checkbox group works on the web. List items should be usable with and without a group.

Depends on #96

Button inside List ends up becoming squished.

Buttons seem to scale according to the parent element. A List with buttons will end up squishing the buttons to an unreadable state. A solution to this would be to add some way to manually set button padding.

2018073114190800-DB1426D1DFD034027CECDE9C2DD914B8

[Question] Application example with video player

Hello,
First, thank you for your amazing work.
I would like to move my current GUI to borealis.
My objective is to delegate video to my core FFMPEG application.
Currently, the app is using SDL2(audio, video, gamepad, touchscreen) as main interface (but I can switch video to opengl easily).

I'm experiencing with borealis' view (StagedApplet) and nvgluCreateFramebuffer.
But I think I misunderstood the project philosophy.
Could you please give me some hints on how to implement video "player" (best practices)

My question are the following:
How to integrate/delegate raw OpenGL app in borealis (in fullscreen) ?
Any suggestion for audio/gamepad/touchscreen ?

I also searched across others borealis project without success.
Thank you a lot

Improve and streamline activities transitions animations

Depends on #107

  • TransitionAnimation should only be used for activities and view stacks
  • The in and out transitions animations should be an attribute of the activity, not given when pushing
  • Activites and view stacks should share the same code for transition animations

Reduce the number of layout passes on boot

When we start the app, the whole UI is created from the XML files. Every little XML view and attribute causes a whole layout pass on the entire activity view tree, which is bad.

We need a way to know when we are loading an XML file and differ all layout passes until this is done, do only do ONE pass in the end instead of multiple dozens.

Reimplement Table

But make it better with a fully dynamic number of rows and columns. No reason to make it suck now that we have yoga to take care of the layout for us.

Reimplement Sidebar

What's left:

  • Enable focus conservation once it's done in #105
  • Fix the focus sound being played when pressing A on a sidebar item (the focus sound is played above the clicking sound, only the clicking sound should be heard) when calling onControllerButtonPressed
  • Use a timer to wait before calling setActive when a sidebar item is selected, just like HOS does (this avoids creating and deleting every tab one after the other when going down the list by holding the DOWN button)

Support printing Korean and Chinese characters

Linked issue in sys-clk: retronx-team/sys-clk#23

borealis does not seem to display Korean characters (attached screenshots in the linked issue), this is probably due to the fact only the regular and the symbol font is loaded. The solution to solve this can be to load the other fonts returned by pl, and add them as a fallback font of the current regular font nvgAddFallbackFontId(...)

Reimplement AppletFrame

The only things missing are footer and hint once #88 is done.

  • Footer
  • Hint
  • Override addView and removeView to call setContentView like ScrollingFrame already has

Including borealis within a cmake project

Hello there,

I'm trying to use borealis as a submodule for my Switch homebrew SimpleModManager. I included the borealis lib with cmake in my project, and the compilation seems to work fine. However when I try to launch it on the Switch it crashes.

I've tried to isolate the problem and it seems like it comes from there :

// Init glfw
glfwSetErrorCallback(errorCallback);
glfwInitHint(GLFW_JOYSTICK_HAT_BUTTONS, GLFW_FALSE);
if (!glfwInit())
{
    Logger::error("Failed to initialize glfw");
    return false;
}

...

Application::window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, title.c_str(), nullptr, nullptr); // here is the crash

When glfwInit() is called, it makes glfwCreateWindow crashing.

Have you any clue on where it could come from ?

P.-S. Great GUI by the way :) It's been a while since I've looked for a kind a neutral GUI lib for the swich!

Segfault when attempting to render List with no items

This crashes. Very likely related to #29 but for BoxLayout.

brls::AppletFrame* rootFrame = new brls::AppletFrame(false, false);
brls::List* myList = new brls::List();
rootFrame->setContentView(myList);
brls::Application::pushView(rootFrame);

Reimplement TabFrame

What's left to do:

  • Change getDefaultFocus to try to focus the right pane instead
  • Remember focus when doing right side -> left sidebar -> right side (requires focus conservation from #105)

Reimplement Image

To be done:

  • Implement alignment options for FIT and CROP scaling types
  • Add a TILED scaling type using NVGimageFlags if possible
  • Add corners to ImageAlignment enum, implement it for all scaling types

Drawable and drawing classes

The concept of "drawing" can be defined in its own class. It would allow generalizing things like shapes, with common properties such as border color / radius, corner radius, shadow, etc...

A drawing is made of one or multiple layers.

A layer is made of multiple properties:

  • fill color
  • fill gradient
  • border color
  • border thickness
  • shadow type
  • etc...

Basically the same thing as what make the view backgrounds now.

Note: the current view background has a stub for a "custom" shadow that's not actually implemented. It should be implemented in drawings. The idea is to ask the user for all shadow properties (width, feather, opacity, offset).

View backgrounds can then be entirely replaced with a single Drawing, which will then take care of all the rendering.

  • Make a Drawable class that only has a draw method (the same as the one in View)
  • Make View inherit from Drawable
  • Implement the new Drawing class, also inheriting from Drawable, taken from the current view backgrounds
  • Make a way to define and create drawings from XML, and generalize the XML attributes handlers to allow usage of @theme, @style... in drawing XML files,
  • Remove the view backgrounds logic and replace it by a Drawing instance (also remove all custom backgrounds like sidebar...)
  • Add a new drawing XML type for views: @drawing/... to reference drawings for view background for example (and add a backgroundDrawing attribute)
  • Add a DrawableView method that takes a Drawable and simply draws it across its entire surface

Proper documentation using Doxygen

  • Unify the documentation everywhere to use the Doxygen javadoc syntax
  • Add a script to generate the doc in HTML
  • Host that on GitHub pages - if it can't be hosted on the same repo, add the doxygen html output folder to gitignore
  • Add a link to that in the README and Wiki

Pushing view more than once results in undefined behavior

As in title. I will provide info on two examples resulting in different behavior.

Example 1:

#include <stdio.h>
#include <stdlib.h>

#include <borealis.hpp>
#include <string>

int main(int argc, char* argv[])
{
    // Init the app
    brls::Logger::setLogLevel(brls::LogLevel::DEBUG);

    if (!brls::Application::init("Borealis example"))
    {
        brls::Logger::error("Unable to init Borealis application");
        return EXIT_FAILURE;
    }

        // Create a sample view
        brls::TabFrame* rootFrame = new brls::TabFrame();
	brls::AppletFrame* _appletFrame = new brls::AppletFrame(true, true);
	
	//Set title
        rootFrame->setTitle("Borealis Example App");
	_appletFrame->setTitle("Borealis Example App");
	
	//Create lists
        brls::List* testList = new brls::List();
	brls::List* testList2 = new brls::List();

	//Create listItem pushing view to AppletFrame
        brls::ListItem* HideTabItem = new brls::ListItem("Hide tab");
	HideTabItem->getClickEvent()->subscribe([_appletFrame](brls::View* view) {
            brls::Application::pushView(_appletFrame);
        });

	testList->addView(HideTabItem);
	
	rootFrame->addTab("Main", testList);
	
	//Create listItem pushing view to rootFrame
	
	brls::ListItem* ShowTabItem = new brls::ListItem("Show tab");
	ShowTabItem->getClickEvent()->subscribe([rootFrame](brls::View* view) {
            brls::Application::pushView(rootFrame);
        });

	testList2->addView(ShowTabItem);
	
	_appletFrame->setContentView(testList2);

        // Add the root view to the stack
        brls::Application::pushView(rootFrame);

        // Run the app
        while (brls::Application::mainLoop())
        ;

        // Exit
        return EXIT_SUCCESS;
}

By using clickEvent to push AppletFrame view then go back by pushing TabFrame view results in crash when trying to exit by using home menu and dedicated button. Provided example is returning 0x2A8 error.
Crash report:
01601141633_010000000000100d.log

Example 2:

#include <stdio.h>
#include <stdlib.h>

#include <borealis.hpp>
#include <string>

int main(int argc, char* argv[])
{
    // Init the app
    brls::Logger::setLogLevel(brls::LogLevel::DEBUG);

    if (!brls::Application::init("Borealis example"))
    {
        brls::Logger::error("Unable to init Borealis application");
        return EXIT_FAILURE;
    }

        // Create a sample view
        brls::TabFrame* rootFrame = new brls::TabFrame();
	brls::AppletFrame* _appletFrame = new brls::AppletFrame(true, true);
	
	//Set title
        rootFrame->setTitle("Borealis Example App");
	_appletFrame->setTitle("Borealis Example App");
	
	//Create lists
        brls::List* testList = new brls::List();
	brls::List* testList2 = new brls::List();

	//Create listItem pushing view to AppletFrame
        brls::ListItem* HideTabItem = new brls::ListItem("Hide tab");
	HideTabItem->getClickEvent()->subscribe([_appletFrame](brls::View* view) {
            brls::Application::pushView(_appletFrame);
        });

	testList->addView(HideTabItem);
	
	rootFrame->addTab("Main", testList);
	
	//Create listItem pushing view to rootFrame
	
	brls::ListItem* ShowTabItem = new brls::ListItem("Show tab");
	ShowTabItem->getClickEvent()->subscribe([rootFrame](brls::View* view) {
            brls::Application::popView();
         });

	testList2->addView(ShowTabItem);
	
	_appletFrame->setContentView(testList2);

        // Add the root view to the stack
        brls::Application::pushView(rootFrame);

        // Run the app
        while (brls::Application::mainLoop())
        ;

         // Exit
         return EXIT_SUCCESS;
}

By using clickEvent to push AppletFrame view, go back by using popview and again push AppletFrame it will stuck and crash in few seconds. Provided example is returning 0x2A8 error.
Crash report:
01601142026_010000000000100d.log

Earlier few times I also got 0x6A8 error with different code using similar methods, but I cannot replicate it now. Only what I have is crash report:

01600894264_010000000000100d.log

FW 10.1.0
Atmosphere 0.13.0
Using album and title replacement mode (in second case it just crash app, not whole system)

Reimplement BoxLayout (now Box)

What's missing:

  • Keep focus position (for Sidebar)
  • Change default focus, to be a parameter of addView(View* bool defaultFocus), a method on its own setDefaultFocus and an XML attribute referencing the default view by ID (defaultFocus="my/id" on the box, my/id being one of the child views). Don't use index anymore.
  • Write a destructor and do a little asan run to make sure everything doesn't leak
  • Fix focus to take direction into account (LTR / RTL)

IDEA: Open Source Design System

How interested would you and other developers be on having a consistent design system working along with Borealis?

I started last year to build one, called Aurora Ds, but ended up stopping due to a couple of reasons.

You can check out the skeleton here, with a few elements borrowed from a few people for a quicker ramp up :P

The idea is to document and support all current and future Borealis components and layouts and simplify the work of developers and makers on bringing new apps to life.

Using figma with it's very permissive free tier, allows easy replication and building new UI's from components, that will be mapped to Borealis's code.

Eventually a plugin for figma could be built to export either themes or layouts, with it's simple plugin framework, or directly through API access. This is similar to what I already today with Diez Framework: https://diez.org/.

I think this could vastly simplify building in a very visual way and create richer experiences.
I also loved how attuned we are ๐Ÿ˜ , Aurora (design system) Borealis (UI library).

Question regarding license

I noticed that there is a COPYING file at the root of the project (which I presume is because of using skeleton from fincs/hybrid_app). Would it not be a better idea to move that to a separate folder like licenses/hybrid_app.license. Reason I ask this is because I got confused about two licenses being provided for the project and had to do some headscratching to figure why the zlib license was present for.

Reimplement ScrollView (now ScrollingFrame)

What's left:

  • Display a scroll bar
  • Horizontal scrolling
  • "Mouse wheel" scrolling method, like HOS has. Pressing down should act like a mouse wheel and scroll the content. Focus only changes when the next view is fully visible, otherwise it will scroll to make it visible. Please find a better name for this ๐Ÿ‘€

Reimplement dialogs

Dialogs should be easier to use now, with multiple ways to create them:

  • Prebuilt template with optional title / message / 1, 2 or 3 button for fast dialogs creation (what legacy has)
  • Prebuilt templates with optional title / custom content (from XML or programmatically) and buttons
  • Entirely custom dialog, so only custom content, no provided title or buttons
  • Etc...

The aim is for the dialogs to be super easy to use while allowing customization to various levels. Inheritance is your friend.

Reimplement MaterialIcon

This is a hairy one because I would like a way to treat Image and MaterialIcon the same way (and potentially more icons / images classes in the future).

The point is to add either an image or an icon in a button, applet frame header, etc... using the same method for both. That way we can swap one for the other without any trouble. The easy way would be to replace the image with a View* but I'm sure we can do better.

The MaterialIcon should not be reimplemented using Label as a base as it is overkill. It should use its own drawing method.

I would also love an abstraction layer for material icons to use a nice enum instead of an ugly char to identify an icon.

ViewStack with transition animations

Sometimes people want to make a transition of two views, without necessarily pushing a new activity. For instance you may want to change the content of an applet frame, while keeping the header and footer (or at least without animating them).

The ViewStack view should allow to stack multiple views, with an optional transition animation between pushs and pops (fade in / out, slide left / right, etc...). The choosen transition animation and "isTranslucent" flag of the view should tell what views can be drawn (all of them or only the top most one).

The behavior is the same as the activity stack so it should be generalized to both, as we also want to animate activity pushes / pops, see #112.

I would also like a StackAppletFrame that has a ViewStack as content, but also handles a title and icon stack, linked to the views stack. That is for convenience when using ViewStack inside AppletFrame.

CLion: Allocating an object of abstract class type 'brls::TabFrame' unimplemented pure virtual method 'draw' in 'TabFrame'

I've been trying to use Borealis with JetBrains's CLion IDE, but when I try creating a new TabFrame, CLion gives the following error:

image

Allocating an object of abstract class type 'brls::TabFrame' unimplemented pure virtual method 'draw' in 'TabFrame'

CLion uses CMake (specifically CMake 3.17 with the version of CLion that I'm using) to resolve all of the includes, and I do include Borealis in the CMakeLists.txt file, but I'm using a traditional Makefile to actually compile the code. The code does compile fine with make, but that error in CLion is annoying nonetheless. I'm using the latest beta version of CLion 2020.2.

Here's the full code:

#include <borealis.hpp>

int main() {
    brls::Logger::setLogLevel(brls::LogLevel::DEBUG);

    if (!brls::Application::init("Howl")) {
        brls::Logger::error("Failed to initialize Borealis application.");
        return EXIT_FAILURE;
    }

    brls::TabFrame *rootFrame = new brls::TabFrame();
}

And here's the CMakeLists.txt file (which, again, I don't actually use to compile the code with, but CLion uses it to resolve the includes):

cmake_minimum_required(VERSION 3.17)
project(HowlNX)

set(CMAKE_CXX_STANDARD 17)

include_directories($ENV{DEVKITARM}/include)
include_directories($ENV{DEVKITPRO}/libnx/include)
include_directories(borealis/library/include)

add_executable(HowlNX source/main.cpp)

Allow users to manage swkbdConfigSetKeySetDisableBitmask

Hello,
I think the borealis embedded swkbd is pretty cool.
unfortunately I'm using '/' for my project and this option is locked by default in borealis.

swkbdConfigSetKeySetDisableBitmask(&config, SwkbdKeyDisableBitmask_At | SwkbdKeyDisableBitmask_Percent | SwkbdKeyDisableBitmask_ForwardSlash | SwkbdKeyDisableBitmask_Backslash);

I would like to propose a PR, but since swkbd flags are only known by the SWITCH version,
I do not know how to properly implement this without altering the linux compatibility.
do you have any idea on how to proceed ?
thank you a lot

[Yoga] ScrollView inside ScrollView

I'd like to make a horizontal ScrollView, but there is the weird behaviour when I put ScrollView inside another one.

You can reproduce it by adding this into demo/components.xml
image

I'll try to understand what is going wrong, but maybe you'll realise it faster than me.

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.