diff --git a/.travis.yml b/.travis.yml index 82604edf..0629aeb6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -53,15 +53,15 @@ install: - /tmp/tools/cmake --prefix="$HOME" --exclude-subdir before_script : - # travis don't have a physical monitor. We need to install an emulator: https://docs.travis-ci.com/user/gui-and-headless-browsers/ - - "export DISPLAY=:99.0" - - "sh -e /etc/init.d/xvfb start" - - sleep 3 # give xvfb some time to start # we have: qPCR4vir/nana/../nana-demo and now we are in: qPCR4vir/nana/ our executable tests will access: ../nana-demo/Examples/*.bmp etc.(need to be in parallel with nana-demo/Examples) #- cd ../nana-demo - mkdir demo-build - cd demo-build +services: + - # travis don't have a physical monitor. We need to install an emulator: https://docs.travis-ci.com/user/gui-and-headless-browsers/ + - xvfb + script: - cmake -G"Unix Makefiles" ../nana-demo -DCMAKE_INSTALL_PREFIX=.. -DNANA_CMAKE_ENABLE_JPEG=ON -DNANA_CMAKE_FIND_BOOST_FILESYSTEM=OFF -DNANA_CMAKE_AUTOMATIC_GUI_TESTING=ON -DNANA_CMAKE_INSTALL=OFF - make install diff --git a/build/cmake/install_nana.cmake b/build/cmake/install_nana.cmake index 45636484..7c949646 100644 --- a/build/cmake/install_nana.cmake +++ b/build/cmake/install_nana.cmake @@ -1,4 +1,4 @@ -option(NANA_CMAKE_INSTALL "Install nana when compile the library (to be consumed without cmake)" ON) +option(NANA_CMAKE_INSTALL "Install nana after compiling the library (to be consumed WITHOUT cmake!!)" OFF) # Install the include directories too. if(NANA_CMAKE_INSTALL) @@ -6,8 +6,11 @@ if(NANA_CMAKE_INSTALL) # Is your responsability to ensure all compiler options are compatible with the compilation # of the project linking to the nana lib here generated target_sources(nana PRIVATE ${HEADERS}) - target_include_directories(nana PRIVATE ${NANA_INCLUDE_DIR}) message("The compiled Nana library will be installed in ${CMAKE_INSTALL_PREFIX}/lib") + message("WARNING !!! You are using the 'installed' nana! Not recommended! ") + message("If this was not your intention, please tern OFF option NANA_CMAKE_INSTALL ") + message("for example by adding: -DNANA_CMAKE_INSTALL=OFF to your call to cmake. ") + # Actually in DESTDIR/CMAKE_INSTALL_PREFIX/lib but in windows there is no DESTDIR/ part. install(TARGETS nana ARCHIVE DESTINATION lib @@ -15,8 +18,13 @@ if(NANA_CMAKE_INSTALL) RUNTIME DESTINATION bin) install(DIRECTORY ${NANA_INCLUDE_DIR}/nana DESTINATION include) # in ${CMAKE_INSTALL_PREFIX}/include/nana message("The Nana include files will be installed in ${CMAKE_INSTALL_PREFIX}/include") + target_include_directories(nana PUBLIC $ + $ ) else() # this is the prefered method to consume nana with cmake + message("You are using nana directly from original sources. (Recommended!) " + "If this was not your intention, and what you want is to install precomplied nana first, then " + "please tern ON option NANA_CMAKE_INSTALL ") target_sources(nana PUBLIC ${HEADERS}) target_include_directories(nana PUBLIC ${NANA_INCLUDE_DIR}) endif() diff --git a/include/nana/gui/detail/widget_geometrics.hpp b/include/nana/gui/detail/widget_geometrics.hpp index d172536e..91cdff6c 100644 --- a/include/nana/gui/detail/widget_geometrics.hpp +++ b/include/nana/gui/detail/widget_geometrics.hpp @@ -17,7 +17,8 @@ #include namespace nana { - class color_proxy + /// a tool to share and set a color common to many uses + class color_proxy { public: color_proxy(const color_proxy&); @@ -38,6 +39,7 @@ namespace nana std::shared_ptr color_; };//end namespace color_proxy + /// define common color and geometrical properties struct widget_geometrics { virtual ~widget_geometrics() = default; diff --git a/include/nana/gui/msgbox.hpp b/include/nana/gui/msgbox.hpp index c67795f6..5b822194 100644 --- a/include/nana/gui/msgbox.hpp +++ b/include/nana/gui/msgbox.hpp @@ -1,13 +1,13 @@ -/* +/** * A Message Box Class * Nana C++ Library(http://www.nanapro.org) -* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com) +* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) * -* @file: nana/gui/msgbox.hpp +* @file nana/gui/msgbox.hpp */ #ifndef NANA_GUI_MSGBOX_HPP @@ -81,8 +81,8 @@ namespace nana return *this; } - /// \brief Displays the message that buffered in the stream. - /// @return, the button that user clicked. + /// \brief Displays the message buffered in the stream. + /// @return, the button the user clicked. pick_t show() const; /// A function object method alternative to show() @@ -98,6 +98,9 @@ namespace nana icon_t icon_; }; + /// Simple convenience dialog to get values from the user. + /// + /// The input value can be a boolean, string, a number, an option from a dropdown list or a date. class inputbox { struct abstract_content @@ -110,6 +113,8 @@ namespace nana }; public: + + /// Shows a checkbox for boolean input class boolean : public abstract_content { @@ -128,6 +133,7 @@ namespace nana std::unique_ptr impl_; }; + /// Integer input class integer : public abstract_content { @@ -146,6 +152,7 @@ namespace nana std::unique_ptr impl_; }; + /// Floating-point number input. class real : public abstract_content { @@ -164,6 +171,7 @@ namespace nana std::unique_ptr impl_; }; + /// String input or an option from a dropdown list. class text : public abstract_content { @@ -192,6 +200,7 @@ namespace nana std::unique_ptr impl_; }; + /// Date input class date : public abstract_content { @@ -214,6 +223,10 @@ namespace nana std::unique_ptr impl_; }; + /// Path of a file. + /// + /// The path requires an object of filebox. When the user clicks the `Browse` button, + /// it invokes the filebox with proper configurations to query a filename. class path : public abstract_content { @@ -231,11 +244,26 @@ namespace nana std::unique_ptr impl_; }; - inputbox(window, ::std::string description, ::std::string title = ::std::string()); + inputbox(window owner, ///< A handle to an owner window (just a parent form or widget works) + ::std::string description, ///< tells users what the purpose for the input. It can be a formatted-text. + ::std::string title = ::std::string() ///< The title for the inputbox. + ); - void image(::nana::paint::image, bool is_left, const rectangle& valid_area = {}); - void image_v(::nana::paint::image, bool is_top, const rectangle& valid_area = {}); + /// shows images at left/right side of inputbox + void image(::nana::paint::image image, ///< The image + bool is_left, ///< true to place the image at left side, false to the right side + const rectangle& valid_area = {} ///< The area of the image to be displayed + ); + /// shows images at top/bottom side of inputbox + void image_v(::nana::paint::image, ///< The image + bool is_top, ///< `true` to place the image at top side, `false` at bottom side + const rectangle& valid_area = {} ///< The area of the image to be displayed + ); + + /// Shows the inputbox and wait for the user input. + /// + /// This method shows the inputbox without preventing the user interacts with other windows. template bool show(Args&& ... args) { @@ -251,7 +279,11 @@ namespace nana return _m_open(contents, false); } - template + /// Shows the inputbox and wait for the user input blocking other windows. + /// + /// This method blocks the execution and prevents user interaction with other + /// windows until the inputbox is closed. + template bool show_modal(Args&& ... args) { std::vector contents; @@ -267,7 +299,7 @@ namespace nana return _m_open(contents, true); } - /// Sets a verifier to verify the user input. + /// Sets a verifier to verify the user input, taking a handle to the inputbox. void verify(std::function verifier); /** Sets the minimum width for the entry fields diff --git a/include/nana/gui/widgets/widget.hpp b/include/nana/gui/widgets/widget.hpp index fe8fe543..ce46843a 100644 --- a/include/nana/gui/widgets/widget.hpp +++ b/include/nana/gui/widgets/widget.hpp @@ -7,7 +7,7 @@ * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) * - * @file: nana/gui/widgets/widget.hpp + * @file nana/gui/widgets/widget.hpp */ #ifndef NANA_GUI_WIDGET_HPP @@ -48,8 +48,8 @@ namespace nana widget() = default; virtual ~widget() = default; - virtual window handle() const = 0; ///< Returns the handle of window, returns 0 if window is not created. - bool empty() const; ///< Determines whether the manipulator is handling a window. + virtual window handle() const = 0; ///< Returns the handle of window, returns 0 if window is not created. + bool empty() const; ///< Determines whether the manipulator is handling a window. void close(); window parent() const; @@ -169,9 +169,17 @@ namespace nana }; } - /// Base class of all the classes defined as a widget window. Defaultly a widget_tag - template::value>::type> //type DrawerTrigger must be derived from nana::drawer_trigger + /// Base class of all the classes defined as a widget window. Defaultly a widget_tag + /// + /// \tparam Category + /// \tparam DrawerTrigger must be derived from nana::drawer_trigger + /// \tparam Events + /// \tparam Scheme + template::value>::type> class widget_object: public detail::widget_base { protected: @@ -293,8 +301,13 @@ namespace nana std::unique_ptr scheme_; };//end class widget_object - /// Base class of all the classes defined as a non-graphics-buffer widget window. The second template parameter DrawerTrigger is always ignored.\see nana::panel - template //type DrawerTrigger must be derived from nana::drawer_trigger + /// Base class of all the classes defined as a non-graphics-buffer widget window. + /// + /// The second template parameter DrawerTrigger is always ignored.\see nana::panel + /// type DrawerTrigger must be derived from nana::drawer_trigger + template class widget_object: public detail::widget_base { protected: @@ -359,8 +372,14 @@ namespace nana };//end class widget_object - /// Base class of all the classes defined as a root window. \see nana::form - template //type DrawerTrigger must be derived from nana::drawer_trigger + /// Base class of all the classes defined as a root window. \see nana::form + /// + /// \tparam DrawerTrigger must be derived from nana::drawer_trigger + /// \tparam Events + /// \tparam Scheme + template class widget_object: public detail::widget_base { protected: diff --git a/source/gui/msgbox.cpp b/source/gui/msgbox.cpp index 9d0467d0..4d4ffc36 100644 --- a/source/gui/msgbox.cpp +++ b/source/gui/msgbox.cpp @@ -1,4 +1,4 @@ -/* +/** * A Message Box Class * Nana C++ Library(http://www.nanapro.org) * Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com) @@ -7,10 +7,15 @@ * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) * - * @file: nana/gui/msgbox.hpp + * @file nana/gui/msgbox.hpp * @Contributors * James Bremner + * Ariel Vina-Rodriguez */ +#define NOMINMAX +#include // max +#include +#include //include std::abs #include #include @@ -27,8 +32,7 @@ #include #include #include -#include -#include //include std::abs + #if defined(NANA_WINDOWS) #include #elif defined(NANA_X11) @@ -494,21 +498,29 @@ namespace nana //end class msgbox - //class inputbox + //class inputbox todo: add schema class inputbox_window : public ::nana::form { public: - inputbox_window(window owner, paint::image (&imgs)[4], ::nana::rectangle (&valid_areas)[4], const ::std::string & desc, const ::std::string& title, std::size_t contents, unsigned fixed_pixels, const std::vector& each_height) + inputbox_window(window owner, + paint::image (&imgs)[4], ///< 4 ref to images + ::nana::rectangle (&valid_areas)[4], + const ::std::string & description, + const ::std::string& title, + std::size_t contents, + unsigned fixed_pixels, + const std::vector& each_height) + : form(owner, API::make_center(owner, 500, 300), appear::decorate<>()) { - throw_not_utf8(desc); + throw_not_utf8(description); throw_not_utf8(title); - desc_.create(*this); - desc_.format(true).caption(desc); - auto desc_extent = desc_.measure(470); + description_.create(*this); + description_.format(true).caption(description); + auto description_size = description_.measure(470); btn_ok_.create(*this); btn_ok_.i18n(i18n_eval("NANA_BUTTON_OK")); @@ -527,32 +539,26 @@ namespace nana close(); }); - unsigned height = 20 + desc_extent.height + 10 + 38; - + unsigned height = 20 + description_size.height + 10 + 38; std::stringstream ss_content; - ss_content << " 27) - px = each_height[i]; + unsigned px = std::max(27u, each_height[i]); - ss_content << ""; + ss_content << ""; - height += px + 1; + height += px + 3; } - ss_content << ">>>"; - - if (desc_extent.width < 200) - desc_extent.width = 200; + if (description_size.width < 200) + description_size.width = 200; //Make sure the complete display of input extent - if (desc_extent.width < fixed_pixels) - desc_extent.width = fixed_pixels; + if (description_size.width < fixed_pixels) + description_size.width = fixed_pixels; - desc_extent.width += 20; + description_size.width += 20; // 2x margin 10 ::nana::size img_sz[4]; @@ -566,8 +572,9 @@ namespace nana } else sz = imgs[2].size(); - sz.width = static_cast(double(sz.width) * (double(height) / double(sz.height))); - desc_extent.width += sz.width; + const double scale_factor = double(height) / double(sz.height); + sz.width = static_cast(double(sz.width) * scale_factor); + description_size.width += sz.width; } if (imgs[3]) //Right @@ -581,7 +588,7 @@ namespace nana else sz = imgs[3].size(); sz.width = static_cast(double(sz.width) * (double(height) / double(sz.height))); - desc_extent.width += sz.width; + description_size.width += sz.width; } if (imgs[0]) //Top @@ -594,7 +601,8 @@ namespace nana } else sz = imgs[0].size(); - sz.height = static_cast(double(sz.height) * (double(desc_extent.width) / double(sz.width))); + const double scale_factor = double(description_size.width) / double(sz.width); + sz.height = static_cast(double(sz.height) * scale_factor ); height += sz.height; } @@ -608,16 +616,28 @@ namespace nana } else sz = imgs[1].size(); - sz.height = static_cast(double(sz.height) * (double(desc_extent.width) / double(sz.width))); + const double scale_factor = double(description_size.width) / double(sz.width); + sz.height = static_cast(double(sz.height) * scale_factor); height += sz.height; } std::stringstream ss; - ss << "vert<"<>"; + ss << "vert< img_top height="<" + <<" << img_left width=" <" + <<" " // added height: 2x10 + <<" " + <<" " + <<" >>" // added height: 38 + <<" < img_right width=" <>< img_bottom height="<"; + + // added height: 10 x3 = 30 + 38 auto& place = this->get_place(); place.div(ss.str().c_str()); - place["desc"] << desc_; + place["description"] << description_; place["buttons"] << btn_ok_ << btn_cancel_; const char * img_fields[4] = {"img_top", "img_bottom", "img_left", "img_right"}; @@ -635,7 +655,7 @@ namespace nana place.field_display(img_fields[i], imgs[i]); } - move(API::make_center(this->owner(), desc_extent.width, height)); + move(API::make_center(this->owner(), description_size.width, height)); caption(title); } @@ -659,7 +679,7 @@ namespace nana return valid_input_; } private: - ::nana::label desc_; + ::nana::label description_; ::nana::button btn_ok_; ::nana::button btn_cancel_; bool valid_input_{ false }; diff --git a/source/gui/widgets/progress.cpp b/source/gui/widgets/progress.cpp index 49fbda99..fb727af1 100644 --- a/source/gui/widgets/progress.cpp +++ b/source/gui/widgets/progress.cpp @@ -96,11 +96,11 @@ namespace nana { if (widget_) { - auto value_px = (widget_->size().width - border_px * 2); + unsigned value_px = (widget_->size().width - border_px * 2); //avoid overflow if (unknown_ || (value_ < max_)) - value_px = static_cast(value_px * (double(value_) / double(max_))); + value_px = unsigned(double(value_px) * (double(value_) / double(max_))); if (value_px != value_px_) {