Almost working c++ status bar

Signed-off-by: tamasmeszaros <meszaros.q@gmail.com>
This commit is contained in:
tamasmeszaros 2018-08-29 18:02:10 +02:00
parent 5ee106fbf9
commit 9e2d48ff3b
13 changed files with 442 additions and 156 deletions

View File

@ -62,13 +62,14 @@ sub new {
eval { Wx::ToolTip::SetAutoPop(32767) }; eval { Wx::ToolTip::SetAutoPop(32767) };
# initialize status bar # initialize status bar
$self->{statusbar} = Slic3r::GUI::ProgressStatusBar->new($self, Wx::NewId); $self->{statusbar} = Slic3r::GUI::ProgressStatusBar->new();
# $self->{statusbar}->SetParent($self, Wx::NewId);
$self->{statusbar}->Embed;
$self->{statusbar}->SetStatusText(L("Version ").$Slic3r::VERSION.L(" - Remember to check for updates at http://github.com/prusa3d/slic3r/releases")); $self->{statusbar}->SetStatusText(L("Version ").$Slic3r::VERSION.L(" - Remember to check for updates at http://github.com/prusa3d/slic3r/releases"));
$self->SetStatusBar($self->{statusbar});
# Make the global status bar and its progress indicator available in C++ # Make the global status bar and its progress indicator available in C++
$appController->set_global_progress_indicator( $appController->set_global_progress_indicator(
$self->{statusbar}->{prog}->GetId(), $self->{statusbar}->GetProgId(),
$self->{statusbar}->GetId(), $self->{statusbar}->GetId(),
); );

View File

@ -4,141 +4,143 @@ package Slic3r::GUI::ProgressStatusBar;
use strict; use strict;
use warnings; use warnings;
use Wx qw(:gauge :misc); # use Wx qw(:gauge :misc);
use base 'Wx::StatusBar'; # use base 'Wx::StatusBar';
sub new { our $cancel_cb;
my $class = shift;
my $self = $class->SUPER::new(@_);
$self->{busy} = 0; # sub new {
$self->{timer} = Wx::Timer->new($self); # my $class = shift;
$self->{prog} = Wx::Gauge->new($self, wxGA_HORIZONTAL, 100, wxDefaultPosition, wxDefaultSize); # my $self = $class->SUPER::new(@_);
$self->{prog}->Hide;
$self->{cancelbutton} = Wx::Button->new($self, -1, "Cancel", wxDefaultPosition, wxDefaultSize);
$self->{cancelbutton}->Hide;
$self->SetFieldsCount(3); # $self->{busy} = 0;
$self->SetStatusWidths(-1, 150, 155); # $self->{timer} = Wx::Timer->new($self);
# $self->{prog} = Wx::Gauge->new($self, wxGA_HORIZONTAL, 100, wxDefaultPosition, wxDefaultSize);
# $self->{prog}->Hide;
# $self->{cancelbutton} = Wx::Button->new($self, -1, "Cancel", wxDefaultPosition, wxDefaultSize);
# $self->{cancelbutton}->Hide;
Wx::Event::EVT_TIMER($self, \&OnTimer, $self->{timer}); # $self->SetFieldsCount(3);
Wx::Event::EVT_SIZE($self, \&OnSize); # $self->SetStatusWidths(-1, 150, 155);
Wx::Event::EVT_BUTTON($self, $self->{cancelbutton}, sub {
$self->{cancel_cb}->();
$self->{cancelbutton}->Hide;
});
return $self; # Wx::Event::EVT_TIMER($self, \&OnTimer, $self->{timer});
} # Wx::Event::EVT_SIZE($self, \&OnSize);
# Wx::Event::EVT_BUTTON($self, $self->{cancelbutton}, sub {
# $self->{cancel_cb}->();
# $self->{cancelbutton}->Hide;
# });
sub DESTROY { # return $self;
my $self = shift; # }
$self->{timer}->Stop if $self->{timer} && $self->{timer}->IsRunning;
}
sub OnSize { # sub DESTROY {
my ($self, $event) = @_; # my $self = shift;
# $self->{timer}->Stop if $self->{timer} && $self->{timer}->IsRunning;
# }
my %fields = ( # sub OnSize {
# 0 is reserved for status text # my ($self, $event) = @_;
1 => $self->{cancelbutton},
2 => $self->{prog},
);
foreach (keys %fields) { # my %fields = (
my $rect = $self->GetFieldRect($_); # # 0 is reserved for status text
my $offset = &Wx::wxGTK ? 1 : 0; # add a cosmetic 1 pixel offset on wxGTK # 1 => $self->{cancelbutton},
my $pos = [$rect->GetX + $offset, $rect->GetY + $offset]; # 2 => $self->{prog},
$fields{$_}->Move($pos); # );
$fields{$_}->SetSize($rect->GetWidth - $offset, $rect->GetHeight);
}
$event->Skip; # foreach (keys %fields) {
} # my $rect = $self->GetFieldRect($_);
# my $offset = &Wx::wxGTK ? 1 : 0; # add a cosmetic 1 pixel offset on wxGTK
# my $pos = [$rect->GetX + $offset, $rect->GetY + $offset];
# $fields{$_}->Move($pos);
# $fields{$_}->SetSize($rect->GetWidth - $offset, $rect->GetHeight);
# }
sub OnTimer { # $event->Skip;
my ($self, $event) = @_; # }
if ($self->{prog}->IsShown) { # sub OnTimer {
$self->{timer}->Stop; # my ($self, $event) = @_;
}
$self->{prog}->Pulse if $self->{_busy}; # if ($self->{prog}->IsShown) {
} # $self->{timer}->Stop;
# }
# $self->{prog}->Pulse if $self->{_busy};
# }
sub SetCancelCallback { sub SetCancelCallback {
my $self = shift; my $self = shift;
my ($cb) = @_; my ($cb) = @_;
$self->{cancel_cb} = $cb; $cancel_cb = $cb;
$cb ? $self->{cancelbutton}->Show : $self->{cancelbutton}->Hide; # $cb ? $self->{cancelbutton}->Show : $self->{cancelbutton}->Hide;
} }
sub Run { # sub Run {
my $self = shift; # my $self = shift;
my $rate = shift || 100; # my $rate = shift || 100;
if (!$self->{timer}->IsRunning) { # if (!$self->{timer}->IsRunning) {
$self->{timer}->Start($rate); # $self->{timer}->Start($rate);
} # }
} # }
sub GetProgress { # sub GetProgress {
my $self = shift; # my $self = shift;
return $self->{prog}->GetValue; # return $self->{prog}->GetValue;
} # }
sub SetProgress { # sub SetProgress {
my $self = shift; # my $self = shift;
my ($val) = @_; # my ($val) = @_;
if (!$self->{prog}->IsShown) { # if (!$self->{prog}->IsShown) {
$self->ShowProgress(1); # $self->ShowProgress(1);
} # }
if ($val == $self->{prog}->GetRange) { # if ($val == $self->{prog}->GetRange) {
$self->{prog}->SetValue(0); # $self->{prog}->SetValue(0);
$self->ShowProgress(0); # $self->ShowProgress(0);
} else { # } else {
$self->{prog}->SetValue($val); # $self->{prog}->SetValue($val);
} # }
} # }
sub SetRange { # sub SetRange {
my $self = shift; # my $self = shift;
my ($val) = @_; # my ($val) = @_;
if ($val != $self->{prog}->GetRange) { # if ($val != $self->{prog}->GetRange) {
$self->{prog}->SetRange($val); # $self->{prog}->SetRange($val);
} # }
} # }
sub ShowProgress { # sub ShowProgress {
my $self = shift; # my $self = shift;
my ($show) = @_; # my ($show) = @_;
$self->{prog}->Show($show); # $self->{prog}->Show($show);
$self->{prog}->Pulse; # $self->{prog}->Pulse;
} # }
sub StartBusy { # sub StartBusy {
my $self = shift; # my $self = shift;
my $rate = shift || 100; # my $rate = shift || 100;
$self->{_busy} = 1; # $self->{_busy} = 1;
$self->ShowProgress(1); # $self->ShowProgress(1);
if (!$self->{timer}->IsRunning) { # if (!$self->{timer}->IsRunning) {
$self->{timer}->Start($rate); # $self->{timer}->Start($rate);
} # }
} # }
sub StopBusy { # sub StopBusy {
my $self = shift; # my $self = shift;
$self->{timer}->Stop; # $self->{timer}->Stop;
$self->ShowProgress(0); # $self->ShowProgress(0);
$self->{prog}->SetValue(0); # $self->{prog}->SetValue(0);
$self->{_busy} = 0; # $self->{_busy} = 0;
} # }
sub IsBusy { # sub IsBusy {
my $self = shift; # my $self = shift;
return $self->{_busy}; # return $self->{_busy};
} # }
1; 1;

View File

@ -247,6 +247,8 @@ add_library(libslic3r_gui STATIC
${LIBDIR}/slic3r/GUI/UpdateDialogs.hpp ${LIBDIR}/slic3r/GUI/UpdateDialogs.hpp
${LIBDIR}/slic3r/GUI/FirmwareDialog.cpp ${LIBDIR}/slic3r/GUI/FirmwareDialog.cpp
${LIBDIR}/slic3r/GUI/FirmwareDialog.hpp ${LIBDIR}/slic3r/GUI/FirmwareDialog.hpp
${LIBDIR}/slic3r/GUI/ProgressStatusBar.hpp
${LIBDIR}/slic3r/GUI/ProgressStatusBar.cpp
${LIBDIR}/slic3r/Utils/Http.cpp ${LIBDIR}/slic3r/Utils/Http.cpp
${LIBDIR}/slic3r/Utils/Http.hpp ${LIBDIR}/slic3r/Utils/Http.hpp
${LIBDIR}/slic3r/Utils/FixModelByWin10.cpp ${LIBDIR}/slic3r/Utils/FixModelByWin10.cpp
@ -267,7 +269,7 @@ add_library(libslic3r_gui STATIC
${LIBDIR}/slic3r/Utils/Time.hpp ${LIBDIR}/slic3r/Utils/Time.hpp
${LIBDIR}/slic3r/Utils/HexFile.cpp ${LIBDIR}/slic3r/Utils/HexFile.cpp
${LIBDIR}/slic3r/Utils/HexFile.hpp ${LIBDIR}/slic3r/Utils/HexFile.hpp
${LIBDIR}/slic3r/IProgressIndicator.hpp ${LIBDIR}/slic3r/ProgressIndicator.hpp
${LIBDIR}/slic3r/AppController.hpp ${LIBDIR}/slic3r/AppController.hpp
${LIBDIR}/slic3r/AppController.cpp ${LIBDIR}/slic3r/AppController.cpp
${LIBDIR}/slic3r/AppControllerWx.cpp ${LIBDIR}/slic3r/AppControllerWx.cpp
@ -420,6 +422,7 @@ set(XS_XSP_FILES
${XSP_DIR}/Utils_PrintHost.xsp ${XSP_DIR}/Utils_PrintHost.xsp
${XSP_DIR}/Utils_PresetUpdater.xsp ${XSP_DIR}/Utils_PresetUpdater.xsp
${XSP_DIR}/AppController.xsp ${XSP_DIR}/AppController.xsp
${XSP_DIR}/ProgressStatusBar.xsp
${XSP_DIR}/XS.xsp ${XSP_DIR}/XS.xsp
) )
foreach (file ${XS_XSP_FILES}) foreach (file ${XS_XSP_FILES})

View File

@ -63,6 +63,7 @@ REGISTER_CLASS(Preset, "GUI::Preset");
REGISTER_CLASS(PresetCollection, "GUI::PresetCollection"); REGISTER_CLASS(PresetCollection, "GUI::PresetCollection");
REGISTER_CLASS(PresetBundle, "GUI::PresetBundle"); REGISTER_CLASS(PresetBundle, "GUI::PresetBundle");
REGISTER_CLASS(TabIface, "GUI::Tab"); REGISTER_CLASS(TabIface, "GUI::Tab");
REGISTER_CLASS(ProgressStatusBar, "GUI::ProgressStatusBar");
REGISTER_CLASS(PresetUpdater, "PresetUpdater"); REGISTER_CLASS(PresetUpdater, "PresetUpdater");
REGISTER_CLASS(AppController, "AppController"); REGISTER_CLASS(AppController, "AppController");
REGISTER_CLASS(PrintController, "PrintController"); REGISTER_CLASS(PrintController, "PrintController");

View File

@ -289,10 +289,6 @@ const PrintConfig &PrintController::config() const
} }
void AppController::arrange_model() void AppController::arrange_model()
{
auto ftr = std::async(
supports_asynch()? std::launch::async : std::launch::deferred,
[this]()
{ {
using Coord = libnest2d::TCoord<libnest2d::PointImpl>; using Coord = libnest2d::TCoord<libnest2d::PointImpl>;
@ -341,17 +337,39 @@ void AppController::arrange_model()
_(L("Exception occurred"))); _(L("Exception occurred")));
} }
// Create the arranger config
auto min_obj_distance = static_cast<Coord>(dist/SCALING_FACTOR);
auto& bedpoints = print_ctl()->config().bed_shape.values;
Polyline bed; bed.points.reserve(bedpoints.size());
for(auto& v : bedpoints)
bed.append(Point::new_scale(v(0), v(1)));
if(pind) pind->update(0, _(L("Arranging objects...")));
try {
arr::arrange(*model_,
min_obj_distance,
bed,
arr::BOX,
false, // create many piles not just one pile
[pind, count](unsigned rem) {
if(pind)
pind->update(count - rem, _(L("Arranging objects...")));
});
} catch(std::exception& e) {
std::cerr << e.what() << std::endl;
report_issue(IssueType::ERR,
_(L("Could not arrange model objects! "
"Some geometries may be invalid.")),
_(L("Exception occurred")));
}
// Restore previous max value // Restore previous max value
if(pind) { if(pind) {
pind->max(pmax); pind->max(pmax);
pind->update(0, _(L("Arranging done."))); pind->update(0, _(L("Arranging done.")));
} }
});
while( ftr.wait_for(std::chrono::milliseconds(10))
!= std::future_status::ready) {
process_events();
}
} }
} }

View File

@ -7,7 +7,7 @@
#include <atomic> #include <atomic>
#include <iostream> #include <iostream>
#include "IProgressIndicator.hpp" #include "ProgressIndicator.hpp"
namespace Slic3r { namespace Slic3r {
@ -33,7 +33,7 @@ class AppControllerBoilerplate {
public: public:
/// A Progress indicator object smart pointer /// A Progress indicator object smart pointer
using ProgresIndicatorPtr = std::shared_ptr<IProgressIndicator>; using ProgresIndicatorPtr = std::shared_ptr<ProgressIndicator>;
private: private:
class PriData; // Some structure to store progress indication data class PriData; // Some structure to store progress indication data

View File

@ -104,10 +104,10 @@ namespace {
* the main thread as well. * the main thread as well.
*/ */
class GuiProgressIndicator: class GuiProgressIndicator:
public IProgressIndicator, public wxEvtHandler { public ProgressIndicator, public wxEvtHandler {
wxProgressDialog gauge_; wxProgressDialog gauge_;
using Base = IProgressIndicator; using Base = ProgressIndicator;
wxString message_; wxString message_;
int range_; wxString title_; int range_; wxString title_;
bool is_asynch_ = false; bool is_asynch_ = false;
@ -153,7 +153,7 @@ public:
virtual void cancel() override { virtual void cancel() override {
update(max(), "Abort"); update(max(), "Abort");
IProgressIndicator::cancel(); ProgressIndicator::cancel();
} }
virtual void state(float val) override { virtual void state(float val) override {
@ -211,10 +211,10 @@ AppControllerBoilerplate::create_progress_indicator(unsigned statenum,
namespace { namespace {
// A wrapper progress indicator class around the statusbar created in perl. // A wrapper progress indicator class around the statusbar created in perl.
class Wrapper: public IProgressIndicator, public wxEvtHandler { class Wrapper: public ProgressIndicator, public wxEvtHandler {
wxGauge *gauge_; wxGauge *gauge_;
wxStatusBar *stbar_; wxStatusBar *stbar_;
using Base = IProgressIndicator; using Base = ProgressIndicator;
std::string message_; std::string message_;
AppControllerBoilerplate& ctl_; AppControllerBoilerplate& ctl_;
@ -223,7 +223,7 @@ class Wrapper: public IProgressIndicator, public wxEvtHandler {
} }
void _state(unsigned st) { void _state(unsigned st) {
if( st <= IProgressIndicator::max() ) { if( st <= ProgressIndicator::max() ) {
Base::state(st); Base::state(st);
if(!gauge_->IsShown()) showProgress(true); if(!gauge_->IsShown()) showProgress(true);
@ -266,7 +266,7 @@ public:
virtual void max(float val) override { virtual void max(float val) override {
if(val > 1.0) { if(val > 1.0) {
gauge_->SetRange(static_cast<int>(val)); gauge_->SetRange(static_cast<int>(val));
IProgressIndicator::max(val); ProgressIndicator::max(val);
} }
} }

View File

@ -0,0 +1,156 @@
#include "ProgressStatusBar.hpp"
#include <wx/timer.h>
#include <wx/gauge.h>
#include <wx/button.h>
#include <wx/statusbr.h>
#include <wx/frame.h>
#include "GUI.hpp"
#include <iostream>
namespace Slic3r {
ProgressStatusBar::ProgressStatusBar(wxWindow *parent, int id):
self(new wxStatusBar(parent ? parent : GUI::get_main_frame(),
id == -1? wxID_ANY : id)),
timer_(new wxTimer(self)),
prog_ (new wxGauge(self,
wxGA_HORIZONTAL,
100,
wxDefaultPosition,
wxDefaultSize)),
cancelbutton_(new wxButton(self,
-1,
"Cancel",
wxDefaultPosition,
wxDefaultSize))
{
prog_->Hide();
cancelbutton_->Hide();
self->SetFieldsCount(3);
int w[] = {-1, 150, 155};
self->SetStatusWidths(3, w);
self->Bind(wxEVT_TIMER, [this](const wxTimerEvent&) {
if (prog_->IsShown()) timer_->Stop();
if(is_busy()) prog_->Pulse();
});
self->Bind(wxEVT_SIZE, [this](wxSizeEvent& event){
wxRect rect;
self->GetFieldRect(1, rect);
auto offset = 0;
cancelbutton_->Move(rect.GetX() + offset, rect.GetY() + offset);
cancelbutton_->SetSize(rect.GetWidth() - offset, rect.GetHeight());
self->GetFieldRect(2, rect);
prog_->Move(rect.GetX() + offset, rect.GetY() + offset);
prog_->SetSize(rect.GetWidth() - offset, rect.GetHeight());
event.Skip();
});
cancelbutton_->Bind(wxEVT_BUTTON, [this](const wxCommandEvent&) {
if(cancel_cb_) cancel_cb_();
cancelbutton_->Hide();
});
}
//ProgressStatusBar::ProgressStatusBar(): ProgressStatusBar(nullptr, wxID_ANY)
//{
//}
ProgressStatusBar::~ProgressStatusBar() {
if(timer_->IsRunning()) timer_->Stop();
}
int ProgressStatusBar::get_progress() const
{
return prog_->GetValue();
}
void ProgressStatusBar::set_progress(int val)
{
if(!prog_->IsShown()) show_progress(true);
if(val == prog_->GetRange()) {
prog_->SetValue(0);
show_progress(false);
} else {
prog_->SetValue(val);
}
}
void ProgressStatusBar::set_range(int val)
{
if(val != prog_->GetRange()) {
prog_->SetRange(val);
}
}
void ProgressStatusBar::show_progress(bool show)
{
prog_->Show(show);
prog_->Pulse();
}
void ProgressStatusBar::start_busy(int rate)
{
busy_ = true;
show_progress(true);
if (!timer_->IsRunning()) {
timer_->Start(rate);
}
}
void ProgressStatusBar::stop_busy()
{
timer_->Stop();
show_progress(false);
prog_->SetValue(0);
busy_ = false;
}
void ProgressStatusBar::set_cancel_callback(ProgressStatusBar::CancelFn ccb) {
cancel_cb_ = ccb;
if(ccb) cancelbutton_->Show();
else cancelbutton_->Hide();
}
void ProgressStatusBar::run(int rate)
{
if(!timer_->IsRunning()) {
timer_->Start(rate);
}
}
void ProgressStatusBar::Embed()
{
std::cout << "Embedding" << std::endl;
wxFrame* mf = GUI::get_main_frame();
std::cout << mf->GetName() << std::endl;
std::cout << self->GetName() << std::endl;
mf->SetStatusBar(self);
}
void ProgressStatusBar::SetStatusText(std::string txt)
{
self->SetStatusText(txt);
}
int ProgressStatusBar::GetId()
{
return self->GetId();
}
int ProgressStatusBar::GetProgId()
{
return prog_->GetId();
}
}

View File

@ -0,0 +1,61 @@
#ifndef PROGRESSSTATUSBAR_HPP
#define PROGRESSSTATUSBAR_HPP
#include <memory>
#include <functional>
class wxTimer;
class wxGauge;
class wxButton;
class wxTimerEvent;
class wxStatusBar;
class wxWindow;
namespace Slic3r {
/**
* @brief The ProgressStatusBar class is the widgets occupying the lower area
* of the Slicer main window. It consists of a message area to the left and a
* progress indication area to the right with an optional cancel button.
*/
class ProgressStatusBar {
wxStatusBar *self; // we cheat! It should be the base class but: perl!
wxTimer *timer_;
wxGauge *prog_;
wxButton *cancelbutton_;
public:
/// Cancel callback function type
using CancelFn = std::function<void()>;
ProgressStatusBar(wxWindow *parent = nullptr, int id = -1);
~ProgressStatusBar();
int get_progress() const;
void set_progress(int);
void set_range(int = 100);
void show_progress(bool);
void start_busy(int = 100);
void stop_busy();
inline bool is_busy() const { return busy_; }
void set_cancel_callback(CancelFn);
void run(int rate);
// Temporary methods to satisfy Perl side
void Embed();
void SetStatusText(std::string txt);
int GetId();
int GetProgId();
private:
bool busy_ = false;
CancelFn cancel_cb_;
};
namespace GUI {
using Slic3r::ProgressStatusBar;
}
}
#endif // PROGRESSSTATUSBAR_HPP

View File

@ -10,7 +10,7 @@ namespace Slic3r {
/** /**
* @brief Generic progress indication interface. * @brief Generic progress indication interface.
*/ */
class IProgressIndicator { class ProgressIndicator {
public: public:
using CancelFn = std::function<void(void)>; // Cancel functio signature. using CancelFn = std::function<void(void)>; // Cancel functio signature.
@ -20,7 +20,7 @@ private:
public: public:
inline virtual ~IProgressIndicator() {} inline virtual ~ProgressIndicator() {}
/// Get the maximum of the progress range. /// Get the maximum of the progress range.
float max() const { return max_; } float max() const { return max_; }

View File

@ -0,0 +1,41 @@
%module{Slic3r::XS};
%{
#include <xsinit.h>
#include "slic3r/GUI/ProgressStatusBar.hpp"
%}
%name{Slic3r::GUI::ProgressStatusBar} class ProgressStatusBar {
ProgressStatusBar();
~ProgressStatusBar();
int GetProgress() const
%code%{ RETVAL=THIS->get_progress(); %};
void SetProgress(int val)
%code%{ THIS->set_progress(val); %};
void SetRange(int val = 100)
%code%{ THIS->set_range(val); %};
void ShowProgress(bool show)
%code%{ THIS->show_progress(show); %};
void StartBusy(int val = 100)
%code%{ THIS->start_busy(val); %};
void StopBusy()
%code%{ THIS->stop_busy(); %};
bool IsBusy() const
%code%{ RETVAL=THIS->is_busy(); %};
void Run(int rate)
%code%{ THIS->run(rate); %};
void Embed();
void SetStatusText(std::string txt);
int GetId();
int GetProgId();
};

View File

@ -235,6 +235,8 @@ PresetBundle* O_OBJECT_SLIC3R
Ref<PresetBundle> O_OBJECT_SLIC3R_T Ref<PresetBundle> O_OBJECT_SLIC3R_T
TabIface* O_OBJECT_SLIC3R TabIface* O_OBJECT_SLIC3R
Ref<TabIface> O_OBJECT_SLIC3R_T Ref<TabIface> O_OBJECT_SLIC3R_T
ProgressStatusBar* O_OBJECT_SLIC3R
Ref<ProgressStatusBar> O_OBJECT_SLIC3R_T
PresetUpdater* O_OBJECT_SLIC3R PresetUpdater* O_OBJECT_SLIC3R
Ref<PresetUpdater> O_OBJECT_SLIC3R_T Ref<PresetUpdater> O_OBJECT_SLIC3R_T

View File

@ -213,6 +213,7 @@
%typemap{PresetHints*}; %typemap{PresetHints*};
%typemap{Ref<PresetHints>}{simple}; %typemap{Ref<PresetHints>}{simple};
%typemap{TabIface*}; %typemap{TabIface*};
%typemap{ProgressStatusBar*};
%typemap{PrintRegionPtrs*}; %typemap{PrintRegionPtrs*};
%typemap{PrintObjectPtrs*}; %typemap{PrintObjectPtrs*};