Merge branch 'qPCR4vir-patch-2' into hotfix-1.7.2

This commit is contained in:
Jinhao 2019-08-05 04:14:42 +08:00
commit 5f49e1f12f
7 changed files with 144 additions and 63 deletions

View File

@ -53,15 +53,15 @@ install:
- /tmp/tools/cmake --prefix="$HOME" --exclude-subdir - /tmp/tools/cmake --prefix="$HOME" --exclude-subdir
before_script : 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) # 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 #- cd ../nana-demo
- mkdir demo-build - mkdir demo-build
- cd 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: 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 - 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 - make install

View File

@ -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. # Install the include directories too.
if(NANA_CMAKE_INSTALL) 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 # Is your responsability to ensure all compiler options are compatible with the compilation
# of the project linking to the nana lib here generated # of the project linking to the nana lib here generated
target_sources(nana PRIVATE ${HEADERS}) 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("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. # Actually in DESTDIR/CMAKE_INSTALL_PREFIX/lib but in windows there is no DESTDIR/ part.
install(TARGETS nana install(TARGETS nana
ARCHIVE DESTINATION lib ARCHIVE DESTINATION lib
@ -15,8 +18,13 @@ if(NANA_CMAKE_INSTALL)
RUNTIME DESTINATION bin) RUNTIME DESTINATION bin)
install(DIRECTORY ${NANA_INCLUDE_DIR}/nana DESTINATION include) # in ${CMAKE_INSTALL_PREFIX}/include/nana 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") message("The Nana include files will be installed in ${CMAKE_INSTALL_PREFIX}/include")
target_include_directories(nana PUBLIC $<BUILD_INTERFACE:${NANA_INCLUDE_DIR}>
$<INSTALL_INTERFACE:include> )
else() else()
# this is the prefered method to consume nana with cmake # 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_sources(nana PUBLIC ${HEADERS})
target_include_directories(nana PUBLIC ${NANA_INCLUDE_DIR}) target_include_directories(nana PUBLIC ${NANA_INCLUDE_DIR})
endif() endif()

View File

@ -17,6 +17,7 @@
#include <memory> #include <memory>
namespace nana namespace nana
{ {
/// a tool to share and set a color common to many uses
class color_proxy class color_proxy
{ {
public: public:
@ -38,6 +39,7 @@ namespace nana
std::shared_ptr<color> color_; std::shared_ptr<color> color_;
};//end namespace color_proxy };//end namespace color_proxy
/// define common color and geometrical properties
struct widget_geometrics struct widget_geometrics
{ {
virtual ~widget_geometrics() = default; virtual ~widget_geometrics() = default;

View File

@ -1,13 +1,13 @@
/* /**
* A Message Box Class * A Message Box Class
* Nana C++ Library(http://www.nanapro.org) * 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. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt) * http://www.boost.org/LICENSE_1_0.txt)
* *
* @file: nana/gui/msgbox.hpp * @file nana/gui/msgbox.hpp
*/ */
#ifndef NANA_GUI_MSGBOX_HPP #ifndef NANA_GUI_MSGBOX_HPP
@ -81,8 +81,8 @@ namespace nana
return *this; return *this;
} }
/// \brief Displays the message that buffered in the stream. /// \brief Displays the message buffered in the stream.
/// @return, the button that user clicked. /// @return, the button the user clicked.
pick_t show() const; pick_t show() const;
/// A function object method alternative to show() /// A function object method alternative to show()
@ -98,6 +98,9 @@ namespace nana
icon_t icon_; 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 class inputbox
{ {
struct abstract_content struct abstract_content
@ -110,6 +113,8 @@ namespace nana
}; };
public: public:
/// Shows a checkbox for boolean input
class boolean class boolean
: public abstract_content : public abstract_content
{ {
@ -128,6 +133,7 @@ namespace nana
std::unique_ptr<implement> impl_; std::unique_ptr<implement> impl_;
}; };
/// Integer input
class integer class integer
: public abstract_content : public abstract_content
{ {
@ -146,6 +152,7 @@ namespace nana
std::unique_ptr<implement> impl_; std::unique_ptr<implement> impl_;
}; };
/// Floating-point number input.
class real class real
: public abstract_content : public abstract_content
{ {
@ -164,6 +171,7 @@ namespace nana
std::unique_ptr<implement> impl_; std::unique_ptr<implement> impl_;
}; };
/// String input or an option from a dropdown list.
class text class text
: public abstract_content : public abstract_content
{ {
@ -192,6 +200,7 @@ namespace nana
std::unique_ptr<implement> impl_; std::unique_ptr<implement> impl_;
}; };
/// Date input
class date class date
: public abstract_content : public abstract_content
{ {
@ -214,6 +223,10 @@ namespace nana
std::unique_ptr<implement> impl_; std::unique_ptr<implement> 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 class path
: public abstract_content : public abstract_content
{ {
@ -231,11 +244,26 @@ namespace nana
std::unique_ptr<implement> impl_; std::unique_ptr<implement> 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 = {}); /// shows images at left/right side of inputbox
void image_v(::nana::paint::image, bool is_top, const rectangle& valid_area = {}); 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<typename ...Args> template<typename ...Args>
bool show(Args&& ... args) bool show(Args&& ... args)
{ {
@ -251,6 +279,10 @@ namespace nana
return _m_open(contents, false); return _m_open(contents, false);
} }
/// 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<typename ...Args> template<typename ...Args>
bool show_modal(Args&& ... args) bool show_modal(Args&& ... args)
{ {
@ -267,7 +299,7 @@ namespace nana
return _m_open(contents, true); 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<bool(window)> verifier); void verify(std::function<bool(window)> verifier);
/** Sets the minimum width for the entry fields /** Sets the minimum width for the entry fields

View File

@ -7,7 +7,7 @@
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt) * 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 #ifndef NANA_GUI_WIDGET_HPP
@ -170,8 +170,16 @@ namespace nana
} }
/// Base class of all the classes defined as a widget window. Defaultly a widget_tag /// Base class of all the classes defined as a widget window. Defaultly a widget_tag
template<typename Category, typename DrawerTrigger, typename Events = ::nana::general_events, typename Scheme = ::nana::widget_geometrics, ///
typename = typename std::enable_if<std::is_base_of<::nana::drawer_trigger, DrawerTrigger>::value>::type> //type DrawerTrigger must be derived from nana::drawer_trigger /// \tparam Category
/// \tparam DrawerTrigger must be derived from nana::drawer_trigger
/// \tparam Events
/// \tparam Scheme
template<typename Category,
typename DrawerTrigger,
typename Events = ::nana::general_events,
typename Scheme = ::nana::widget_geometrics,
typename = typename std::enable_if<std::is_base_of<::nana::drawer_trigger, DrawerTrigger>::value>::type>
class widget_object: public detail::widget_base class widget_object: public detail::widget_base
{ {
protected: protected:
@ -293,8 +301,13 @@ namespace nana
std::unique_ptr<scheme_type> scheme_; std::unique_ptr<scheme_type> scheme_;
};//end class widget_object };//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 /// Base class of all the classes defined as a non-graphics-buffer widget window.
template<typename DrawerTrigger, typename Events, typename Scheme> //type DrawerTrigger must be derived from nana::drawer_trigger ///
/// The second template parameter DrawerTrigger is always ignored.\see nana::panel
/// type DrawerTrigger must be derived from nana::drawer_trigger
template<typename DrawerTrigger,
typename Events,
typename Scheme>
class widget_object<category::lite_widget_tag, DrawerTrigger, Events, Scheme>: public detail::widget_base class widget_object<category::lite_widget_tag, DrawerTrigger, Events, Scheme>: public detail::widget_base
{ {
protected: protected:
@ -360,7 +373,13 @@ namespace nana
/// Base class of all the classes defined as a root window. \see nana::form /// Base class of all the classes defined as a root window. \see nana::form
template<typename DrawerTrigger, typename Events, typename Scheme> //type DrawerTrigger must be derived from nana::drawer_trigger ///
/// \tparam DrawerTrigger must be derived from nana::drawer_trigger
/// \tparam Events
/// \tparam Scheme
template<typename DrawerTrigger,
typename Events,
typename Scheme>
class widget_object<category::root_tag, DrawerTrigger, Events, Scheme>: public detail::widget_base class widget_object<category::root_tag, DrawerTrigger, Events, Scheme>: public detail::widget_base
{ {
protected: protected:

View File

@ -1,4 +1,4 @@
/* /**
* A Message Box Class * A Message Box Class
* Nana C++ Library(http://www.nanapro.org) * Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com) * Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
@ -7,10 +7,15 @@
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt) * http://www.boost.org/LICENSE_1_0.txt)
* *
* @file: nana/gui/msgbox.hpp * @file nana/gui/msgbox.hpp
* @Contributors * @Contributors
* James Bremner * James Bremner
* Ariel Vina-Rodriguez
*/ */
#define NOMINMAX
#include <algorithm> // max
#include <functional>
#include <cstdlib> //include std::abs
#include <nana/gui/compact.hpp> #include <nana/gui/compact.hpp>
#include <nana/gui/msgbox.hpp> #include <nana/gui/msgbox.hpp>
@ -27,8 +32,7 @@
#include <nana/datetime.hpp> #include <nana/datetime.hpp>
#include <nana/internationalization.hpp> #include <nana/internationalization.hpp>
#include <nana/gui/filebox.hpp> #include <nana/gui/filebox.hpp>
#include <functional>
#include <cstdlib> //include std::abs
#if defined(NANA_WINDOWS) #if defined(NANA_WINDOWS)
#include <windows.h> #include <windows.h>
#elif defined(NANA_X11) #elif defined(NANA_X11)
@ -494,21 +498,29 @@ namespace nana
//end class msgbox //end class msgbox
//class inputbox //class inputbox todo: add schema
class inputbox_window class inputbox_window
: public ::nana::form : public ::nana::form
{ {
public: 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<unsigned>& 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<unsigned>& each_height)
: form(owner, API::make_center(owner, 500, 300), appear::decorate<>()) : form(owner, API::make_center(owner, 500, 300), appear::decorate<>())
{ {
throw_not_utf8(desc); throw_not_utf8(description);
throw_not_utf8(title); throw_not_utf8(title);
desc_.create(*this); description_.create(*this);
desc_.format(true).caption(desc); description_.format(true).caption(description);
auto desc_extent = desc_.measure(470); auto description_size = description_.measure(470);
btn_ok_.create(*this); btn_ok_.create(*this);
btn_ok_.i18n(i18n_eval("NANA_BUTTON_OK")); btn_ok_.i18n(i18n_eval("NANA_BUTTON_OK"));
@ -527,32 +539,26 @@ namespace nana
close(); close();
}); });
unsigned height = 20 + desc_extent.height + 10 + 38; unsigned height = 20 + description_size.height + 10 + 38;
std::stringstream ss_content; std::stringstream ss_content;
ss_content << "<margin=10 vert <desc weight=" << desc_extent.height << "><vert margin=[10]";
for (std::size_t i = 0; i < contents; ++i) for (std::size_t i = 0; i < contents; ++i)
{ {
unsigned px = 27; unsigned px = std::max(27u, each_height[i]);
if (each_height[i] > 27)
px = each_height[i];
ss_content << "<weight=" << (px + 3) << " margin=[3] input_" << i << ">"; ss_content << "<height=" << (px + 3) << " margin=[3] input_" << i << ">";
height += px + 1; height += px + 3;
} }
ss_content << "><margin=[15] weight=38<><buttons arrange=80 gap=10 weight=170>>>"; if (description_size.width < 200)
description_size.width = 200;
if (desc_extent.width < 200)
desc_extent.width = 200;
//Make sure the complete display of input extent //Make sure the complete display of input extent
if (desc_extent.width < fixed_pixels) if (description_size.width < fixed_pixels)
desc_extent.width = fixed_pixels; description_size.width = fixed_pixels;
desc_extent.width += 20; description_size.width += 20; // 2x margin 10
::nana::size img_sz[4]; ::nana::size img_sz[4];
@ -566,8 +572,9 @@ namespace nana
} }
else else
sz = imgs[2].size(); sz = imgs[2].size();
sz.width = static_cast<size::value_type>(double(sz.width) * (double(height) / double(sz.height))); const double scale_factor = double(height) / double(sz.height);
desc_extent.width += sz.width; sz.width = static_cast<size::value_type>(double(sz.width) * scale_factor);
description_size.width += sz.width;
} }
if (imgs[3]) //Right if (imgs[3]) //Right
@ -581,7 +588,7 @@ namespace nana
else else
sz = imgs[3].size(); sz = imgs[3].size();
sz.width = static_cast<size::value_type>(double(sz.width) * (double(height) / double(sz.height))); sz.width = static_cast<size::value_type>(double(sz.width) * (double(height) / double(sz.height)));
desc_extent.width += sz.width; description_size.width += sz.width;
} }
if (imgs[0]) //Top if (imgs[0]) //Top
@ -594,7 +601,8 @@ namespace nana
} }
else else
sz = imgs[0].size(); sz = imgs[0].size();
sz.height = static_cast<size::value_type>(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<size::value_type>(double(sz.height) * scale_factor );
height += sz.height; height += sz.height;
} }
@ -608,16 +616,28 @@ namespace nana
} }
else else
sz = imgs[1].size(); sz = imgs[1].size();
sz.height = static_cast<size::value_type>(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<size::value_type>(double(sz.height) * scale_factor);
height += sz.height; height += sz.height;
} }
std::stringstream ss; std::stringstream ss;
ss << "vert<img_top weight="<<img_sz[0].height<<"><<img_left weight="<<img_sz[2].width<<">"<<ss_content.str()<<"<img_right weight="<<img_sz[3].width<<">><img_bottom weight="<<img_sz[1].height<<">"; ss << "vert< img_top height="<<img_sz[0].height<<">"
<<" << img_left width=" <<img_sz[2].width <<">"
<<" <margin=10 vert <description height=" << description_size.height << ">" // added height: 2x10
<<" <vert margin=[10]" // added height: 10
<< ss_content.str()
<<" >"
<<" <height=38 margin=[15] <><width=170 buttons arrange=80 gap=10>"
<<" >>" // added height: 38
<<" < img_right width=" <<img_sz[3].width
<<" >>< img_bottom height="<<img_sz[1].height<<">";
// added height: 10 x3 = 30 + 38
auto& place = this->get_place(); auto& place = this->get_place();
place.div(ss.str().c_str()); place.div(ss.str().c_str());
place["desc"] << desc_; place["description"] << description_;
place["buttons"] << btn_ok_ << btn_cancel_; place["buttons"] << btn_ok_ << btn_cancel_;
const char * img_fields[4] = {"img_top", "img_bottom", "img_left", "img_right"}; 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]); 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); caption(title);
} }
@ -659,7 +679,7 @@ namespace nana
return valid_input_; return valid_input_;
} }
private: private:
::nana::label desc_; ::nana::label description_;
::nana::button btn_ok_; ::nana::button btn_ok_;
::nana::button btn_cancel_; ::nana::button btn_cancel_;
bool valid_input_{ false }; bool valid_input_{ false };

View File

@ -96,11 +96,11 @@ namespace nana
{ {
if (widget_) if (widget_)
{ {
auto value_px = (widget_->size().width - border_px * 2); unsigned value_px = (widget_->size().width - border_px * 2);
//avoid overflow //avoid overflow
if (unknown_ || (value_ < max_)) if (unknown_ || (value_ < max_))
value_px = static_cast<unsigned>(value_px * (double(value_) / double(max_))); value_px = unsigned(double(value_px) * (double(value_) / double(max_)));
if (value_px != value_px_) if (value_px != value_px_)
{ {