Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorenricoturri1966 <enricoturri@seznam.cz>2021-12-22 12:50:59 +0300
committerenricoturri1966 <enricoturri@seznam.cz>2021-12-22 12:50:59 +0300
commitd1822f3ca2655afaa2e69fc194e56b283d3818a3 (patch)
tree46d283c1aa69d04d5eec7117862228afb702d8a7 /src
parentcd4094743e57d0d9f3947068c48deae4c03b354b (diff)
parent1fe4ba289bf68a7e4ceb575b5e63194441bc1bfa (diff)
Merge branch 'dev' of https://github.com/prusa3d/PrusaSlicer into et_color_class
Diffstat (limited to 'src')
-rw-r--r--src/libslic3r/CMakeLists.txt10
-rw-r--r--src/libslic3r/GCode/AvoidCrossingPerimeters.cpp66
-rw-r--r--src/libslic3r/PresetBundle.cpp14
-rw-r--r--src/slic3r/CMakeLists.txt6
-rw-r--r--src/slic3r/GUI/GLCanvas3D.cpp6
-rw-r--r--src/slic3r/GUI/GUI_App.cpp50
-rw-r--r--src/slic3r/GUI/GUI_ObjectList.cpp4
-rw-r--r--src/slic3r/GUI/Plater.cpp62
-rw-r--r--src/slic3r/GUI/UpdateDialogs.cpp2
9 files changed, 136 insertions, 84 deletions
diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt
index f398c3ba7..c79be847b 100644
--- a/src/libslic3r/CMakeLists.txt
+++ b/src/libslic3r/CMakeLists.txt
@@ -14,7 +14,7 @@ if (TARGET OpenVDB::openvdb)
set(OpenVDBUtils_SOURCES OpenVDBUtils.cpp OpenVDBUtils.hpp)
endif()
-add_library(libslic3r STATIC
+set(SLIC3R_SOURCES
pchheader.cpp
pchheader.hpp
BoundingBox.cpp
@@ -293,6 +293,14 @@ add_library(libslic3r STATIC
SLA/ReprojectPointsOnMesh.hpp
)
+add_library(libslic3r STATIC ${SLIC3R_SOURCES})
+
+foreach(_source IN ITEMS ${SLIC3R_SOURCES})
+ get_filename_component(_source_path "${_source}" PATH)
+ string(REPLACE "/" "\\" _group_path "${_source_path}")
+ source_group("${_group_path}" FILES "${_source}")
+endforeach()
+
if (SLIC3R_STATIC)
set(CGAL_Boost_USE_STATIC_LIBS ON CACHE BOOL "" FORCE)
endif ()
diff --git a/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp b/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp
index 48b9515f7..417322584 100644
--- a/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp
+++ b/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp
@@ -731,34 +731,50 @@ static bool need_wipe(const GCode &gcodegen,
}
// Adds points around all vertices so that the offset affects only small sections around these vertices.
-static void resample_polygon(Polygon &polygon, double dist_from_vertex)
+static void resample_polygon(Polygon &polygon, double dist_from_vertex, double max_allowed_distance)
{
Points resampled_poly;
resampled_poly.reserve(3 * polygon.size());
- resampled_poly.emplace_back(polygon.first_point());
- for (size_t pt_idx = 1; pt_idx < polygon.size(); ++pt_idx) {
- const Point &p1 = polygon[pt_idx - 1];
- const Point &p2 = polygon[pt_idx];
- double line_length = (p2 - p1).cast<double>().norm();
- Vector line_vec = ((p2 - p1).cast<double>().normalized() * dist_from_vertex).cast<coord_t>();
- if (line_length > 2 * dist_from_vertex) {
- resampled_poly.emplace_back(p1 + line_vec);
- resampled_poly.emplace_back(p2 - line_vec);
- }
+ for (size_t pt_idx = 0; pt_idx < polygon.size(); ++pt_idx) {
resampled_poly.emplace_back(polygon[pt_idx]);
+
+ const Point &p1 = polygon[pt_idx];
+ const Point &p2 = polygon[next_idx_modulo(pt_idx, polygon.size())];
+ const Vec2d line_vec = (p2 - p1).cast<double>();
+ double line_length = line_vec.norm();
+ const Vector vertex_offset_vec = (line_vec.normalized() * dist_from_vertex).cast<coord_t>();
+ if (line_length > 2 * dist_from_vertex && vertex_offset_vec != Vector(0, 0)) {
+ resampled_poly.emplace_back(p1 + vertex_offset_vec);
+
+ const Vec2d new_vertex_vec = (p2 - p1 - 2 * vertex_offset_vec).cast<double>();
+ const double new_vertex_vec_length = new_vertex_vec.norm();
+ if (new_vertex_vec_length > max_allowed_distance) {
+ const Vec2d &prev_point = resampled_poly.back().cast<double>();
+ const size_t parts_count = size_t(ceil(new_vertex_vec_length / max_allowed_distance));
+ for (size_t part_idx = 1; part_idx < parts_count; ++part_idx) {
+ const double part_param = double(part_idx) / double(parts_count);
+ const Vec2d new_point = prev_point + new_vertex_vec * part_param;
+ resampled_poly.emplace_back(new_point.cast<coord_t>());
+ }
+ }
+
+ resampled_poly.emplace_back(p2 - vertex_offset_vec);
+ }
}
polygon.points = std::move(resampled_poly);
}
-static void resample_expolygon(ExPolygon &ex_polygon, double dist_from_vertex)
+static void resample_expolygon(ExPolygon &ex_polygon, double dist_from_vertex, double max_allowed_distance)
{
- resample_polygon(ex_polygon.contour, dist_from_vertex);
- for (Polygon &polygon : ex_polygon.holes) resample_polygon(polygon, dist_from_vertex);
+ resample_polygon(ex_polygon.contour, dist_from_vertex, max_allowed_distance);
+ for (Polygon &polygon : ex_polygon.holes)
+ resample_polygon(polygon, dist_from_vertex, max_allowed_distance);
}
-static void resample_expolygons(ExPolygons &ex_polygons, double dist_from_vertex)
+static void resample_expolygons(ExPolygons &ex_polygons, double dist_from_vertex, double max_allowed_distance)
{
- for (ExPolygon &ex_poly : ex_polygons) resample_expolygon(ex_poly, dist_from_vertex);
+ for (ExPolygon &ex_poly : ex_polygons)
+ resample_expolygon(ex_poly, dist_from_vertex, max_allowed_distance);
}
static void precompute_polygon_distances(const Polygon &polygon, std::vector<float> &polygon_distances_out)
@@ -834,7 +850,7 @@ static std::vector<float> contour_distance(const EdgeGrid::Grid &grid,
double param_end = boundary_parameters.back();
const size_t ipt = it_contour_and_segment->second;
if (contour.begin() + ipt + 1 < contour.end())
- param_hi += boundary_parameters[ipt > 0 ? ipt - 1 : 0];
+ param_hi += boundary_parameters[ipt];
if (param_lo > param_hi)
std::swap(param_lo, param_hi);
assert(param_lo > -SCALED_EPSILON && param_lo <= param_end + SCALED_EPSILON);
@@ -932,7 +948,7 @@ static ExPolygons inner_offset(const ExPolygons &ex_polygons, double offset)
double min_contour_width = 2. * offset + SCALED_EPSILON;
double search_radius = 2. * (offset + min_contour_width);
ExPolygons ex_poly_result = ex_polygons;
- resample_expolygons(ex_poly_result, offset / 2);
+ resample_expolygons(ex_poly_result, offset / 2, scaled<double>(0.5));
for (ExPolygon &ex_poly : ex_poly_result) {
BoundingBox bbox(get_extents(ex_poly));
@@ -1034,24 +1050,30 @@ static Polygons get_boundary_external(const Layer &layer)
#endif
// Collect all holes for all printed objects and their instances, which will be printed at the same time as passed "layer".
for (const PrintObject *object : layer.object()->print()->objects()) {
- Polygons polygons_per_obj;
+ Polygons holes_per_obj;
#ifdef INCLUDE_SUPPORTS_IN_BOUNDARY
ExPolygons supports_per_obj;
#endif
if (const Layer *l = object->get_layer_at_printz(layer.print_z, EPSILON); l)
- for (const ExPolygon &island : l->lslices) append(polygons_per_obj, island.holes);
+ for (const ExPolygon &island : l->lslices)
+ append(holes_per_obj, island.holes);
if (support_layer) {
auto *layer_below = object->get_first_layer_bellow_printz(layer.print_z, EPSILON);
if (layer_below)
- for (const ExPolygon &island : layer_below->lslices) append(polygons_per_obj, island.holes);
+ for (const ExPolygon &island : layer_below->lslices)
+ append(holes_per_obj, island.holes);
#ifdef INCLUDE_SUPPORTS_IN_BOUNDARY
append(supports_per_obj, support_layer->support_islands.expolygons);
#endif
}
+ // After 7ff76d07684858fd937ef2f5d863f105a10f798e, when expand is called on CW polygons (holes), they are shrunk
+ // instead of expanded because union that makes CCW from CW isn't called anymore. So let's make it CCW.
+ polygons_reverse(holes_per_obj);
+
for (const PrintInstance &instance : object->instances()) {
size_t boundary_idx = boundary.size();
- append(boundary, polygons_per_obj);
+ append(boundary, holes_per_obj);
for (; boundary_idx < boundary.size(); ++boundary_idx)
boundary[boundary_idx].translate(instance.shift);
#ifdef INCLUDE_SUPPORTS_IN_BOUNDARY
diff --git a/src/libslic3r/PresetBundle.cpp b/src/libslic3r/PresetBundle.cpp
index 81983b4aa..874b775cd 100644
--- a/src/libslic3r/PresetBundle.cpp
+++ b/src/libslic3r/PresetBundle.cpp
@@ -212,17 +212,27 @@ static void copy_dir(const boost::filesystem::path& from_dir, const boost::files
// Import newer configuration from alternate PrusaSlicer configuration directory.
// AppConfig from the alternate location is already loaded.
// User profiles are being merged (old files are not being deleted),
-// while old system bundles are being deleted before newer are copied.
+// while old vendors and cache folders are being deleted before newer are copied.
void PresetBundle::import_newer_configs(const std::string& from)
{
boost::filesystem::path data_dir = boost::filesystem::path(Slic3r::data_dir());
// Clean-up vendors from the target directory, as the existing vendors will not be referenced
// by the copied PrusaSlicer.ini
- boost::filesystem::remove_all(data_dir / "vendor");
+ try {
+ boost::filesystem::remove_all(data_dir / "cache");
+ } catch (const std::exception &ex) {
+ BOOST_LOG_TRIVIAL(error) << "Error deleting old cache " << (data_dir / "cache").string() << ": " << ex.what();
+ }
+ try {
+ boost::filesystem::remove_all(data_dir / "vendor");
+ } catch (const std::exception &ex) {
+ BOOST_LOG_TRIVIAL(error) << "Error deleting old vendors " << (data_dir / "vendor").string() << ": " << ex.what();
+ }
// list of searched paths based on current directory system in setup_directories()
// do not copy cache and snapshots
boost::filesystem::path from_data_dir = boost::filesystem::path(from);
std::initializer_list<boost::filesystem::path> from_dirs= {
+ from_data_dir / "cache",
from_data_dir / "vendor",
from_data_dir / "shapes",
#ifdef SLIC3R_PROFILE_USE_PRESETS_SUBDIR
diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt
index 34cc98051..211a2c2e7 100644
--- a/src/slic3r/CMakeLists.txt
+++ b/src/slic3r/CMakeLists.txt
@@ -258,6 +258,12 @@ endif ()
add_library(libslic3r_gui STATIC ${SLIC3R_GUI_SOURCES})
+foreach(_source IN ITEMS ${SLIC3R_GUI_SOURCES})
+ get_filename_component(_source_path "${_source}" PATH)
+ string(REPLACE "/" "\\" _group_path "${_source_path}")
+ source_group("${_group_path}" FILES "${_source}")
+endforeach()
+
encoding_check(libslic3r_gui)
target_link_libraries(libslic3r_gui libslic3r avrdude cereal imgui GLEW::GLEW OpenGL::GL hidapi libcurl ${wxWidgets_LIBRARIES})
diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index 73936f431..94edc797d 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -1881,6 +1881,12 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
// updates volumes transformations
volume->set_instance_transformation(mvs->model_volume->get_object()->instances[mvs->composite_id.instance_id]->get_transformation());
volume->set_volume_transformation(mvs->model_volume->get_transformation());
+
+ // updates volumes convex hull
+ if (mvs->model_volume->is_model_part() && ! volume->convex_hull())
+ // Model volume was likely changed from modifier or support blocker / enforcer to a model part.
+ // Only model parts require convex hulls.
+ volume->set_convex_hull(mvs->model_volume->get_convex_hull_shared_ptr());
}
}
}
diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp
index 131b9df2a..be628c188 100644
--- a/src/slic3r/GUI/GUI_App.cpp
+++ b/src/slic3r/GUI/GUI_App.cpp
@@ -1081,27 +1081,6 @@ bool GUI_App::on_init_inner()
// Slic3r::debugf "wxWidgets version %s, Wx version %s\n", wxVERSION_STRING, wxVERSION;
-
- if (is_editor()) {
- std::string msg = Http::tls_global_init();
- std::string ssl_cert_store = app_config->get("tls_accepted_cert_store_location");
- bool ssl_accept = app_config->get("tls_cert_store_accepted") == "yes" && ssl_cert_store == Http::tls_system_cert_store();
-
- if (!msg.empty() && !ssl_accept) {
- RichMessageDialog
- dlg(nullptr,
- wxString::Format(_L("%s\nDo you want to continue?"), msg),
- "PrusaSlicer", wxICON_QUESTION | wxYES_NO);
- dlg.ShowCheckBox(_L("Remember my choice"));
- if (dlg.ShowModal() != wxID_YES) return false;
-
- app_config->set("tls_cert_store_accepted",
- dlg.IsCheckBoxChecked() ? "yes" : "no");
- app_config->set("tls_accepted_cert_store_location",
- dlg.IsCheckBoxChecked() ? Http::tls_system_cert_store() : "");
- }
- }
-
// !!! Initialization of UI settings as a language, application color mode, fonts... have to be done before first UI action.
// Like here, before the show InfoDialog in check_older_app_config()
@@ -1139,6 +1118,26 @@ bool GUI_App::on_init_inner()
NppDarkMode::SetSystemMenuForApp(new_sys_menu_enabled);
#endif
+ if (is_editor()) {
+ std::string msg = Http::tls_global_init();
+ std::string ssl_cert_store = app_config->get("tls_accepted_cert_store_location");
+ bool ssl_accept = app_config->get("tls_cert_store_accepted") == "yes" && ssl_cert_store == Http::tls_system_cert_store();
+
+ if (!msg.empty() && !ssl_accept) {
+ RichMessageDialog
+ dlg(nullptr,
+ wxString::Format(_L("%s\nDo you want to continue?"), msg),
+ "PrusaSlicer", wxICON_QUESTION | wxYES_NO);
+ dlg.ShowCheckBox(_L("Remember my choice"));
+ if (dlg.ShowModal() != wxID_YES) return false;
+
+ app_config->set("tls_cert_store_accepted",
+ dlg.IsCheckBoxChecked() ? "yes" : "no");
+ app_config->set("tls_accepted_cert_store_location",
+ dlg.IsCheckBoxChecked() ? Http::tls_system_cert_store() : "");
+ }
+ }
+
SplashScreen* scrn = nullptr;
if (app_config->get("show_splash_screen") == "1") {
// make a bitmap with dark grey banner on the left side
@@ -1730,6 +1729,7 @@ void GUI_App::force_colors_update()
if (WXHWND wxHWND = wxToolTip::GetToolTipCtrl())
NppDarkMode::SetDarkExplorerTheme((HWND)wxHWND);
NppDarkMode::SetDarkTitleBar(mainframe->GetHWND());
+ NppDarkMode::SetDarkTitleBar(mainframe->m_settings_dialog.GetHWND());
#endif //_MSW_DARK_MODE
m_force_colors_update = true;
}
@@ -1749,6 +1749,14 @@ void GUI_App::update_ui_from_settings()
mainframe->printhost_queue_dlg()->force_color_changed();
#ifdef _MSW_DARK_MODE
update_scrolls(mainframe);
+ if (mainframe->is_dlg_layout()) {
+ // update for tabs bar
+ UpdateDarkUI(&mainframe->m_settings_dialog);
+ mainframe->m_settings_dialog.Fit();
+ mainframe->m_settings_dialog.Refresh();
+ // update scrollbars
+ update_scrolls(&mainframe->m_settings_dialog);
+ }
#endif //_MSW_DARK_MODE
}
#endif
diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp
index 160999db3..85ab42119 100644
--- a/src/slic3r/GUI/GUI_ObjectList.cpp
+++ b/src/slic3r/GUI/GUI_ObjectList.cpp
@@ -1398,6 +1398,8 @@ void ObjectList::load_subobject(ModelVolumeType type, bool from_galery/* = false
if (m_objects_model->GetItemType(item)&itInstance)
item = m_objects_model->GetItemById(obj_idx);
+ take_snapshot((type == ModelVolumeType::MODEL_PART) ? _L("Load Part") : _L("Load Modifier"));
+
std::vector<ModelVolume*> volumes;
// ! ysFIXME - delete commented code after testing and rename "load_modifier" to something common
/*
@@ -1409,8 +1411,6 @@ void ObjectList::load_subobject(ModelVolumeType type, bool from_galery/* = false
if (volumes.empty())
return;
- take_snapshot((type == ModelVolumeType::MODEL_PART) ? _L("Load Part") : _L("Load Modifier"));
-
wxDataViewItemArray items = reorder_volumes_and_get_selection(obj_idx, [volumes](const ModelVolume* volume) {
return std::find(volumes.begin(), volumes.end(), volume) != volumes.end(); });
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index b3ec46425..89d74f7bb 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -5707,23 +5707,26 @@ void Plater::export_stl(bool extended, bool selection_only)
return;
// Following lambda generates a combined mesh for export with normals pointing outwards.
- auto mesh_to_export = [](const ModelObject* mo, bool instances) -> TriangleMesh {
+ auto mesh_to_export = [](const ModelObject& mo, int instance_id) {
TriangleMesh mesh;
- for (const ModelVolume *v : mo->volumes)
+ for (const ModelVolume* v : mo.volumes)
if (v->is_model_part()) {
TriangleMesh vol_mesh(v->mesh());
vol_mesh.transform(v->get_matrix(), true);
mesh.merge(vol_mesh);
}
- if (instances) {
+ if (instance_id == -1) {
TriangleMesh vols_mesh(mesh);
mesh = TriangleMesh();
- for (const ModelInstance *i : mo->instances) {
+ for (const ModelInstance* i : mo.instances) {
TriangleMesh m = vols_mesh;
m.transform(i->get_matrix(), true);
mesh.merge(m);
}
}
+ else if (0 <= instance_id && instance_id < mo.instances.size())
+ mesh.transform(mo.instances[instance_id]->get_matrix(), true);
+
return mesh;
};
@@ -5732,14 +5735,8 @@ void Plater::export_stl(bool extended, bool selection_only)
if (selection_only) {
const ModelObject* model_object = p->model.objects[obj_idx];
if (selection.get_mode() == Selection::Instance)
- {
- if (selection.is_single_full_object())
- mesh = mesh_to_export(model_object, true);
- else
- mesh = mesh_to_export(model_object, false);
- }
- else
- {
+ mesh = selection.is_single_full_object() ? mesh_to_export(*model_object, -1) : mesh_to_export(*model_object, selection.get_instance_idx());
+ else {
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
mesh = model_object->volumes[volume->volume_idx()]->mesh();
mesh.transform(volume->get_volume_transformation().get_matrix(), true);
@@ -5747,69 +5744,62 @@ void Plater::export_stl(bool extended, bool selection_only)
}
}
else {
- for (const ModelObject *o : p->model.objects)
- mesh.merge(mesh_to_export(o, true));
+ for (const ModelObject* o : p->model.objects) {
+ mesh.merge(mesh_to_export(*o, -1));
+ }
}
}
- else
- {
+ else {
// This is SLA mode, all objects have only one volume.
// However, we must have a look at the backend to load
// hollowed mesh and/or supports
const PrintObjects& objects = p->sla_print.objects();
- for (const SLAPrintObject* object : objects)
- {
+ for (const SLAPrintObject* object : objects) {
const ModelObject* model_object = object->model_object();
if (selection_only) {
if (model_object->id() != p->model.objects[obj_idx]->id())
continue;
}
- Transform3d mesh_trafo_inv = object->trafo().inverse();
- bool is_left_handed = object->is_left_handed();
+ const Transform3d mesh_trafo_inv = object->trafo().inverse();
+ const bool is_left_handed = object->is_left_handed();
TriangleMesh pad_mesh;
- bool has_pad_mesh = extended && object->has_mesh(slaposPad);
- if (has_pad_mesh)
- {
+ const bool has_pad_mesh = extended && object->has_mesh(slaposPad);
+ if (has_pad_mesh) {
pad_mesh = object->get_mesh(slaposPad);
pad_mesh.transform(mesh_trafo_inv);
}
TriangleMesh supports_mesh;
- bool has_supports_mesh = extended && object->has_mesh(slaposSupportTree);
- if (has_supports_mesh)
- {
+ const bool has_supports_mesh = extended && object->has_mesh(slaposSupportTree);
+ if (has_supports_mesh) {
supports_mesh = object->get_mesh(slaposSupportTree);
supports_mesh.transform(mesh_trafo_inv);
}
const std::vector<SLAPrintObject::Instance>& obj_instances = object->instances();
- for (const SLAPrintObject::Instance& obj_instance : obj_instances)
- {
+ for (const SLAPrintObject::Instance& obj_instance : obj_instances) {
auto it = std::find_if(model_object->instances.begin(), model_object->instances.end(),
[&obj_instance](const ModelInstance *mi) { return mi->id() == obj_instance.instance_id; });
assert(it != model_object->instances.end());
- if (it != model_object->instances.end())
- {
- bool one_inst_only = selection_only && ! selection.is_single_full_object();
+ if (it != model_object->instances.end()) {
+ const bool one_inst_only = selection_only && ! selection.is_single_full_object();
- int instance_idx = it - model_object->instances.begin();
+ const int instance_idx = it - model_object->instances.begin();
const Transform3d& inst_transform = one_inst_only
? Transform3d::Identity()
: object->model_object()->instances[instance_idx]->get_transformation().get_matrix();
TriangleMesh inst_mesh;
- if (has_pad_mesh)
- {
+ if (has_pad_mesh) {
TriangleMesh inst_pad_mesh = pad_mesh;
inst_pad_mesh.transform(inst_transform, is_left_handed);
inst_mesh.merge(inst_pad_mesh);
}
- if (has_supports_mesh)
- {
+ if (has_supports_mesh) {
TriangleMesh inst_supports_mesh = supports_mesh;
inst_supports_mesh.transform(inst_transform, is_left_handed);
inst_mesh.merge(inst_supports_mesh);
diff --git a/src/slic3r/GUI/UpdateDialogs.cpp b/src/slic3r/GUI/UpdateDialogs.cpp
index 367c290d9..f80975ce5 100644
--- a/src/slic3r/GUI/UpdateDialogs.cpp
+++ b/src/slic3r/GUI/UpdateDialogs.cpp
@@ -132,6 +132,7 @@ MsgUpdateConfig::MsgUpdateConfig(const std::vector<Update> &updates, bool force_
line->AddSpacer(3*VERT_SPACING);
line->Add(new wxHyperlinkCtrl(this, wxID_ANY, _(L("Open changelog page")), changelog_url));
versions->Add(line);
+ versions->AddSpacer(1); // empty value for the correct alignment inside a GridSizer
}
}
@@ -189,6 +190,7 @@ MsgUpdateForced::MsgUpdateForced(const std::vector<Update>& updates) :
line->AddSpacer(3 * VERT_SPACING);
line->Add(new wxHyperlinkCtrl(this, wxID_ANY, _(L("Open changelog page")), changelog_url));
versions->Add(line);
+ versions->AddSpacer(1); // empty value for the correct alignment inside a GridSizer
}
}