Project

General

Profile

WTable is populated the widgets in the layout change size

Added by Pedro Vicente 11 months ago

I have an application that loads data into a WTable that is initially empty

At start , the widgets are layout as below

But when the WTable is populated the widgets in the layout change form (become much bigger, etc)

Is there a way to avoid this resizing , by code or CSS ?

available at

https://github.com/pedro-vicente/nostr_client_relay

in case you want to give it a try

CSS is


.yellow-box
{
    background-color: #FFE4C4;
    border: 1px solid black;
    margin-top: 1ex;
    margin-bottom: 1ex;
}

.table_messages td, .table_messages th 
{
  border: 1px solid #ddd;
  padding: 8px;
}

.table_messages tr:nth-child(even){background-color: #f2f2f2;}

.table_messages tr:hover {background-color: #ddd;}

code is


NostroApplication::NostroApplication(const Wt::WEnvironment& env)
  : WApplication(env), m_row(0)
{
  useStyleSheet("nostro.css");
  root()->setStyleClass("yellow-box");
  setTitle("Nostro");
  const int width = 500;

  auto container = std::make_unique<Wt::WContainerWidget>();
  auto box_main = container->setLayout(std::make_unique<Wt::WHBoxLayout>());
  auto box_left = box_main->addLayout(std::make_unique<Wt::WVBoxLayout>());
  auto box_right = box_main->addLayout(std::make_unique<Wt::WVBoxLayout>());

  /////////////////////////////////////////////////////////////////////////////////////////////////////
  //input, left
  /////////////////////////////////////////////////////////////////////////////////////////////////////

  std::string local = "localhost:8080/nostr";
  std::string uri = "relay.snort.social";

  box_left->addWidget(std::make_unique<Wt::WText>("Relay Uri"));
  m_edit_uri = box_left->addWidget(std::make_unique<Wt::WLineEdit>());
  m_edit_uri->setText(uri);
  m_edit_uri->setWidth(200);

  /////////////////////////////////////////////////////////////////////////////////////////////////////
  //radion buttons, select EVENT or REQ
  /////////////////////////////////////////////////////////////////////////////////////////////////////

  m_button_message = std::make_shared<Wt::WButtonGroup>();
  Wt::WRadioButton* button;
  button = box_left->addWidget(std::make_unique<Wt::WRadioButton>("Event"));
  button->setInline(true);
  m_button_message->addButton(button);
  button = box_left->addWidget(std::make_unique<Wt::WRadioButton>("Request"));
  button->setInline(true);
  m_button_message->addButton(button);
  m_button_message->setSelectedButtonIndex(0);

  /////////////////////////////////////////////////////////////////////////////////////////////////////
  //EVENT
  /////////////////////////////////////////////////////////////////////////////////////////////////////

  auto group_event = box_left->addWidget(std::make_unique<Wt::WGroupBox>("Event"));

  group_event->addWidget(std::make_unique<Wt::WText>("Public Key"));
  group_event->addWidget(std::make_unique<Wt::WBreak>());
  m_edit_key = group_event->addWidget(std::make_unique<Wt::WLineEdit>());
  m_edit_key->setWidth(width);
  group_event->addWidget(std::make_unique<Wt::WBreak>());

  group_event->addWidget(std::make_unique<Wt::WText>("Content"));
  group_event->addWidget(std::make_unique<Wt::WBreak>());

  m_area_content = group_event->addWidget(std::make_unique<Wt::WTextArea>());
  m_area_content->setInline(false);
  m_area_content->setColumns(80);
  m_area_content->resize(Wt::WLength::Auto, 100);

  /////////////////////////////////////////////////////////////////////////////////////////////////////
  //REQ
  /////////////////////////////////////////////////////////////////////////////////////////////////////

  auto group_request = box_left->addWidget(std::make_unique<Wt::WGroupBox>("Request"));

  group_request->addWidget(std::make_unique<Wt::WText>("Event id"));
  group_request->addWidget(std::make_unique<Wt::WBreak>());
  m_edit_event_id = group_request->addWidget(std::make_unique<Wt::WLineEdit>());
  m_edit_event_id->setWidth(width);
  group_request->addWidget(std::make_unique<Wt::WBreak>());

  /////////////////////////////////////////////////////////////////////////////////////////////////////
  //generated message
  /////////////////////////////////////////////////////////////////////////////////////////////////////

  box_left->addWidget(std::make_unique<Wt::WText>("Message"));

  m_area_input = box_left->addWidget(std::make_unique<Wt::WTextArea>());
  m_area_input->setInline(false);
  m_area_input->setColumns(100);
  m_area_input->resize(Wt::WLength::Auto, 200);
  m_area_input->setFocus();

  box_left->addWidget(std::make_unique<Wt::WBreak>());

  /////////////////////////////////////////////////////////////////////////////////////////////////////
  //buttons
  /////////////////////////////////////////////////////////////////////////////////////////////////////

  auto hbox_buttons = box_left->addLayout(std::make_unique<Wt::WHBoxLayout>());
  auto button_gen = hbox_buttons->addWidget(std::make_unique<Wt::WPushButton>("Generate message"));
  auto button_send = hbox_buttons->addWidget(std::make_unique<Wt::WPushButton>("Send message"));

  /////////////////////////////////////////////////////////////////////////////////////////////////////
  //output, right
  /////////////////////////////////////////////////////////////////////////////////////////////////////

  m_table_messages = box_right->addWidget(std::make_unique<Wt::WTable>());;
  m_table_messages->resize(1000, Wt::WLength::Auto);
  m_table_messages->setStyleClass("table_messages");

  button_send->clicked().connect(this, &NostroApplication::send_message);
  button_gen->clicked().connect(this, &NostroApplication::make_message);
  root()->addWidget(std::move(container));
}

Replies (3)

RE: WTable is populated the widgets in the layout change size - Added by Pedro Vicente 11 months ago

The attached 2 images show the effect, before and after

As can be seen the 2 buttons become very large in size (it seems it depends on the table size)

RE: WTable is populated the widgets in the layout change size - Added by Pedro Vicente 11 months ago

After reading this article

https://www.webtoolkit.eu/wt/doc/reference/html/overview.html#containers

found out that layout managers are a bad way to align containers, CSS is the way to go

the div can be aligned as columns

CSS


.row 
{
  display: grid;
  grid-auto-flow: column;
  border: 2px outset red;
  background-color: lightblue;
}

.col 
{
  border: solid;
  background-color: darkgrey;
}

code


auto container_row = container->addWidget(std::make_unique<Wt::WContainerWidget>());
container_row->setStyleClass("row");

auto group_event = container_row->addWidget(std::make_unique<Wt::WGroupBox>("Event"));
group_event->setStyleClass("col");

Untitled.png (412 KB) Untitled.png with CSS

RE: WTable is populated the widgets in the layout change size - Added by Matthias Van Ceulebroeck 11 months ago

Hi Pedro,

layout managers are not necessarily a bad to to align containers. it really depends on your use case. But to make it customizable, you indeed should add some CSS.

Your specific case happens because you put the table and the input form in the same WHBoxLayout. So, when the WTable on the right grows, the content on the left tries to match the height of the WTable. It will stretch its content to fit the same height as the WTable.
You can solve this for example by putting a max_height on box_left in your CSS.


Alternatively for more complex layouts you can take a look at WTemplate. This allows you to template your HTML. For example you could have the template content like:

<div>
  <div class="left-side">
    ${event}
    ${request}
    ${message}
  </div>
  <div class="right-side">
    ${table}
  </div>
</div>
.left-side, .right-side {
  width: 50%;
}
.left-side {
  float:left
}
.right-side {
  float:left
}

Then in your CSS code you can do

auto group_request = template->bindNew<Wt::WGroupBox>("event", "Event")

Personally I find that easier to manage complexer layouts, since otherwise you can eventually have way too much layouts/containers to keep a decent overview.

Best,
Matthias

    (1-3/3)