diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index e44dfb742b..e2bd6ef653 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -9,6 +9,7 @@ #include "GCode/WipeTower.hpp" #include "ShortestPath.hpp" #include "Print.hpp" +#include "Thread.hpp" #include "Utils.hpp" #include "ClipperUtils.hpp" #include "libslic3r.h" @@ -34,8 +35,6 @@ #include "SVG.hpp" #include -#include -#include // Intel redesigned some TBB interface considerably when merging TBB with their oneAPI set of libraries, see GH #7332. // We are using quite an old TBB 2017 U7. Before we update our build servers, let's use the old API, which is deprecated in up to date TBB. @@ -1469,32 +1468,6 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato print.throw_if_canceled(); } -// For unknown reasons and in sporadic cases when GCode export is processing, some participating thread -// in tbb::parallel_pipeline has not set locales to "C", probably because this thread is newly spawned. -// So in this class method on_scheduler_entry is called for every thread before it starts participating -// in tbb::parallel_pipeline to ensure that locales are set correctly - -// For tbb::parallel_pipeline, it seems that on_scheduler_entry is called for every layer and every filter. -// We ensure using thread-local storage that locales will be set to "C" just once for any participating thread. -class TBBLocalesSetter : public tbb::task_scheduler_observer -{ -public: - TBBLocalesSetter() { this->observe(true); } - ~TBBLocalesSetter() override { this->observe(false); }; - - void on_scheduler_entry(bool is_worker) override - { - if (bool &is_locales_sets = m_is_locales_sets.local(); !is_locales_sets) { - // Set locales of the worker thread to "C". - set_c_locales(); - is_locales_sets = true; - } - } - -private: - tbb::enumerable_thread_specific, tbb::ets_key_usage_type::ets_key_per_instance> m_is_locales_sets{false}; -}; - // Process all layers of all objects (non-sequential mode) with a parallel pipeline: // Generate G-code, run the filters (vase mode, cooling buffer), run the G-code analyser // and export G-code into file. diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index a53aa57834..5a060db09c 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -43,8 +43,6 @@ #define ENABLE_PREVIEW_LAYOUT (1 && ENABLE_2_5_0_ALPHA1) // Enable drawing the items in legend toolbar using icons #define ENABLE_LEGEND_TOOLBAR_ICONS (1 && ENABLE_PREVIEW_LAYOUT) -// Enable coloring of toolpaths in preview by layer time -#define ENABLE_PREVIEW_LAYER_TIME (1 && ENABLE_2_5_0_ALPHA1) // Enable showing time estimate for travel moves in legend #define ENABLE_TRAVEL_TIME (1 && ENABLE_2_5_0_ALPHA1) // Enable removal of wipe tower magic object_id equal to 1000 diff --git a/src/libslic3r/Thread.cpp b/src/libslic3r/Thread.cpp index 4fe07fb590..22d4cb4197 100644 --- a/src/libslic3r/Thread.cpp +++ b/src/libslic3r/Thread.cpp @@ -4,6 +4,9 @@ #else // any posix system #include + #ifdef __APPLE__ + #include + #endif // __APPLE__ #endif #include @@ -241,4 +244,26 @@ void name_tbb_thread_pool_threads_set_locale() }); } +void set_current_thread_qos() +{ +#ifdef __APPLE__ + // OSX specific: Set Quality of Service to "user initiated", so that the threads will be scheduled to high performance + // cores if available. + pthread_set_qos_class_self_np(QOS_CLASS_USER_INITIATED, 0); +#endif // __APPLE__ +} + +void TBBLocalesSetter::on_scheduler_entry(bool is_worker) +{ +// static std::atomic cnt = 0; +// std::cout << "TBBLocalesSetter Entering " << cnt ++ << " ID " << std::this_thread::get_id() << "\n"; + if (bool& is_locales_sets = m_is_locales_sets.local(); !is_locales_sets) { + // Set locales of the worker thread to "C". + set_c_locales(); + // OSX specific: Elevate QOS on Apple Silicon. + set_current_thread_qos(); + is_locales_sets = true; + } +} + } diff --git a/src/libslic3r/Thread.hpp b/src/libslic3r/Thread.hpp index 9afe13b42d..252116ea79 100644 --- a/src/libslic3r/Thread.hpp +++ b/src/libslic3r/Thread.hpp @@ -6,6 +6,9 @@ #include #include +#include +#include + namespace Slic3r { // Set / get thread name. @@ -26,6 +29,10 @@ inline bool set_thread_name(boost::thread &thread, const std::string &thread_nam bool set_current_thread_name(const char *thread_name); inline bool set_current_thread_name(const std::string &thread_name) { return set_current_thread_name(thread_name.c_str()); } +// OSX specific: Set Quality of Service to "user initiated", so that the threads will be scheduled to high performance +// cores if available. +void set_current_thread_qos(); + // Returns nullopt if not supported. // Not supported by OSX. // Naming threads is only supported on newer Windows 10. @@ -53,6 +60,25 @@ template inline boost::thread create_thread(Fn &&fn) return create_thread(attrs, std::forward(fn)); } +// For unknown reasons and in sporadic cases when GCode export is processing, some participating thread +// in tbb::parallel_pipeline has not set locales to "C", probably because this thread is newly spawned. +// So in this class method on_scheduler_entry is called for every thread before it starts participating +// in tbb::parallel_pipeline to ensure that locales are set correctly +// +// For tbb::parallel_pipeline, it seems that on_scheduler_entry is called for every layer and every filter. +// We ensure using thread-local storage that locales will be set to "C" just once for any participating thread. +class TBBLocalesSetter : public tbb::task_scheduler_observer +{ +public: + TBBLocalesSetter() { this->observe(true); } + ~TBBLocalesSetter() override { this->observe(false); }; + + void on_scheduler_entry(bool is_worker) override; + +private: + tbb::enumerable_thread_specific, tbb::ets_key_usage_type::ets_key_per_instance> m_is_locales_sets{ false }; +}; + } #endif // GUI_THREAD_HPP diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.cpp b/src/slic3r/GUI/BackgroundSlicingProcess.cpp index 173d345704..275fcdc986 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.cpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.cpp @@ -211,6 +211,12 @@ void BackgroundSlicingProcess::thread_proc() set_current_thread_name("slic3r_BgSlcPcs"); name_tbb_thread_pool_threads_set_locale(); + // Set "C" locales and enforce OSX QoS level on all threads entering an arena. + // The cost of the callback is quite low: The callback is called once per thread + // entering a parallel loop and the callback is guarded with a thread local + // variable to be executed just once. + TBBLocalesSetter setter; + assert(m_print != nullptr); assert(m_print == m_fff_print || m_print == m_sla_print); std::unique_lock lck(m_mutex); diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 14889fe65a..a15d73a1e3 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -250,7 +250,6 @@ void GCodeViewer::COG::render() //ImGui::PopStyleVar(); } -#if ENABLE_PREVIEW_LAYER_TIME float GCodeViewer::Extrusions::Range::step_size(EType type) const { switch (type) @@ -262,12 +261,8 @@ float GCodeViewer::Extrusions::Range::step_size(EType type) const } ColorRGBA GCodeViewer::Extrusions::Range::get_color_at(float value, EType type) const -#else -ColorRGBA GCodeViewer::Extrusions::Range::get_color_at(float value) const -#endif // ENABLE_PREVIEW_LAYER_TIME { // Input value scaled to the colors range -#if ENABLE_PREVIEW_LAYER_TIME float global_t = 0.0f; const float step = step_size(type); if (step > 0.0f) { @@ -278,10 +273,6 @@ ColorRGBA GCodeViewer::Extrusions::Range::get_color_at(float value) const case EType::Logarithmic: { global_t = (value > min && min > 0.0f) ? ::log(value / min) / step : 0.0f; break; } } } -#else - const float step = step_size(); - const float global_t = (step != 0.0f) ? std::max(0.0f, value - min) / step : 0.0f; // lower limit of 0.0f -#endif // ENABLE_PREVIEW_LAYER_TIME const size_t color_max_idx = Range_Colors.size() - 1; @@ -901,7 +892,6 @@ void GCodeViewer::refresh(const GCodeProcessorResult& gcode_result, const std::v } } -#if ENABLE_PREVIEW_LAYER_TIME for (size_t i = 0; i < gcode_result.print_statistics.modes.size(); ++i) { m_layers_times[i] = gcode_result.print_statistics.modes[i].layers_times; } @@ -911,7 +901,6 @@ void GCodeViewer::refresh(const GCodeProcessorResult& gcode_result, const std::v m_extrusions.ranges.layer_time[i].update_from(time); } } -#endif // ENABLE_PREVIEW_LAYER_TIME #if ENABLE_GCODE_VIEWER_STATISTICS m_statistics.refresh_time = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start_time).count(); @@ -960,11 +949,9 @@ void GCodeViewer::reset() m_layers_z_range = { 0, 0 }; m_roles = std::vector(); m_print_statistics.reset(); -#if ENABLE_PREVIEW_LAYER_TIME for (size_t i = 0; i < static_cast(PrintEstimatedStatistics::ETimeMode::Count); ++i) { m_layers_times[i] = std::vector(); } -#endif // ENABLE_PREVIEW_LAYER_TIME m_custom_gcode_per_print_z = std::vector(); m_sequential_view.gcode_window.reset(); #if ENABLE_GCODE_VIEWER_STATISTICS @@ -2435,7 +2422,6 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool case EViewType::Feedrate: { color = m_extrusions.ranges.feedrate.get_color_at(path.feedrate); break; } case EViewType::FanSpeed: { color = m_extrusions.ranges.fan_speed.get_color_at(path.fan_speed); break; } case EViewType::Temperature: { color = m_extrusions.ranges.temperature.get_color_at(path.temperature); break; } -#if ENABLE_PREVIEW_LAYER_TIME case EViewType::LayerTimeLinear: case EViewType::LayerTimeLogarithmic: { const Path::Sub_Path& sub_path = path.sub_paths.front(); @@ -2454,7 +2440,6 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool } break; } -#endif // ENABLE_PREVIEW_LAYER_TIME case EViewType::VolumetricRate: { color = m_extrusions.ranges.volumetric_rate.get_color_at(path.volumetric_rate); break; } case EViewType::Tool: { color = m_tool_colors[path.extruder_id]; break; } case EViewType::ColorPrint: { @@ -3464,14 +3449,9 @@ void GCodeViewer::render_legend(float& legend_height) }; const PrintEstimatedStatistics::Mode& time_mode = m_print_statistics.modes[static_cast(m_time_estimate_mode)]; -#if ENABLE_PREVIEW_LAYER_TIME bool show_estimated_time = time_mode.time > 0.0f && (m_view_type == EViewType::FeatureType || m_view_type == EViewType::LayerTimeLinear || m_view_type == EViewType::LayerTimeLogarithmic || (m_view_type == EViewType::ColorPrint && !time_mode.custom_gcode_times.empty())); -#else - bool show_estimated_time = time_mode.time > 0.0f && (m_view_type == EViewType::FeatureType || - (m_view_type == EViewType::ColorPrint && !time_mode.custom_gcode_times.empty())); -#endif // ENABLE_PREVIEW_LAYER_TIME const float icon_size = ImGui::GetTextLineHeight(); const float percent_bar_size = 2.0f * ImGui::GetTextLineHeight(); @@ -3613,7 +3593,6 @@ void GCodeViewer::render_legend(float& legend_height) } }; -#if ENABLE_PREVIEW_LAYER_TIME auto append_time_range = [append_item](const Extrusions::Range& range, Extrusions::Range::EType type) { auto append_range_item = [append_item](int i, float value) { std::string str_value = get_time_dhms(value); @@ -3644,7 +3623,6 @@ void GCodeViewer::render_legend(float& legend_height) } } }; -#endif // ENABLE_PREVIEW_LAYER_TIME auto append_headers = [&imgui](const std::array& texts, const std::array& offsets) { size_t i = 0; @@ -3836,10 +3814,8 @@ void GCodeViewer::render_legend(float& legend_height) _u8L("Fan speed (%)"), _u8L("Temperature (°C)"), _u8L("Volumetric flow rate (mm³/s)"), -#if ENABLE_PREVIEW_LAYER_TIME _u8L("Layer time (linear)"), _u8L("Layer time (logarithmic)"), -#endif // ENABLE_PREVIEW_LAYER_TIME _u8L("Tool"), _u8L("Color Print") }, view_type, ImGuiComboFlags_HeightLargest); ImGui::PopStyleColor(2); @@ -3873,10 +3849,8 @@ void GCodeViewer::render_legend(float& legend_height) case EViewType::FanSpeed: { imgui.title(_u8L("Fan Speed (%)")); break; } case EViewType::Temperature: { imgui.title(_u8L("Temperature (°C)")); break; } case EViewType::VolumetricRate: { imgui.title(_u8L("Volumetric flow rate (mm³/s)")); break; } -#if ENABLE_PREVIEW_LAYER_TIME case EViewType::LayerTimeLinear: { imgui.title(_u8L("Layer time (linear)")); break; } case EViewType::LayerTimeLogarithmic: { imgui.title(_u8L("Layer time (logarithmic)")); break; } -#endif // ENABLE_PREVIEW_LAYER_TIME case EViewType::Tool: { append_headers({ _u8L("Tool"), _u8L("Used filament") }, offsets); break; @@ -3931,10 +3905,8 @@ void GCodeViewer::render_legend(float& legend_height) case EViewType::FanSpeed: { append_range(m_extrusions.ranges.fan_speed, 0); break; } case EViewType::Temperature: { append_range(m_extrusions.ranges.temperature, 0); break; } case EViewType::VolumetricRate: { append_range(m_extrusions.ranges.volumetric_rate, 3); break; } -#if ENABLE_PREVIEW_LAYER_TIME case EViewType::LayerTimeLinear: { append_time_range(m_extrusions.ranges.layer_time[static_cast(m_time_estimate_mode)], Extrusions::Range::EType::Linear); break; } case EViewType::LayerTimeLogarithmic: { append_time_range(m_extrusions.ranges.layer_time[static_cast(m_time_estimate_mode)], Extrusions::Range::EType::Logarithmic); break; } -#endif // ENABLE_PREVIEW_LAYER_TIME case EViewType::Tool: { // shows only extruders actually used for (unsigned char extruder_id : m_extruder_ids) { @@ -4275,6 +4247,14 @@ void GCodeViewer::render_legend(float& legend_height) } #endif // !ENABLE_PREVIEW_LAYOUT + auto add_strings_row_to_table = [&imgui](const std::string& col_1, const ImVec4& col_1_color, const std::string& col_2, const ImVec4& col_2_color) { + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + imgui.text_colored(col_1_color, col_1.c_str()); + ImGui::TableSetColumnIndex(1); + imgui.text_colored(col_2_color, col_2.c_str()); + }; + // settings section bool has_settings = false; has_settings |= !m_settings_ids.print.empty(); @@ -4289,47 +4269,37 @@ void GCodeViewer::render_legend(float& legend_height) show_settings &= (m_view_type == EViewType::FeatureType || m_view_type == EViewType::Tool); show_settings &= has_settings; if (show_settings) { - auto calc_offset = [this]() { - float ret = 0.0f; - if (!m_settings_ids.printer.empty()) - ret = std::max(ret, ImGui::CalcTextSize((_u8L("Printer") + std::string(":")).c_str()).x); - if (!m_settings_ids.print.empty()) - ret = std::max(ret, ImGui::CalcTextSize((_u8L("Print settings") + std::string(":")).c_str()).x); - if (!m_settings_ids.filament.empty()) { - for (unsigned char i : m_extruder_ids) { - ret = std::max(ret, ImGui::CalcTextSize((_u8L("Filament") + " " + std::to_string(i + 1) + ":").c_str()).x); - } - } - if (ret > 0.0f) - ret += 2.0f * ImGui::GetStyle().ItemSpacing.x; - return ret; - }; - ImGui::Spacing(); imgui.title(_u8L("Settings")); - float offset = calc_offset(); + auto trim_text_if_needed = [](const std::string& txt) { + const float max_length = 250.0f; + const float length = ImGui::CalcTextSize(txt.c_str()).x; + if (length > max_length) { + const size_t new_len = txt.length() * max_length / length; + return txt.substr(0, new_len) + "..."; + } + return txt; + }; - if (!m_settings_ids.printer.empty()) { - imgui.text(_u8L("Printer") + ":"); - ImGui::SameLine(offset); - imgui.text(m_settings_ids.printer); - } - if (!m_settings_ids.print.empty()) { - imgui.text(_u8L("Print settings") + ":"); - ImGui::SameLine(offset); - imgui.text(m_settings_ids.print); - } - if (!m_settings_ids.filament.empty()) { - for (unsigned char i : m_extruder_ids) { - if (i < static_cast(m_settings_ids.filament.size()) && !m_settings_ids.filament[i].empty()) { - std::string txt = _u8L("Filament"); - txt += (m_extruder_ids.size() == 1) ? ":" : " " + std::to_string(i + 1); - imgui.text(txt); - ImGui::SameLine(offset); - imgui.text(m_settings_ids.filament[i]); + if (ImGui::BeginTable("Settings", 2)) { + if (!m_settings_ids.printer.empty()) + add_strings_row_to_table(_u8L("Printer") + ":", ImGuiWrapper::COL_ORANGE_LIGHT, + trim_text_if_needed(m_settings_ids.printer), ImGuiWrapper::to_ImVec4(ColorRGBA::WHITE())); + if (!m_settings_ids.print.empty()) + add_strings_row_to_table(_u8L("Print settings") + ":", ImGuiWrapper::COL_ORANGE_LIGHT, + trim_text_if_needed(m_settings_ids.print), ImGuiWrapper::to_ImVec4(ColorRGBA::WHITE())); + if (!m_settings_ids.filament.empty()) { + for (unsigned char i : m_extruder_ids) { + if (i < static_cast(m_settings_ids.filament.size()) && !m_settings_ids.filament[i].empty()) { + std::string txt = _u8L("Filament"); + txt += (m_extruder_ids.size() == 1) ? ":" : " " + std::to_string(i + 1); + add_strings_row_to_table(txt, ImGuiWrapper::COL_ORANGE_LIGHT, + trim_text_if_needed(m_settings_ids.filament[i]), ImGuiWrapper::to_ImVec4(ColorRGBA::WHITE())); + } } } + ImGui::EndTable(); } } @@ -4363,33 +4333,24 @@ void GCodeViewer::render_legend(float& legend_height) imgui.title(time_title + ":"); - std::string first_str = _u8L("First layer"); - std::string total_str = _u8L("Total"); + if (ImGui::BeginTable("Times", 2)) { + if (!time_mode.layers_times.empty()) { + add_strings_row_to_table(_u8L("First layer") + ":", ImGuiWrapper::COL_ORANGE_LIGHT, + short_time(get_time_dhms(time_mode.layers_times.front())), ImGuiWrapper::to_ImVec4(ColorRGBA::WHITE())); + } - float max_len = 10.0f + ImGui::GetStyle().ItemSpacing.x; - if (time_mode.layers_times.empty()) - max_len += ImGui::CalcTextSize(total_str.c_str()).x; - else - max_len += std::max(ImGui::CalcTextSize(first_str.c_str()).x, ImGui::CalcTextSize(total_str.c_str()).x); + add_strings_row_to_table(_u8L("Total") + ":", ImGuiWrapper::COL_ORANGE_LIGHT, + short_time(get_time_dhms(time_mode.time)), ImGuiWrapper::to_ImVec4(ColorRGBA::WHITE())); - if (!time_mode.layers_times.empty()) { - imgui.text(first_str + ":"); - ImGui::SameLine(max_len); - imgui.text(short_time(get_time_dhms(time_mode.layers_times.front()))); + ImGui::EndTable(); } - imgui.text(total_str + ":"); - ImGui::SameLine(max_len); - imgui.text(short_time(get_time_dhms(time_mode.time))); - auto show_mode_button = [this, &imgui, can_show_mode_button](const wxString& label, PrintEstimatedStatistics::ETimeMode mode) { if (can_show_mode_button(mode)) { if (imgui.button(label)) { m_time_estimate_mode = mode; -#if ENABLE_PREVIEW_LAYER_TIME if (m_view_type == EViewType::LayerTimeLinear || m_view_type == EViewType::LayerTimeLogarithmic) refresh_render_paths(false, false); -#endif // ENABLE_PREVIEW_LAYER_TIME imgui.set_requires_extra_frame(); } } diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index d10936fe33..6f7f015603 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -432,13 +432,11 @@ class GCodeViewer { struct Range { -#if ENABLE_PREVIEW_LAYER_TIME enum class EType : unsigned char { Linear, Logarithmic }; -#endif // ENABLE_PREVIEW_LAYER_TIME float min; float max; @@ -454,13 +452,8 @@ class GCodeViewer } void reset() { min = FLT_MAX; max = -FLT_MAX; count = 0; } -#if ENABLE_PREVIEW_LAYER_TIME float step_size(EType type = EType::Linear) const; ColorRGBA get_color_at(float value, EType type = EType::Linear) const; -#else - float step_size() const { return (max - min) / (static_cast(Range_Colors.size()) - 1.0f); } - ColorRGBA get_color_at(float value) const; -#endif // ENABLE_PREVIEW_LAYER_TIME }; struct Ranges @@ -477,10 +470,8 @@ class GCodeViewer Range volumetric_rate; // Color mapping by extrusion temperature. Range temperature; -#if ENABLE_PREVIEW_LAYER_TIME // Color mapping by layer time. std::array(PrintEstimatedStatistics::ETimeMode::Count)> layer_time; -#endif // ENABLE_PREVIEW_LAYER_TIME void reset() { height.reset(); @@ -489,11 +480,9 @@ class GCodeViewer fan_speed.reset(); volumetric_rate.reset(); temperature.reset(); -#if ENABLE_PREVIEW_LAYER_TIME for (auto& range : layer_time) { range.reset(); } -#endif // ENABLE_PREVIEW_LAYER_TIME } }; @@ -752,10 +741,8 @@ public: FanSpeed, Temperature, VolumetricRate, -#if ENABLE_PREVIEW_LAYER_TIME LayerTimeLinear, LayerTimeLogarithmic, -#endif // ENABLE_PREVIEW_LAYER_TIME Tool, ColorPrint, Count @@ -801,9 +788,7 @@ private: #endif // ENABLE_GCODE_VIEWER_STATISTICS GCodeProcessorResult::SettingsIds m_settings_ids; std::array m_sequential_range_caps; -#if ENABLE_PREVIEW_LAYER_TIME std::array, static_cast(PrintEstimatedStatistics::ETimeMode::Count)> m_layers_times; -#endif // ENABLE_PREVIEW_LAYER_TIME std::vector m_custom_gcode_per_print_z; diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 4989d12eed..4f965e604c 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -222,10 +222,8 @@ bool Preview::init(wxWindow* parent, Bed3D& bed, Model* model) m_choice_view_type->Append(_L("Fan speed")); m_choice_view_type->Append(_L("Temperature")); m_choice_view_type->Append(_L("Volumetric flow rate")); -#if ENABLE_PREVIEW_LAYER_TIME m_choice_view_type->Append(_L("Layer time (linear)")); m_choice_view_type->Append(_L("Layer time (logarithmic)")); -#endif // ENABLE_PREVIEW_LAYER_TIME m_choice_view_type->Append(_L("Tool")); m_choice_view_type->Append(_L("Color Print")); m_choice_view_type->SetSelection(0);