ultimatepp/uppsrc/CtrlLib/Progress.cpp
cxl 8ebdcbb0d5 uppsrc: NAMESPACE_UPP / END_UPP_NAMESPACE removed
git-svn-id: svn://ultimatepp.org/upp/trunk@10186 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2016-08-26 17:15:30 +00:00

280 lines
5.1 KiB
C++

#include "CtrlLib.h"
namespace Upp {
CH_STYLE(ProgressIndicator, Style, StyleDefault)
{
classic = GUI_GlobalStyle() == GUISTYLE_CLASSIC;
hlook = CtrlsImg::PI();
hchunk = CtrlsImg::PIC();
vlook = CtrlsImg::VPI();
vchunk = CtrlsImg::VPIC();
bound = false;
}
Size ProgressIndicator::GetMsz()
{
Size sz = GetSize();
Rect mg = ChMargins(style->classic || percent || !IsNull(color) ? EditFieldEdge()
: sz.cx > sz.cy ? style->hlook : style->vlook);
sz.cx -= mg.left + mg.right;
sz.cy -= mg.top + mg.bottom;
return sz;
}
void ProgressIndicator::Paint(Draw& w) {
Size sz = GetSize();
Size msz = GetMsz();
int p0 = 0;
int p = pxp;
if(total <= 0) {
int l = max(msz.cx, msz.cy) & ~7;
p0 = pxp - l / 4;
p = min(p - p0, max(msz.cx, msz.cy) - p0);
if(style->bound && p0 < 0) {
p += p0;
p0 = 0;
}
}
if(style->classic || percent || !IsNull(color)) {
ChPaintEdge(w, sz, EditFieldEdge());
Rect mg = ChMargins(EditFieldEdge());
sz -= Size(mg.left + mg.right, mg.top + mg.bottom);
Rect r1, r2, r3;
r1 = r2 = r3 = RectC(mg.left, mg.top, sz.cx, sz.cy);
w.Clip(r1);
if(sz.cx > sz.cy) {
r1.right = r2.left = min(p, sz.cx) + mg.left + p0;
r3.right = mg.left + p0;
r3.bottom = r1.bottom;
}
else {
r2.bottom = r1.top = sz.cy - min(p, sz.cy) + mg.left + p0;
r3.bottom = mg.top + p0;
r3.right = r1.right;
}
w.DrawRect(r1, Nvl(color, SColorHighlight()));
w.DrawRect(r2, SColorPaper);
w.DrawRect(r3, SColorPaper);
if(percent) {
String pt = Format("%d %%", 100 * actual / max(total, 1));
Size psz = GetTextSize(pt, StdFont());
int px = (sz.cx - psz.cx) / 2 + 2;
int py = (sz.cy - psz.cy) / 2 + 2;
w.Clip(r1);
w.DrawText(px, py, pt, StdFont(), SColorLight);
w.End();
w.Clip(r2);
w.DrawText(px, py, pt, StdFont(), SColorText);
w.End();
}
w.End();
}
else {
if(sz.cy > sz.cx) {
ChPaint(w, sz, style->vlook);
Rect r = ChMargins(style->vlook);
w.Clip(r.left, r.top, sz.cx - r.left - r.right, sz.cy - r.top - r.bottom);
ChPaint(w, r.left, sz.cy - r.bottom - p - p0, sz.cx - r.left - r.right, p,
style->vchunk);
}
else {
ChPaint(w, sz, style->hlook);
Rect r = ChMargins(style->hlook);
w.Clip(r.left, r.top, sz.cx - r.left - r.right, sz.cy - r.top - r.bottom);
ChPaint(w, r.left + p0, r.top, p, sz.cy - r.top - r.bottom, style->hchunk);
}
w.End();
}
}
void ProgressIndicator::Layout() {
Set(actual, total);
}
void ProgressIndicator::Set(int _actual, int _total) {
actual = _actual;
total = _total;
Size sz = GetMsz();
int p;
if(total <= 0) {
int l = max(1, max(sz.cx, sz.cy) & ~7);
int p = GetTickCount() / 15 % (l + l / 4);
if(pxp != p) {
pxp = p;
Refresh();
}
return;
}
else {
int l = max(1, max(sz.cx, sz.cy));
p = total ? min(iscale(actual, l, total), l) : 0;
}
if(p != pxp) {
pxp = p;
Refresh();
}
}
ProgressIndicator::ProgressIndicator() {
style = &StyleDefault();
Transparent();
NoWantFocus();
total = actual = 0;
percent = false;
color = Null;
pxp = 0;
}
ProgressIndicator::~ProgressIndicator() {}
void Progress::Reset() {
pos = 0;
total = 0;
cancel = false;
granularity = 50;
show_delay = 250;
set_time = show_time = GetTickCount(); // + 300;
}
void Progress::Init() {
CtrlLayout(*this, t_("Working..."));
stop <<= callback(this, &Progress::Cancel);
info.SetAlign(ALIGN_CENTER);
owner = NULL;
Reset();
}
Progress::Progress() {
Init();
}
Progress::Progress(Ctrl *owner) {
Init();
SetOwner(owner);
}
Progress::Progress(const char *s, int total) {
Init();
text = s;
SetTotal(total);
}
Progress::Progress(Ctrl *owner, const char *s, int total) {
Init();
text = s;
SetTotal(total);
SetOwner(owner);
}
Progress::~Progress() {}
void Progress::Create() {
if(IsPainting() || IsOpen() || cancel)
return;
stop.Hide();
if(owner)
Open(owner);
else
Open();
SetFocus();
Show();
modality.Begin(this);
if(total) Set(pos, total);
Setxt();
Sync();
Process();
}
void Progress::Process()
{
if(!IsOpen()) {
dword t = GetTickCount();
if((int)(t - show_time) >= show_delay) {
Create();
show_time = t;
}
}
if(IsOpen()) {
GuiSleep(0);
ProcessEvents();
}
}
void Progress::Setxt()
{
info = Format(text, pos);
Process();
}
void Progress::Set(int apos, int atotal) {
pos = apos;
total = atotal;
dword t = GetTickCount();
if((int)(t - set_time) < granularity)
return;
set_time = t;
while(atotal > 30000) {
atotal >>= 8;
apos >>= 8;
}
pi.Set(apos, atotal);
Setxt();
Sync();
Process();
}
void Progress::SetTotal(int atotal) {
Set(pos, atotal);
}
void Progress::SetPos(int apos) {
Set(apos, total);
}
void Progress::Step(int n)
{
Set(pos + n, total);
}
void Progress::Close()
{
modality.End();
TopWindow::Close();
}
void Progress::Cancel() {
cancel = true;
Close();
}
bool Progress::Canceled()
{
stop.Show();
Process();
return cancel;
}
bool Progress::SetCanceled(int pos, int total)
{
stop.Show();
Set(pos, total);
return cancel;
}
bool Progress::SetPosCanceled(int pos)
{
stop.Show();
SetPos(pos);
return cancel;
}
bool Progress::StepCanceled(int n)
{
stop.Show();
Step(n);
return cancel;
}
}