mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-04 00:10:40 +08:00
Implement generic object rotation in all 3 axes with a slider and box.
This commit is contained in:
parent
f3c652e322
commit
ada744d718
89
src/GUI/Dialogs/AnglePicker.hpp
Normal file
89
src/GUI/Dialogs/AnglePicker.hpp
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
#ifndef ANGLEPICKER_HPP
|
||||||
|
#define ANGLEPICKER_HPP
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <wx/dialog.h>
|
||||||
|
#include <wx/textctrl.h>
|
||||||
|
#include <wx/slider.h>
|
||||||
|
#include <wx/sizer.h>
|
||||||
|
#include <wx/stattext.h>
|
||||||
|
#include <wx/button.h>
|
||||||
|
|
||||||
|
namespace Slic3r { namespace GUI {
|
||||||
|
|
||||||
|
/// Dialog to produce a special dialog with both a slider for +/- 360 degree rotation and a text box.
|
||||||
|
/// Supports decimal numbers via integer scaling.
|
||||||
|
template <int scaling = 10000>
|
||||||
|
class AnglePicker : public wxDialog {
|
||||||
|
public:
|
||||||
|
AnglePicker(wxWindow* parent, const wxString& title, double initial_angle) :
|
||||||
|
wxDialog(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE, wxString("AnglePicker")), _angle(scaling * initial_angle) {
|
||||||
|
|
||||||
|
auto* lbl_min = new wxStaticText(this, wxID_ANY, wxString(L"-360°"), wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT);
|
||||||
|
auto* lbl_max = new wxStaticText(this, wxID_ANY, wxString(L"360°"), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
|
||||||
|
auto* lbl_txt = new wxStaticText(this, wxID_ANY, wxString("Angle "), wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT);
|
||||||
|
|
||||||
|
auto btn_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
btn_sizer->Add(
|
||||||
|
new wxButton(this, wxID_OK, _("OK"), wxDefaultPosition, wxDefaultSize),
|
||||||
|
0,
|
||||||
|
wxALL,
|
||||||
|
10);
|
||||||
|
btn_sizer->Add(
|
||||||
|
new wxButton(this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize),
|
||||||
|
0,
|
||||||
|
wxALL,
|
||||||
|
10);
|
||||||
|
|
||||||
|
|
||||||
|
this->slider = new wxSlider(this, wxID_ANY, _angle, -360*scaling, 360*scaling, wxDefaultPosition, wxSize(255, wxDefaultSize.y));
|
||||||
|
this->manual_entry = new wxTextCtrl(this, wxID_ANY, wxString("") << angle(), wxDefaultPosition, wxDefaultSize);
|
||||||
|
|
||||||
|
|
||||||
|
this->hsizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
this->hsizer->Add(lbl_min, wxALIGN_LEFT);
|
||||||
|
this->hsizer->Add(this->slider, wxALIGN_CENTER);
|
||||||
|
this->hsizer->Add(lbl_max, wxALIGN_RIGHT);
|
||||||
|
|
||||||
|
auto text_sizer {new wxBoxSizer(wxHORIZONTAL)};
|
||||||
|
text_sizer->Add(lbl_txt, 0);
|
||||||
|
text_sizer->Add(this->manual_entry, 0);
|
||||||
|
|
||||||
|
this->vsizer = new wxBoxSizer(wxVERTICAL);
|
||||||
|
|
||||||
|
this->vsizer->Add(this->hsizer, 0);
|
||||||
|
this->vsizer->Add(text_sizer, 0);
|
||||||
|
this->vsizer->Add(btn_sizer, 0, wxALIGN_CENTER);
|
||||||
|
|
||||||
|
this->SetSizerAndFit(vsizer);
|
||||||
|
|
||||||
|
this->Bind(wxEVT_SLIDER, [this](wxCommandEvent &e){
|
||||||
|
wxString str;
|
||||||
|
_angle = this->slider->GetValue();
|
||||||
|
str.Printf("%f", this->angle());
|
||||||
|
this->manual_entry->SetValue(str);
|
||||||
|
});
|
||||||
|
this->Bind(wxEVT_TEXT, [this](wxCommandEvent &e){
|
||||||
|
wxString str {this->manual_entry->GetValue()};
|
||||||
|
double value {0.0};
|
||||||
|
if (str.ToDouble(&value))
|
||||||
|
if (value <= 360.0 && value >= -360.0)
|
||||||
|
this->slider->SetValue(value * scaling);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
double angle() { return double(_angle) / double(scaling) ; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// Scaled integer
|
||||||
|
int _angle {0};
|
||||||
|
|
||||||
|
wxSlider* slider {nullptr};
|
||||||
|
wxTextCtrl* manual_entry {nullptr};
|
||||||
|
wxSizer* hsizer {nullptr};
|
||||||
|
wxSizer* vsizer {nullptr};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}}
|
||||||
|
|
||||||
|
#endif// ANGLEPICKER_HPP
|
@ -120,11 +120,9 @@ void MainFrame::init_menubar()
|
|||||||
|
|
||||||
wxMenu* menuPlater = new wxMenu();
|
wxMenu* menuPlater = new wxMenu();
|
||||||
{
|
{
|
||||||
append_menu_item(menuPlater, _(L"Arrange…"), _("Arrange models on plater"), [=](wxCommandEvent& e) { if (this->plater != nullptr) this->plater->arrange();}, wxID_ANY, "bricks.png", "Ctrl+G");
|
append_menu_item(menuPlater, _(L"Arrange…"), _("Arrange models on plater"), [this](wxCommandEvent& e) { if (this->plater != nullptr) this->plater->arrange();}, wxID_ANY, "bricks.png", "Ctrl+G");
|
||||||
}
|
|
||||||
wxMenu* menuObject = new wxMenu();
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
wxMenu* menuObject = this->plater->object_menu();
|
||||||
wxMenu* menuSettings = new wxMenu();
|
wxMenu* menuSettings = new wxMenu();
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
#include "MainFrame.hpp"
|
#include "MainFrame.hpp"
|
||||||
#include "BoundingBox.hpp"
|
#include "BoundingBox.hpp"
|
||||||
#include "Geometry.hpp"
|
#include "Geometry.hpp"
|
||||||
|
#include "Dialogs/AnglePicker.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace Slic3r { namespace GUI {
|
namespace Slic3r { namespace GUI {
|
||||||
|
|
||||||
@ -450,11 +452,6 @@ void Plater::object_settings_dialog(ObjRef obj) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wxMenu* Plater::object_menu() {
|
|
||||||
return new wxMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Plater::select_object(ObjRef obj) {
|
void Plater::select_object(ObjRef obj) {
|
||||||
for (auto& o : this->objects) {
|
for (auto& o : this->objects) {
|
||||||
o.selected = false;
|
o.selected = false;
|
||||||
@ -733,8 +730,26 @@ void Plater::decrease(size_t copies, bool dont_push) {
|
|||||||
this->on_model_change();
|
this->on_model_change();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Plater::rotate(Axis axis, bool dont_push) {
|
||||||
|
ObjRef obj {this->selected_object()};
|
||||||
|
if (obj == this->objects.end()) return;
|
||||||
|
double angle {0.0};
|
||||||
|
|
||||||
|
auto* model_object {this->model->objects.at(obj->identifier)};
|
||||||
|
auto model_instance {model_object->instances.begin()};
|
||||||
|
|
||||||
|
// pop a menu to get the angle
|
||||||
|
auto* pick = new AnglePicker<1000>(this, "Set Angle", angle);
|
||||||
|
if (pick->ShowModal() == wxID_OK) {
|
||||||
|
angle = pick->angle();
|
||||||
|
pick->Destroy(); // cleanup afterwards.
|
||||||
|
this->rotate(angle, axis, dont_push);
|
||||||
|
} else {
|
||||||
|
pick->Destroy(); // cleanup afterwards.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Plater::rotate(double angle, Axis axis, bool dont_push) {
|
void Plater::rotate(double angle, Axis axis, bool dont_push) {
|
||||||
//TODO
|
|
||||||
ObjRef obj {this->selected_object()};
|
ObjRef obj {this->selected_object()};
|
||||||
if (obj == this->objects.end()) return;
|
if (obj == this->objects.end()) return;
|
||||||
|
|
||||||
@ -761,7 +776,7 @@ void Plater::rotate(double angle, Axis axis, bool dont_push) {
|
|||||||
this->print->add_model_object(model_object, obj->identifier);
|
this->print->add_model_object(model_object, obj->identifier);
|
||||||
|
|
||||||
if (!dont_push) {
|
if (!dont_push) {
|
||||||
// TODO
|
add_undo_operation(UndoCmd::Rotate, obj->identifier, angle, axis);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->selection_changed();
|
this->selection_changed();
|
||||||
@ -797,6 +812,9 @@ void Plater::add_undo_operation(UndoCmd cmd, int obj_id, Slic3r::Model& model) {
|
|||||||
void Plater::add_undo_operation(UndoCmd cmd, int obj_id, size_t copies) {
|
void Plater::add_undo_operation(UndoCmd cmd, int obj_id, size_t copies) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Plater::add_undo_operation(UndoCmd cmd, int obj_id, double angle, Axis axis) {
|
||||||
|
}
|
||||||
|
|
||||||
void Plater::object_list_changed() {
|
void Plater::object_list_changed() {
|
||||||
//TODO
|
//TODO
|
||||||
}
|
}
|
||||||
@ -816,5 +834,127 @@ void Plater::resume_background_process() {
|
|||||||
//TODO
|
//TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxMenu* Plater::object_menu() {
|
||||||
|
auto* frame {this->GetFrame()};
|
||||||
|
auto* menu {new wxMenu()};
|
||||||
|
|
||||||
|
append_menu_item(menu, _("Delete"), _("Remove the selected object."), [=](wxCommandEvent& e) { this->remove();}, wxID_ANY, "brick_delete.png", "Ctrl+Del");
|
||||||
|
/*
|
||||||
|
wxTheApp->append_menu_item($menu, "Delete\tCtrl+Del", 'Remove the selected object', sub {
|
||||||
|
$self->remove;
|
||||||
|
}, undef, 'brick_delete.png');
|
||||||
|
wxTheApp->append_menu_item($menu, "Increase copies\tCtrl++", 'Place one more copy of the selected object', sub {
|
||||||
|
$self->increase;
|
||||||
|
}, undef, 'add.png');
|
||||||
|
wxTheApp->append_menu_item($menu, "Decrease copies\tCtrl+-", 'Remove one copy of the selected object', sub {
|
||||||
|
$self->decrease;
|
||||||
|
}, undef, 'delete.png');
|
||||||
|
wxTheApp->append_menu_item($menu, "Set number of copies…", 'Change the number of copies of the selected object', sub {
|
||||||
|
$self->set_number_of_copies;
|
||||||
|
}, undef, 'textfield.png');
|
||||||
|
$menu->AppendSeparator();
|
||||||
|
wxTheApp->append_menu_item($menu, "Move to bed center", 'Center object around bed center', sub {
|
||||||
|
$self->center_selected_object_on_bed;
|
||||||
|
}, undef, 'arrow_in.png');
|
||||||
|
wxTheApp->append_menu_item($menu, "Rotate 45° clockwise", 'Rotate the selected object by 45° clockwise', sub {
|
||||||
|
$self->rotate(-45);
|
||||||
|
}, undef, 'arrow_rotate_clockwise.png');
|
||||||
|
wxTheApp->append_menu_item($menu, "Rotate 45° counter-clockwise", 'Rotate the selected object by 45° counter-clockwise', sub {
|
||||||
|
$self->rotate(+45);
|
||||||
|
}, undef, 'arrow_rotate_anticlockwise.png');
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
auto* rotateMenu {new wxMenu};
|
||||||
|
append_menu_item(rotateMenu, _(L"Around X axis…"), _("Rotate the selected object by an arbitrary angle around X axis."), [this](wxCommandEvent& e) { this->rotate(X); }, wxID_ANY, "bullet_red.png");
|
||||||
|
|
||||||
|
append_menu_item(rotateMenu, _(L"Around Y axis…"), _("Rotate the selected object by an arbitrary angle around Y axis."), [this](wxCommandEvent& e) { this->rotate(Y); }, wxID_ANY, "bullet_green.png");
|
||||||
|
|
||||||
|
append_menu_item(rotateMenu, _(L"Around Z axis…"), _("Rotate the selected object by an arbitrary angle around Z axis."), [this](wxCommandEvent& e) { this->rotate(Z); }, wxID_ANY, "bullet_blue.png");
|
||||||
|
|
||||||
|
append_submenu(menu, _("Rotate"), _("Rotate the selected object by an arbitrary angle"), rotateMenu, wxID_ANY, "textfield.png");
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
|
||||||
|
{
|
||||||
|
my $mirrorMenu = Wx::Menu->new;
|
||||||
|
wxTheApp->append_menu_item($mirrorMenu, "Along X axis…", 'Mirror the selected object along the X axis', sub {
|
||||||
|
$self->mirror(X);
|
||||||
|
}, undef, 'bullet_red.png');
|
||||||
|
wxTheApp->append_menu_item($mirrorMenu, "Along Y axis…", 'Mirror the selected object along the Y axis', sub {
|
||||||
|
$self->mirror(Y);
|
||||||
|
}, undef, 'bullet_green.png');
|
||||||
|
wxTheApp->append_menu_item($mirrorMenu, "Along Z axis…", 'Mirror the selected object along the Z axis', sub {
|
||||||
|
$self->mirror(Z);
|
||||||
|
}, undef, 'bullet_blue.png');
|
||||||
|
wxTheApp->append_submenu($menu, "Mirror", 'Mirror the selected object', $mirrorMenu, undef, 'shape_flip_horizontal.png');
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
my $scaleMenu = Wx::Menu->new;
|
||||||
|
wxTheApp->append_menu_item($scaleMenu, "Uniformly…", 'Scale the selected object along the XYZ axes', sub {
|
||||||
|
$self->changescale(undef);
|
||||||
|
});
|
||||||
|
wxTheApp->append_menu_item($scaleMenu, "Along X axis…", 'Scale the selected object along the X axis', sub {
|
||||||
|
$self->changescale(X);
|
||||||
|
}, undef, 'bullet_red.png');
|
||||||
|
wxTheApp->append_menu_item($scaleMenu, "Along Y axis…", 'Scale the selected object along the Y axis', sub {
|
||||||
|
$self->changescale(Y);
|
||||||
|
}, undef, 'bullet_green.png');
|
||||||
|
wxTheApp->append_menu_item($scaleMenu, "Along Z axis…", 'Scale the selected object along the Z axis', sub {
|
||||||
|
$self->changescale(Z);
|
||||||
|
}, undef, 'bullet_blue.png');
|
||||||
|
wxTheApp->append_submenu($menu, "Scale", 'Scale the selected object by a given factor', $scaleMenu, undef, 'arrow_out.png');
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
my $scaleToSizeMenu = Wx::Menu->new;
|
||||||
|
wxTheApp->append_menu_item($scaleToSizeMenu, "Uniformly…", 'Scale the selected object along the XYZ axes', sub {
|
||||||
|
$self->changescale(undef, 1);
|
||||||
|
});
|
||||||
|
wxTheApp->append_menu_item($scaleToSizeMenu, "Along X axis…", 'Scale the selected object along the X axis', sub {
|
||||||
|
$self->changescale(X, 1);
|
||||||
|
}, undef, 'bullet_red.png');
|
||||||
|
wxTheApp->append_menu_item($scaleToSizeMenu, "Along Y axis…", 'Scale the selected object along the Y axis', sub {
|
||||||
|
$self->changescale(Y, 1);
|
||||||
|
}, undef, 'bullet_green.png');
|
||||||
|
wxTheApp->append_menu_item($scaleToSizeMenu, "Along Z axis…", 'Scale the selected object along the Z axis', sub {
|
||||||
|
$self->changescale(Z, 1);
|
||||||
|
}, undef, 'bullet_blue.png');
|
||||||
|
wxTheApp->append_submenu($menu, "Scale to size", 'Scale the selected object to match a given size', $scaleToSizeMenu, undef, 'arrow_out.png');
|
||||||
|
}
|
||||||
|
|
||||||
|
wxTheApp->append_menu_item($menu, "Split", 'Split the selected object into individual parts', sub {
|
||||||
|
$self->split_object;
|
||||||
|
}, undef, 'shape_ungroup.png');
|
||||||
|
wxTheApp->append_menu_item($menu, "Cut…", 'Open the 3D cutting tool', sub {
|
||||||
|
$self->object_cut_dialog;
|
||||||
|
}, undef, 'package.png');
|
||||||
|
wxTheApp->append_menu_item($menu, "Layer heights…", 'Open the dynamic layer height control', sub {
|
||||||
|
$self->object_layers_dialog;
|
||||||
|
}, undef, 'variable_layer_height.png');
|
||||||
|
$menu->AppendSeparator();
|
||||||
|
wxTheApp->append_menu_item($menu, "Settings…", 'Open the object editor dialog', sub {
|
||||||
|
$self->object_settings_dialog;
|
||||||
|
}, undef, 'cog.png');
|
||||||
|
$menu->AppendSeparator();
|
||||||
|
wxTheApp->append_menu_item($menu, "Reload from Disk", 'Reload the selected file from Disk', sub {
|
||||||
|
$self->reload_from_disk;
|
||||||
|
}, undef, 'arrow_refresh.png');
|
||||||
|
wxTheApp->append_menu_item($menu, "Export object as STL…", 'Export this single object as STL file', sub {
|
||||||
|
$self->export_object_stl;
|
||||||
|
}, undef, 'brick_go.png');
|
||||||
|
wxTheApp->append_menu_item($menu, "Export object and modifiers as AMF…", 'Export this single object and all associated modifiers as AMF file', sub {
|
||||||
|
$self->export_object_amf;
|
||||||
|
}, undef, 'brick_go.png');
|
||||||
|
wxTheApp->append_menu_item($menu, "Export object and modifiers as 3MF…", 'Export this single object and all associated modifiers as 3MF file', sub {
|
||||||
|
$self->export_object_tmf;
|
||||||
|
}, undef, 'brick_go.png');
|
||||||
|
|
||||||
|
return $menu;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return menu;
|
||||||
|
}
|
||||||
|
|
||||||
}} // Namespace Slic3r::GUI
|
}} // Namespace Slic3r::GUI
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ namespace Slic3r { namespace GUI {
|
|||||||
using UndoOperation = int;
|
using UndoOperation = int;
|
||||||
|
|
||||||
enum class UndoCmd {
|
enum class UndoCmd {
|
||||||
Remove, Add, Reset, Increase, Decrease
|
Remove, Add, Reset, Increase, Decrease, Rotate
|
||||||
};
|
};
|
||||||
|
|
||||||
using ObjIdx = unsigned int;
|
using ObjIdx = unsigned int;
|
||||||
@ -70,6 +70,12 @@ public:
|
|||||||
/// Undo for increase/decrease
|
/// Undo for increase/decrease
|
||||||
void add_undo_operation(UndoCmd cmd, int obj_id, size_t copies);
|
void add_undo_operation(UndoCmd cmd, int obj_id, size_t copies);
|
||||||
|
|
||||||
|
/// Undo for increase/decrease
|
||||||
|
void add_undo_operation(UndoCmd cmd, int obj_id, double angle, Axis axis);
|
||||||
|
|
||||||
|
/// Create menu for object.
|
||||||
|
wxMenu* object_menu();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<Slic3r::Print> print {std::make_shared<Print>(Slic3r::Print())};
|
std::shared_ptr<Slic3r::Print> print {std::make_shared<Print>(Slic3r::Print())};
|
||||||
std::shared_ptr<Slic3r::Model> model {std::make_shared<Model>(Slic3r::Model())};
|
std::shared_ptr<Slic3r::Model> model {std::make_shared<Model>(Slic3r::Model())};
|
||||||
@ -158,8 +164,6 @@ private:
|
|||||||
void object_settings_dialog(ObjIdx obj_idx);
|
void object_settings_dialog(ObjIdx obj_idx);
|
||||||
void object_settings_dialog(ObjRef obj);
|
void object_settings_dialog(ObjRef obj);
|
||||||
|
|
||||||
/// Create and launch menu for object.
|
|
||||||
wxMenu* object_menu();
|
|
||||||
|
|
||||||
/// Instantiate the toolbar
|
/// Instantiate the toolbar
|
||||||
void build_toolbar();
|
void build_toolbar();
|
||||||
@ -173,6 +177,8 @@ private:
|
|||||||
/// Remove instances of the currently selected model.
|
/// Remove instances of the currently selected model.
|
||||||
void decrease(size_t copies = 1, bool dont_push = false);
|
void decrease(size_t copies = 1, bool dont_push = false);
|
||||||
|
|
||||||
|
/// Rotate the currently selected model, triggering a user prompt.
|
||||||
|
void rotate(Axis axis = Z, bool dont_push = false);
|
||||||
/// Rotate the currently selected model.
|
/// Rotate the currently selected model.
|
||||||
void rotate(double angle, Axis axis = Z, bool dont_push = false);
|
void rotate(double angle, Axis axis = Z, bool dont_push = false);
|
||||||
|
|
||||||
|
@ -64,6 +64,24 @@ void fatal_error(wxWindow* parent, const wxString& message) {
|
|||||||
throw std::runtime_error(message.ToStdString());
|
throw std::runtime_error(message.ToStdString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxMenuItem* append_submenu(wxMenu* menu, const wxString& name, const wxString& help, wxMenu* submenu, int id, const wxString& icon) {
|
||||||
|
auto* item {new wxMenuItem(menu, id, name, help)};
|
||||||
|
|
||||||
|
set_menu_item_icon(item,icon);
|
||||||
|
item->SetSubMenu(submenu);
|
||||||
|
menu->Append(item);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_menu_item_icon(wxMenuItem* item, const wxString& icon) {
|
||||||
|
if (!icon.IsEmpty()) {
|
||||||
|
wxBitmap ico;
|
||||||
|
if(ico.LoadFile(var(icon), wxBITMAP_TYPE_PNG))
|
||||||
|
item->SetBitmap(ico);
|
||||||
|
else
|
||||||
|
std::cerr<< var(icon) << " failed to load \n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
sub append_submenu {
|
sub append_submenu {
|
||||||
|
@ -107,6 +107,8 @@ void show_info(wxWindow* parent, const wxString& message, const wxString& title)
|
|||||||
/// Show an error messagebox and then throw an exception.
|
/// Show an error messagebox and then throw an exception.
|
||||||
void fatal_error(wxWindow* parent, const wxString& message);
|
void fatal_error(wxWindow* parent, const wxString& message);
|
||||||
|
|
||||||
|
/// Assign a menu item icon
|
||||||
|
void set_menu_item_icon(wxMenuItem* item, const wxString& icon);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void append_menu_item(wxMenu* menu, const wxString& name,const wxString& help, T lambda, int id = wxID_ANY, const wxString& icon = "", const wxString& accel = "") {
|
void append_menu_item(wxMenu* menu, const wxString& name,const wxString& help, T lambda, int id = wxID_ANY, const wxString& icon = "", const wxString& accel = "") {
|
||||||
@ -117,18 +119,14 @@ void append_menu_item(wxMenu* menu, const wxString& name,const wxString& help, T
|
|||||||
tmp->SetAccel(a); // set the accelerator if and only if the accelerator is fine
|
tmp->SetAccel(a); // set the accelerator if and only if the accelerator is fine
|
||||||
}
|
}
|
||||||
tmp->SetHelp(help);
|
tmp->SetHelp(help);
|
||||||
if (!icon.IsEmpty()) {
|
set_menu_item_icon(tmp, icon);
|
||||||
wxBitmap ico;
|
|
||||||
if(ico.LoadFile(var(icon), wxBITMAP_TYPE_PNG))
|
|
||||||
tmp->SetBitmap(ico);
|
|
||||||
else
|
|
||||||
std::cerr<< var(icon) << " failed to load \n";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeid(lambda) != typeid(nullptr))
|
if (typeid(lambda) != typeid(nullptr))
|
||||||
menu->Bind(wxEVT_MENU, lambda, tmp->GetId(), tmp->GetId());
|
menu->Bind(wxEVT_MENU, lambda, tmp->GetId(), tmp->GetId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxMenuItem* append_submenu(wxMenu* menu, const wxString& name, const wxString& help, wxMenu* submenu, int id = wxID_ANY, const wxString& icon = "");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
sub CallAfter {
|
sub CallAfter {
|
||||||
my ($self, $cb) = @_;
|
my ($self, $cb) = @_;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user