/* ** Copyright 2017-2021 Double Precision, Inc. ** See COPYING for distribution information. */ #include "config.h" #include <x/mpobj.H> #include <x/exception.H> #include <x/destroy_callback.H> #include <x/ref.H> #include <x/obj.H> #include <x/appid.H> #include <x/w/main_window.H> #include <x/w/label.H> #include <x/w/gridlayoutmanager.H> #include <x/w/gridfactory.H> #include <x/w/progressbar.H> #include "close_flag.H" #include <string> #include <iostream> std::string x::appid() noexcept { return "progressbar.examples.w.libcxx.com"; } // Create the progress bar. static auto initialize_progressbar(const x::w::factory &f) { // progressbar_config is an optional parameter to create_progressbar(). // // It provides the progress bar's initial value and maximum value, // as well as a custom appearance object. x::w::progressbar_config config{0, 100}; auto pb=f->create_progressbar ([] (const x::w::progressbar &pb) { // We are creating the progress bar with the // grid layout manager. Put one element into the // progress bar, our label. auto glm=pb->gridlayout(); auto f=glm->append_row(); // Position the label centered, in the progress bar. f->halign(x::w::halign::center); f->create_label("0%")->show(); }, // Optional parameter: initial configuration config, // Optional parameter: the grid layout manager, by default. x::w::new_gridlayoutmanager{}); pb->show(); return pb; } void showprogressbar() { x::destroy_callback::base::guard guard; auto close_flag=close_flag_ref::create(); auto main_window=x::w::main_window ::create([] (const auto &main_window) { auto layout=main_window->gridlayout(); x::w::gridfactory factory= layout->append_row(); initialize_progressbar(factory); }); // Retrieve the progress bar, and the label elements from the newly- // created main_window. // Both the main window and the progress bar containers are grid // layout managers, with one display element: row 0, column 0. x::w::progressbar pb=main_window->gridlayout()->get(0, 0); x::w::label l=pb->gridlayout()->get(0, 0); main_window->set_window_title("Progress bar!"); guard(main_window->connection_mcguffin()); main_window->on_disconnect([] { exit(1); }); main_window->on_delete ([close_flag] (ONLY IN_THREAD, const auto &ignore) { close_flag->close(); }); main_window->show_all(); x::mpcobj<bool>::lock lock{close_flag->flag}; // Count the progress bar, and go away. int v=0; while (1) { lock.wait_for(std::chrono::milliseconds(500), [&] { return *lock; }); if (*lock) break; if (v >= 100) break; v += 5; // Update the progress bar to reflect the completion // percentage. // // It's up to us to update the label inside the progress bar. // We format "x%" ourselves, and update the label. // // Progress bar's update() method updates the progress bar's // visual slider. The third parameter to update() is an // optional closure. The closure parameter is an optimization // technique. // // Updating the label redraws it, and updating the // progress bar ends up redrawing the label again, to include // the slider that "slides" under the label. Passing a closure // to update() executes the closure and updates the progress // bar in one operation, redrawing the whole thing in one shot. std::ostringstream o; o << v << '%'; pb->update(v, 100, [txt=o.str(), l] (ONLY IN_THREAD) { l->update(txt); }); } } int main(int argc, char **argv) { try { showprogressbar(); } catch (const x::exception &e) { e->caught(); exit(1); } return 0; }
progressbar.C
uses
a factory's create_progressbar
()'s to
create a new progress bar, then creates a label inside it.
progressbar.C
then proceeds to count from 0 to 100.
At each step, progressbar.C
updates the label's
text to read “n%”, and calls the progress bar's
update
() method to draw the progress bar's
slider.
update
() takes two integer values, and an
optional closure. The total “progress” of the progress bar
ranges from 0 to maximum_value
(the 2nd parameter
to update
()) with value
(the 1st parameter) indicating the current level of progress.
Essentially, update
() draws the slider from
the left margin and up to value/maximum_value
of
the progress bar's width. Both the value
and
maximum_value
get updated by the same
update
().
Each update
() provides the same
maximum_value
, and an increasing
value
, but each update may specify a
different maximum_value
, and a higher or
a lower value
. The progress bar's slider
simply gets moved to the recalculated position.
A value of 0 does not show the slider at all, and slider covers the
entire width of the progress bar when both values are equal.
progressbar.C
also gives an example of using
the third, optional, update
() parameter,
for optimization purposes.