Add inputbox

This commit is contained in:
cnjinhao 2015-01-28 07:14:21 +08:00
parent c3d5c4aef4
commit a802083feb
5 changed files with 370 additions and 139 deletions

View File

@ -91,6 +91,26 @@ namespace nana
button_t button_;
icon_t icon_;
};
class inputbox
{
public:
inputbox(window, ::nana::string description, ::nana::string title = ::nana::string(), ::nana::string label = ::nana::string());
void set_modal();
bool valid() const;
int get_int(int value, int begin, int last, int step);
double get_double(double value, double begin, double last, double step);
::nana::string get_string();
private:
window owner_;
bool valid_input_;
bool modal_mode_;
::nana::string description_;
::nana::string title_;
::nana::string label_;
};
}//end namespace nana
#endif

View File

@ -49,6 +49,7 @@ namespace nana
void mouse_leave(graph_reference, const arg_mouse&) override;
void key_press(graph_reference, const arg_keyboard&) override;
void key_char(graph_reference, const arg_keyboard&) override;
void resized(graph_reference, const arg_resized&) override;
private:
implementation * const impl_;
};
@ -80,6 +81,11 @@ namespace nana
void range(std::initializer_list<std::string> steps_utf8);
void range(std::initializer_list<std::wstring> steps);
/// Gets the spined value
::nana::string value() const;
int to_int() const;
double to_double() const;
/// Sets a predicator that determines whether accepts the current user input.
/// @param pred Predicator to determines the input.
void set_accept(std::function<bool(::nana::char_t)> pred);

View File

@ -9,17 +9,20 @@
*
* @file: nana/gui/msgbox.hpp
*/
#include <nana/gui/msgbox.hpp>
#include <nana/gui/programming_interface.hpp>
//#include <nana/gui/msgbox.hpp> //deprecated
//#include <nana/gui/programming_interface.hpp> //deprecated
#include <nana/gui.hpp>
#include <nana/gui/widgets/label.hpp>
#include <nana/gui/widgets/button.hpp>
#include <nana/gui/widgets/spinbox.hpp>
#include <nana/gui/place.hpp>
#include <nana/internationalization.hpp>
#if defined(NANA_WINDOWS)
#include <windows.h>
#elif defined(NANA_X11)
#include <nana/gui/wvl.hpp>
#include <nana/gui/widgets/label.hpp>
#include <nana/gui/widgets/button.hpp>
#include <nana/gui/widgets/picture.hpp>
#include <nana/paint/pixel_buffer.hpp>
#include <nana/gui/place.hpp>
#endif
namespace nana
@ -107,7 +110,7 @@ namespace nana
const unsigned text_pixels = 500 - ico_pixels;
text_.create(*this, nana::rectangle(12 + ico_pixels, 25, 1, 1));
text_.background(0xFFFFFF);
text_.bgcolor(colors::white);
text_.caption(text);
nana::size ts = text_.measure(text_pixels);
@ -319,146 +322,294 @@ namespace nana
};
#endif
//class msgbox
msgbox::msgbox()
: wd_(nullptr), button_(ok), icon_(icon_none)
{}
//class msgbox
msgbox::msgbox()
: wd_(nullptr), button_(ok), icon_(icon_none)
{}
msgbox::msgbox(const msgbox& rhs)
: wd_(rhs.wd_), title_(rhs.title_), button_(rhs.button_), icon_(rhs.icon_)
msgbox::msgbox(const msgbox& rhs)
: wd_(rhs.wd_), title_(rhs.title_), button_(rhs.button_), icon_(rhs.icon_)
{
sstream_<<rhs.sstream_.str();
}
msgbox& msgbox::operator=(const msgbox& rhs)
{
if(this != &rhs)
{
sstream_<<rhs.sstream_.str();
wd_ = rhs.wd_;
title_ = rhs.title_;
button_ = rhs.button_;
icon_ = rhs.icon_;
sstream_ << rhs.sstream_.str();
}
return *this;
}
msgbox& msgbox::operator=(const msgbox& rhs)
{
if(this != &rhs)
{
wd_ = rhs.wd_;
title_ = rhs.title_;
button_ = rhs.button_;
icon_ = rhs.icon_;
sstream_ << rhs.sstream_.str();
}
return *this;
}
msgbox::msgbox(const nana::string& title)
: wd_(nullptr), title_(title), button_(ok), icon_(icon_none)
{}
msgbox::msgbox(const nana::string& title)
: wd_(nullptr), title_(title), button_(ok), icon_(icon_none)
{}
msgbox::msgbox(window wd, const nana::string& title)
: wd_(wd), title_(title), button_(ok), icon_(icon_none)
{}
msgbox::msgbox(window wd, const nana::string& title)
: wd_(wd), title_(title), button_(ok), icon_(icon_none)
{}
msgbox::msgbox(window wd, const nana::string& title, button_t b)
: wd_(wd), title_(title), button_(b), icon_(icon_none)
{}
msgbox::msgbox(window wd, const nana::string& title, button_t b)
: wd_(wd), title_(title), button_(b), icon_(icon_none)
{}
msgbox& msgbox::icon(icon_t ic)
{
icon_ = ic;
return *this;
}
msgbox& msgbox::icon(icon_t ic)
{
icon_ = ic;
return *this;
}
void msgbox::clear()
{
sstream_.str("");
sstream_.clear();
}
void msgbox::clear()
{
sstream_.str("");
sstream_.clear();
}
msgbox & msgbox::operator<<(const nana::string& str)
{
msgbox & msgbox::operator<<(const nana::string& str)
{
#if defined(NANA_UNICODE)
sstream_<<static_cast<std::string>(nana::charset(str));
sstream_<<static_cast<std::string>(nana::charset(str));
#else
sstream_<<str;
sstream_<<str;
#endif
return *this;
}
return *this;
}
msgbox & msgbox::operator<<(const nana::char_t* str)
{
msgbox & msgbox::operator<<(const nana::char_t* str)
{
#if defined(NANA_UNICODE)
sstream_<<static_cast<std::string>(nana::charset(str));;
sstream_<<static_cast<std::string>(nana::charset(str));;
#else
sstream_<<str;
sstream_<<str;
#endif
return *this;
}
return *this;
}
msgbox & msgbox::operator<<(const nana::charset& cs)
{
std::string str = cs;
sstream_ << str;
return *this;
}
msgbox & msgbox::operator<<(const nana::charset& cs)
{
std::string str = cs;
sstream_ << str;
return *this;
}
msgbox & msgbox::operator<<(std::ostream& (*manipulator)(std::ostream&))
{
sstream_<<manipulator;
return *this;
}
msgbox & msgbox::operator<<(std::ostream& (*manipulator)(std::ostream&))
{
sstream_<<manipulator;
return *this;
}
msgbox::pick_t msgbox::show() const
{
msgbox::pick_t msgbox::show() const
{
#if defined(NANA_WINDOWS)
int type = 0;
switch(button_)
{
case msgbox::ok:
type = MB_OK;
break;
case msgbox::yes_no:
type = MB_YESNO;
break;
case msgbox::yes_no_cancel:
type = MB_YESNOCANCEL;
break;
}
int type = 0;
switch(button_)
{
case msgbox::ok:
type = MB_OK;
break;
case msgbox::yes_no:
type = MB_YESNO;
break;
case msgbox::yes_no_cancel:
type = MB_YESNOCANCEL;
break;
}
switch(icon_)
{
case msgbox::icon_error:
type |= MB_ICONERROR;
break;
case msgbox::icon_question:
type |= MB_ICONQUESTION;
break;
case msgbox::icon_information:
type |= MB_ICONINFORMATION;
break;
case msgbox::icon_warning:
type |= MB_ICONWARNING;
break;
default: break;
}
switch(icon_)
{
case msgbox::icon_error:
type |= MB_ICONERROR;
break;
case msgbox::icon_question:
type |= MB_ICONQUESTION;
break;
case msgbox::icon_information:
type |= MB_ICONINFORMATION;
break;
case msgbox::icon_warning:
type |= MB_ICONWARNING;
break;
default: break;
}
#if defined(NANA_UNICODE)
int bt = ::MessageBoxW(reinterpret_cast<HWND>(API::root(wd_)), static_cast<std::wstring>(nana::charset(sstream_.str())).c_str(), title_.c_str(), type);
#else
int bt = ::MessageBoxA(reinterpret_cast<HWND>(API::root(wd_), sstream_.str().c_str(), title_.c_str(), type);
#endif
switch(bt)
{
case IDOK:
return pick_ok;
case IDYES:
return pick_yes;
case IDNO:
return pick_no;
case IDCANCEL:
return pick_cancel;
}
return pick_yes;
#elif defined(NANA_X11)
msgbox_window box(wd_, title_, button_, icon_);
box.prompt(nana::charset(sstream_.str()));
return box.pick();
#endif
switch(bt)
{
case IDOK:
return pick_ok;
case IDYES:
return pick_yes;
case IDNO:
return pick_no;
case IDCANCEL:
return pick_cancel;
}
//end class msgbox
return pick_yes;
#elif defined(NANA_X11)
msgbox_window box(wd_, title_, button_, icon_);
box.prompt(nana::charset(sstream_.str()));
return box.pick();
#endif
return pick_yes;
}
//end class msgbox
//class inputbox
class inputbox_window
: public ::nana::form
{
public:
inputbox_window(window owner, const ::nana::string & desc, const ::nana::string& title, const ::nana::string& label, unsigned input_widget_size)
: form(owner, API::make_center(owner, 500, 300), appear::decorate<>())
{
desc_.create(*this);
desc_.format(true).caption(desc);
auto desc_extent = desc_.measure(470);
desc_extent.height += 8;
label_.create(*this);
label_.format(true).caption(label);
label_.text_align(::nana::align::left, ::nana::align_v::center);
auto label_extent = label_.measure(230);
label_extent.height += 8;
btn_ok_.create(*this);
btn_ok_.i18n(i18n_eval("Nana.OK"));
btn_ok_.events().click([this]{
close();
valid_input_ = true;
});
btn_cancel_.create(*this);
btn_cancel_.i18n(i18n_eval("Nana.Cancel"));
btn_cancel_.events().click([this]{
close();
});
place_.bind(*this);
std::stringstream ss;
ss << "margin=10 vert <desc weight=" << desc_extent.height << "><weight=" << label_extent.height << "<label weight=" << label_extent.width << "><margin=[0,0,0,10] input";
if (input_widget_size)
ss << " weight=" << input_widget_size;
ss << ">><margin=[10,0,0,0] buttons arrange=100 gap=10 weight=23>";
place_.div(ss.str().data());
place_["desc"] << desc_;
place_["label"] << label_;
place_["buttons"] << btn_ok_ << btn_cancel_;
unsigned height = 20 + desc_extent.height + label_extent.height + 10 + 23;
size({ 500, height });
caption(title);
}
void set_input(window handle)
{
place_["input"] << handle;
place_.collocate();
show();
}
bool valid_input() const
{
return valid_input_;
}
private:
::nana::label desc_;
::nana::label label_;
::nana::button btn_ok_;
::nana::button btn_cancel_;
bool valid_input_{ false };
::nana::place place_;
};
inputbox::inputbox(window owner, ::nana::string desc, ::nana::string title, ::nana::string label)
: owner_{ owner }, valid_input_{ false }, modal_mode_{false},
description_(std::move(desc)),
title_(std::move(title)),
label_(std::move(label))
{}
void inputbox::set_modal()
{
modal_mode_ = true;
}
bool inputbox::valid() const
{
return valid_input_;
}
int inputbox::get_int(int value, int begin, int last, int step)
{
int longest = (std::abs((begin < 0 ? begin * 10 : begin)) < std::abs(last < 0 ? last * 10 : last) ? last : begin);
std::wstringstream ss;
ss << longest;
paint::graphics graph{ ::nana::size{ 10, 10 } };
auto input_widget_size = graph.text_extent_size(ss.str()).width + 34;
auto t1 = graph.typeface();
inputbox_window inp_window(owner_, description_, title_, label_, input_widget_size);
::nana::spinbox spinbox(inp_window);
spinbox.range(begin, last, step);
spinbox.set_accept_integer();
inp_window.set_input(spinbox);
auto t2 = spinbox.typeface();
if (modal_mode_)
inp_window.modality();
else
API::wait_for(inp_window);
valid_input_ = inp_window.valid_input();
return spinbox.to_int();
}
double inputbox::get_double(double value, double begin, double last, double step)
{
std::wstring longest;
for (auto i = begin; i < last; i += step)
{
std::wstringstream ss;
ss << i;
auto str = ss.str();
if (str.size() > longest.size())
longest = str;
}
paint::graphics graph{ ::nana::size{ 10, 10 } };
auto input_widget_size = graph.text_extent_size(longest).width + 34;
inputbox_window inp_window(owner_, description_, title_, label_, input_widget_size);
::nana::spinbox spinbox(inp_window);
spinbox.range(begin, last, step);
spinbox.set_accept_real();
inp_window.set_input(spinbox);
if (modal_mode_)
inp_window.modality();
else
API::wait_for(inp_window);
valid_input_ = inp_window.valid_input();
return spinbox.to_double();
}
::nana::string inputbox::get_string()
{
return{};
}
//end class inputbox
}

View File

@ -157,7 +157,7 @@ namespace nana
API::eat_tabstop(wd, true);
API::effects_edge_nimbus(wd, effects::edge_nimbus::active);
API::effects_edge_nimbus(wd, effects::edge_nimbus::over);
_m_reset_text_area();
reset_text_area();
}
void detach()
@ -166,6 +166,11 @@ namespace nana
editor_ = nullptr;
}
::nana::string value() const
{
return range_->value();
}
void set_range(std::unique_ptr<range_interface> ptr)
{
range_.swap(ptr);
@ -268,6 +273,15 @@ namespace nana
return false;
}
void reset_text_area()
{
auto spins_r = _m_spins_area();
if (spins_r.x == 0)
editor_->text_area({});
else
editor_->text_area({ 2, 2, graph_->width() - spins_r.width - 2, spins_r.height - 2 });
}
private:
void _m_text()
{
@ -279,15 +293,6 @@ namespace nana
}
}
void _m_reset_text_area()
{
auto spins_r = _m_spins_area();
if (spins_r.x == 0)
editor_->text_area({});
else
editor_->text_area({ 2, 2, graph_->width() - spins_r.width - 2, spins_r.height - 2 });
}
::nana::rectangle _m_spins_area() const
{
auto size = API::window_size(editor_->window_handle());
@ -432,6 +437,14 @@ namespace nana
API::lazy_refresh();
}
}
void drawer::resized(graph_reference graph, const arg_resized& arg)
{
impl_->reset_text_area();
impl_->render();
impl_->editor()->reset_caret();
API::lazy_refresh();
}
}
}//end namespace drawerbase
@ -490,6 +503,33 @@ namespace nana
API::refresh_window(handle());
}
::nana::string spinbox::value() const
{
internal_scope_guard lock;
if (handle())
return get_drawer_trigger().impl()->value();
return{};
}
int spinbox::to_int() const
{
//std::stoi is not defined by MinGW
std::wstringstream ss;
ss << value();
int n = 0;
ss >> n;
return n;
}
double spinbox::to_double() const
{
//std::stod is not defined by MinGW
std::wstringstream ss;
ss << value();
double d = 0;
ss >> d;
return d;
}
void spinbox::set_accept(std::function<bool(::nana::char_t)> pred)
{

View File

@ -144,6 +144,15 @@ namespace nana
static std::shared_ptr<data>& get_data_ptr()
{
static std::shared_ptr<data> data_ptr;
if (!data_ptr)
{
data_ptr = std::make_shared<data>();
//Initialize the predefined language text
auto & table = data_ptr->table;
table["Nana.OK"].assign(L"OK");
table["Nana.Cancel"].assign(L"Cancel");
}
return data_ptr;
}
@ -208,6 +217,16 @@ namespace nana
impl->table[std::move(msgid)].swap(str);
}
//Assign all language texts to the new table.
auto & cur_table = get_data_ptr()->table;
auto & new_table = impl->table;
for (auto & m : cur_table)
{
auto & value = new_table[m.first];
if (value.empty())
value = m.second;
}
get_data_ptr().swap(impl);
use_eval();
}
@ -288,22 +307,17 @@ namespace nana
void internationalization::set(std::string msgid, nana::string msgstr)
{
auto & ptr = internationalization_parts::get_data_ptr();
if (!ptr)
ptr = std::make_shared<internationalization_parts::data>();
ptr->table[msgid].swap(msgstr);
}
bool internationalization::_m_get(std::string& msgid, nana::string& msgstr) const
{
auto impl = internationalization_parts::get_data_ptr();
if (impl)
auto & impl = internationalization_parts::get_data_ptr();
auto i = impl->table.find(msgid);
if (i != impl->table.end())
{
auto i = impl->table.find(msgid);
if (i != impl->table.end())
{
msgstr = i->second;
return true;
}
msgstr = i->second;
return true;
}
msgstr = nana::charset(std::move(msgid), nana::unicode::utf8);