Git Product home page Git Product logo

Comments (8)

ArthurSonzogni avatar ArthurSonzogni commented on July 21, 2024

Hello @Biobots!

I am not totally sure of what you want. Let me present the two potential solution:

static dom (non interactive)

You can use:

auto document = hbox(paragraph(long_string))
  • hflow implements the flow layout.
  • the helper function paragraph helps breaking a long string into a list of words.

Try with the example:
https://arthursonzogni.com/FTXUI/doc/_2examples_2dom_2paragraph_8cpp-example.html#a3

interactive component (using keyboard)

I don't have anything built-in.
Here is an example you can adapt:
https://github.com/ArthurSonzogni/chrome-log-beautifier/blob/master/src/ui/log_displayer.cpp#L28

Selected parts:

Element LogDisplayer::RenderLines(const std::vector<std::string>& lines) {
    Elements list;

    for (auto& line : lines) {
      Decorator line_decorator =  nothing;
      if (index++ == selected_) {
        if (Focused())
          line_decorator = focus | inverted;
        else
          line_decorator = focus;
      }
      list.push_back(text(line) | line_decorator)
   }
   return vbox(std::move(list)) | frame | border;
}

bool LogDisplayer::OnEvent(Event event) {
  if (!Focused())
    return false;

  int old_selected = selected_;
  if (event == Event::ArrowUp || event == Event::Character('k'))
    selected_--;
  if (event == Event::ArrowDown || event == Event::Character('j'))
    selected_++;
  if (event == Event::Tab && size)
    selected_ = (selected_ + 1) % size;
  if (event == Event::TabReverse && size)
    selected_ = (selected_ + size - 1) % size;

  selected_ = std::max(0, std::min(size-1, selected_));

  if (selected_ != old_selected) {
    return true;
  }

  return false;
}

from ftxui.

b1060t avatar b1060t commented on July 21, 2024

@ArthurSonzogni Thanks a lot! I'm trying the second solution now. However. there's another problem. It seems that in interactive mode, the 'render()' function is only called when there are some keyboard input. Is it possible to render the screen at a fixed speed like 30FPS since the output log should be automatically updated?

My logger's render function is called by logger.RenderLog() which is defined as:

class LogDisplayer : public Component
{
private:
	vector<string> _payload;
public:
	LogDisplayer() = default;
	void getLog(string str)
	{
		istringstream ss(str);
		string tmp;
		while(getline(ss, tmp))
		{
			_payload.push_back(tmp);
		}
	}
	Element RenderLog()
	{
		Elements list;
		for(int i = _payload.size() - 13; i < _payload.size(); i++)
		{
			Element doc = hbox({
				text(buildwstring(_payload[i])),
			}) | flex;
			list.push_back(doc);
		}
		if(list.empty()) list.push_back(text(L"empty"));
		return window(text(L"test"), vbox(list) | flex);
	}
};

from ftxui.

ArthurSonzogni avatar ArthurSonzogni commented on July 21, 2024

You can post custom event using PostEvent and a Event::Custom. Those will refresh the view.

You usually want to send them after you know some data have been added. However, I guess in your case you are not actively waiting, but are checking periodically if there are updates. In this case, I guess you can create a new thread that will periodically send such events.

  std::thread update([&screen]() {
    for (;;) {
      using namespace std::chrono_literals;
      std::this_thread::sleep_for(0.05s);
      screen.PostEvent(Event::Custom);
    }
  });

From the example:

std::thread update([&screen]() {

from ftxui.

b1060t avatar b1060t commented on July 21, 2024

Actually I evoked a new thread to keep query for log needed. By adding PostEvent, it indeed worked as I expected.

system("clear");
auto screen = ScreenInteractive::FixedSize(100, 30);
MainWindow component;

thread t([&](){
	AsyncCommand cmd(std::string("logcat"));
	cmd.execute();
	while(!cmd.isDone())
	{
		string log = cmd.getOutput();
		if(log.length() > 0)
		{
			component.getLog(log);
			screen.PostEvent(Event::Custom);
		}
	}
});
t.detach();

screen.Loop(&component);

However, another problem I've met is that it's a bit unconvenient when the length of a sentence is greater than the maximum width of the screen. Though this can be implemented by the user, I'm still wondering if you are considering adding a built-in textarea which can automatically increase its height when there's not enough space to show one sentence without line break.

from ftxui.

ArthurSonzogni avatar ArthurSonzogni commented on July 21, 2024

The difficulty is:
The children pass their Requirement to their parent:

Requirement requirement() { return requirement_; }

Then the parent give them a Box where they are allowed to draw themselves.

virtual void SetBox(Box box);

For the hflow layout, it is very difficult to provide a Requirement. Because the dependencies are inversed. We need to know the parent's final width to determine the children required height.
For now, the hflow layout just require a 1x1 pixel to draw itself and declare themselves to be happy about being expanded if possible:

void ComputeRequirement() override {

I regret I don't have something built-in for this use case.

from ftxui.

b1060t avatar b1060t commented on July 21, 2024

Thanks! Another question:

This is how I define the movement of the window:

bool OnEvent(Event e)
{
	if(!Focused()) return false;

	if(e == Event::ArrowUp) _yoffset++;
	if(e == Event::ArrowDown) _yoffset--;
	if(e == Event::ArrowRight) _xoffset++;
	if(e == Event::ArrowLeft) _xoffset--;

	return true;
}

Once the component I defined is activated, I can never focus to the other part of the screen. I also tried hjkl to define the movement, but the the focused component still stays fixed using the arrow button.

from ftxui.

ArthurSonzogni avatar ArthurSonzogni commented on July 21, 2024

I guess it depends on which component contains your component.

When the parent receives an event, it:

  1. Check if the active child can process the event. If yes, return.
  2. Process the event itself, which likely make the active child to become the next one.

Your component, as a children seems to accept any event.

See for instance the default implementation Container, which is used in most built-in component:

bool Container::OnEvent(Event event) {

bool Container::OnEvent(Event event) {
  if (!Focused())
    return false;

  if (ActiveChild() && ActiveChild()->OnEvent(event))
    return true;

  return (this->*event_handler_)(event);
}

I guess in your case:

(ActiveChild() && ActiveChild()->OnEvent(event))

is always true when the ActiveChild() is your component.

Then this->*event_handler_ is never called. So the current ActiveChild stays the same.

from ftxui.

b1060t avatar b1060t commented on July 21, 2024

Thanks. It seems that my OnEvent function is always returning true once focused. After fixing that, I'm able to enter the other component.

from ftxui.

Related Issues (20)

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.