klayout/src/tl/tlProgress.h

356 lines
8.4 KiB
C++

/*
KLayout Layout Viewer
Copyright (C) 2006-2017 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef HDR_tlProgress
#define HDR_tlProgress
#include "tlCommon.h"
#include <string>
#include "tlException.h"
#include "tlTimer.h"
namespace tl
{
class Progress;
class TL_PUBLIC ProgressAdaptor
{
public:
ProgressAdaptor ();
virtual ~ProgressAdaptor ();
virtual void register_object (Progress *progress) = 0;
virtual void unregister_object (Progress *progress) = 0;
virtual void trigger (Progress *progress) = 0;
virtual void yield (Progress *progress) = 0;
};
/**
* @brief The "break" exception class
*
* Exceptions of this kind are thrown if a break was encountered
*/
class TL_PUBLIC BreakException
: public tl::Exception
{
public:
BreakException () : tl::Exception ("Operation cancelled") { }
};
class Progress;
/**
* @brief A "progress" reporter class
*
* A progress can be reported in two ways: as
* a relative value with a target "max" values and as
* an absolute value.
* This implementation delegates the actual implementation
* to an "adaptor" class that handles the actual display
* of the progress.
*
* This class also allows for some kind of background processing:
* once the test() method is called, the
* adaptor's yield() method is called once that "yield_interval"
* calls have passed. The yield_interval value should be choosen
* sufficiently large so that no performance penalty is to be paid
* for this. In addition, each test() call tests whether
* the operation may have been cancelled and may throw an
* BreakException in this case.
*
* This class is basically a base class for the actual implementation.
* A functionality every progress object must provide is the
* ability to deliver a relative value and a textual description of
* the progress. By default the progress is displayed as a bar
* showing the relative progress.
*/
class TL_PUBLIC Progress
{
public:
/**
* @brief Constructor
*
* This initializes the progress reporter object.
* The string passed is the initial description and title string.
*
* @param desc The description and title string
* @param yield_interval See above.
*/
Progress (const std::string &desc, size_t yield_interval = 1000);
/**
* @brief The destructor
*/
virtual ~Progress ();
/**
* @brief Delivers the current progress as a string
*/
virtual std::string formatted_value () const = 0;
/**
* @brief Delivers the relative progress (a value between 0 and 100 for 0 to 100%).
*
* The value can be bigger and the default progress bar will wrap around for
* values >= 100.
*/
virtual double value () const = 0;
/**
* @brief Set a value indicating whether the operation can be cancelled
*
* The progress object will throw a BreakException is cancelled and this
* flag is set to true. The default is "true".
*/
void can_cancel (bool f)
{
m_can_cancel = f;
}
/**
* @brief Gets a value indicating whether the operation can be cancelled
*/
bool can_cancel () const
{
return m_can_cancel;
}
/**
* @brief Set the description text
*/
void set_desc (const std::string &desc);
/**
* @brief Render the description string
*/
const std::string &desc () const
{
return m_desc;
}
/**
* @brief Render the title string
*/
const std::string &title () const
{
return m_title;
}
/**
* @brief Used by the adaptor to signal a break condition
*/
void signal_break ();
protected:
/**
* @brief Indicates that a new value has arrived
*
* This method must be called by the derived class.
* If "force_yield" is true, the events are always processed.
*/
void test (bool force_yield = false);
private:
friend class ProgressAdaptor;
std::string m_desc;
std::string m_title;
size_t m_interval_count;
size_t m_yield_interval;
double m_last_value;
bool m_can_cancel;
bool m_cancelled;
tl::Clock m_last_yield;
static tl::ProgressAdaptor *adaptor ();
static void register_adaptor (tl::ProgressAdaptor *pa);
};
/**
* @brief A relative progress value
*
* The relative value is computed from a maximum and current value.
* The ratio is converted to a 0 to 100% completion value.
*/
class TL_PUBLIC RelativeProgress
: public Progress
{
public:
/**
* @brief Constructor
*
* This initializes the progress reporter object.
* The string passed is the initial description and title string.
*
* @param desc The description and title string
* @param max_count The limit "max" value. 0 for absolute display of values.
* @param yield_interval See above.
*/
RelativeProgress (const std::string &desc, size_t max_count = 0, size_t yield_interval = 1000);
/**
* @brief Delivers the current progress as a string
*/
std::string formatted_value () const;
/**
* @brief Delivers the relative progress (a value between 0 and 1 for 0 to 100%).
*
* The value can be bigger and the default progress bar will wrap around for
* values >= 1.
*/
double value () const;
/**
* @brief Set the format of the output.
*
* This is a sprintf format string with the value being
* passed as a single double argument.
*/
void set_format (const std::string &fmt)
{
m_format = fmt;
}
/**
* @brief Increment the count
*/
RelativeProgress &operator++ ()
{
return set (m_count + 1);
}
/**
* @brief Set the count absolutely
*/
RelativeProgress &set (size_t count, bool force_yield = false);
private:
friend class ProgressAdaptor;
std::string m_format;
size_t m_count;
double m_unit;
};
/**
* @brief An absolute progress value
*
* The absolute progress indicates a current value with an unknown upper limit, i.e. the
* file size already read or written.
* The value can be formatted in various ways and the translation into a progress value
* of 0 to 100% can be configured within this class.
*/
class TL_PUBLIC AbsoluteProgress
: public Progress
{
public:
/**
* @brief Constructor
*
* This initializes the progress reporter object.
* The string passed is the initial description and title string.
*
* @param desc The description and title string
* @param yield_interval See above.
*/
AbsoluteProgress (const std::string &desc, size_t yield_interval = 1000);
/**
* @brief Delivers the current progress as a string
*/
std::string formatted_value () const;
/**
* @brief Delivers the relative progress (a value between 0 and 1 for 0 to 100%).
*
* The value can be bigger and the default progress bar will wrap around for
* values >= 1.
*/
double value () const;
/**
* @brief Set the format of the output.
*
* This is a sprintf format string with the value being
* passed as a single double argument.
*/
void set_format (const std::string &fmt)
{
m_format = fmt;
}
/**
* @brief Set the unit
*
* This is the unit of the output. The unit is the
* value by which the current count is divided to render
* the value passed to the format string.
*/
void set_unit (double unit)
{
m_unit = unit;
}
/**
* @brief Set the format unit
*
* This is the unit used for formatted output. This allows to separate the format value
* from the bar value which is percent.
*/
void set_format_unit (double unit)
{
m_format_unit = unit;
}
/**
* @brief Increment the count
*/
AbsoluteProgress &operator++ ()
{
return set (m_count + 1);
}
/**
* @brief Set the count absolutely
*/
AbsoluteProgress &set (size_t count, bool force_yield = false);
private:
friend class ProgressAdaptor;
std::string m_format;
size_t m_count;
double m_unit;
double m_format_unit;
};
}
#endif