2019-01-23 18:41:12 +00:00
|
|
|
/*
|
|
|
|
Copyright 2019 Wolfgang Thaller.
|
|
|
|
|
|
|
|
This file is part of Retro68.
|
|
|
|
|
|
|
|
Retro68 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 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
Retro68 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 Retro68. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2018-05-06 16:49:43 +00:00
|
|
|
#include "StatusDisplay.h"
|
2019-08-18 10:31:32 +00:00
|
|
|
#include "SystemInfo.h"
|
|
|
|
|
2018-05-06 16:49:43 +00:00
|
|
|
#include <Quickdraw.h>
|
|
|
|
#include <Windows.h>
|
2018-05-07 20:39:24 +00:00
|
|
|
#include <string.h>
|
2019-08-18 10:31:32 +00:00
|
|
|
#include <algorithm>
|
2018-05-07 20:39:24 +00:00
|
|
|
|
|
|
|
const short tableTop = 50;
|
|
|
|
const short tableLineHeight = 20;
|
|
|
|
const short tableBaseline = 15;
|
|
|
|
|
|
|
|
enum class StatusDisplay::Stat : short
|
|
|
|
{
|
|
|
|
heapSize,
|
|
|
|
freeMem,
|
|
|
|
fileSize,
|
|
|
|
transferred,
|
|
|
|
speed,
|
|
|
|
timeRemaining,
|
|
|
|
transmissionErrors
|
|
|
|
};
|
2018-05-06 16:49:43 +00:00
|
|
|
|
|
|
|
StatusDisplay::StatusDisplay()
|
|
|
|
{
|
2018-05-16 22:38:55 +00:00
|
|
|
statusWindow = hasColorQD ?
|
|
|
|
GetNewCWindow(129, NULL, (WindowPtr) -1)
|
|
|
|
: GetNewWindow(129, NULL, (WindowPtr) -1);
|
2018-05-19 12:55:27 +00:00
|
|
|
SetWRefCon(statusWindow, reinterpret_cast<long>(static_cast<Window*>(this)));
|
2018-05-06 16:49:43 +00:00
|
|
|
|
2018-05-14 21:58:11 +00:00
|
|
|
#if TARGET_API_MAC_CARBON
|
|
|
|
Rect bounds;
|
|
|
|
GetWindowPortBounds(statusWindow, &bounds);
|
|
|
|
#else
|
2018-05-06 16:49:43 +00:00
|
|
|
Rect bounds = statusWindow->portRect;
|
2018-05-14 21:58:11 +00:00
|
|
|
#endif
|
2018-05-06 16:49:43 +00:00
|
|
|
|
|
|
|
SetRect(&statusRect, 10, 0, bounds.right-10, 30);
|
|
|
|
SetRect(&progressRect, 10, 30, bounds.right-10, 46);
|
2018-05-07 20:39:24 +00:00
|
|
|
|
|
|
|
memset(columnWidths, 0, sizeof(columnWidths));
|
|
|
|
columnWidths[1] = columnWidths[4] = 50;
|
|
|
|
|
2018-05-14 21:58:11 +00:00
|
|
|
#if TARGET_API_MAC_CARBON
|
|
|
|
SetPortWindowPort(statusWindow);
|
|
|
|
#else
|
2018-05-07 20:39:24 +00:00
|
|
|
SetPort(statusWindow);
|
2018-05-14 21:58:11 +00:00
|
|
|
#endif
|
2018-05-07 20:39:24 +00:00
|
|
|
TextSize(9);
|
|
|
|
TextFace(bold);
|
|
|
|
for(int i = 0; i < 2 * nValues; i++)
|
|
|
|
{
|
|
|
|
Str255 str;
|
|
|
|
GetIndString(str, 129, i+1);
|
|
|
|
short& col = columnWidths[(i&1)*2 + (i&2)*3/2];
|
|
|
|
col = std::max(col, StringWidth(str));
|
|
|
|
}
|
|
|
|
|
|
|
|
for(int i = 0; i < nValues; i+=2)
|
|
|
|
{
|
|
|
|
SetRect(&valueRects[i],
|
|
|
|
10 + columnWidths[0],
|
|
|
|
tableTop + i/2 * tableLineHeight,
|
|
|
|
10 + columnWidths[0] + columnWidths[1],
|
|
|
|
tableTop + (i/2+1) * tableLineHeight);
|
|
|
|
}
|
|
|
|
for(int i = 1; i < nValues; i+=2)
|
|
|
|
{
|
|
|
|
SetRect(&valueRects[i],
|
|
|
|
bounds.right - 10 - columnWidths[5] - columnWidths[4],
|
|
|
|
tableTop + i/2 * tableLineHeight,
|
|
|
|
bounds.right - 10 - columnWidths[5],
|
|
|
|
tableTop + (i/2+1) * tableLineHeight);
|
|
|
|
}
|
|
|
|
|
2019-01-08 23:31:32 +00:00
|
|
|
#ifdef DEBUG_CONSOLE
|
|
|
|
short consoleTop = tableTop + (nValues+1)/2 * tableLineHeight + 10;
|
|
|
|
SetRect(&consoleRect, 10, consoleTop,
|
|
|
|
bounds.right - 10, consoleTop + 150);
|
|
|
|
#if TARGET_API_MAC_CARBON
|
|
|
|
console = retro::Console(GetWindowPort(statusWindow), consoleRect);
|
|
|
|
#else
|
|
|
|
console = retro::Console(statusWindow, consoleRect);
|
|
|
|
#endif
|
|
|
|
retro::Console::currentInstance = &console;
|
|
|
|
|
|
|
|
bounds.bottom = consoleRect.bottom + 10;
|
|
|
|
#else
|
|
|
|
bounds.bottom = tableTop + (nValues+1)/2 * tableLineHeight + 10;
|
|
|
|
#endif
|
|
|
|
|
2018-05-06 16:49:43 +00:00
|
|
|
RgnHandle tmp = NewRgn();
|
|
|
|
background = NewRgn();
|
|
|
|
RectRgn(background, &bounds);
|
|
|
|
RectRgn(tmp, &progressRect);
|
|
|
|
DiffRgn(background, tmp, background);
|
2018-05-07 20:39:24 +00:00
|
|
|
for(int i = 0; i < nValues; i++)
|
|
|
|
{
|
|
|
|
RectRgn(tmp, &valueRects[i]);
|
|
|
|
DiffRgn(background, tmp, background);
|
|
|
|
}
|
2019-01-08 23:31:32 +00:00
|
|
|
#ifdef DEBUG_CONSOLE
|
|
|
|
RectRgn(tmp, &consoleRect);
|
|
|
|
DiffRgn(background, tmp, background);
|
|
|
|
#endif
|
|
|
|
|
2018-05-06 16:49:43 +00:00
|
|
|
DisposeRgn(tmp);
|
2018-05-16 22:38:55 +00:00
|
|
|
|
|
|
|
if(hasColorQD)
|
|
|
|
{
|
|
|
|
progressBg = GetPixPat(128);
|
|
|
|
progressFg = GetPixPat(129);
|
|
|
|
}
|
2019-01-08 23:31:32 +00:00
|
|
|
|
|
|
|
SizeWindow(statusWindow, bounds.right, bounds.bottom, false);
|
|
|
|
ShowWindow(statusWindow);
|
2018-05-06 16:49:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
StatusDisplay::~StatusDisplay()
|
|
|
|
{
|
|
|
|
DisposeWindow(statusWindow);
|
|
|
|
DisposeRgn(background);
|
|
|
|
}
|
|
|
|
|
2018-05-14 21:58:11 +00:00
|
|
|
void StatusDisplay::Inval(const Rect& r)
|
|
|
|
{
|
|
|
|
#if TARGET_API_MAC_CARBON
|
|
|
|
InvalWindowRect(statusWindow, &r);
|
|
|
|
#else
|
|
|
|
SetPort(statusWindow);
|
|
|
|
InvalRect(&r);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2018-05-07 20:39:24 +00:00
|
|
|
void StatusDisplay::DrawValue(Stat stat, ConstStr255Param str)
|
|
|
|
{
|
|
|
|
Rect& r = valueRects[(short)stat];
|
|
|
|
MoveTo(r.right - StringWidth(str), r.top + tableBaseline);
|
|
|
|
EraseRect(&r);
|
|
|
|
DrawString(str);
|
|
|
|
}
|
|
|
|
void StatusDisplay::DrawValue(Stat stat, long val)
|
|
|
|
{
|
|
|
|
Str255 str;
|
|
|
|
NumToString(val, str);
|
|
|
|
if(val >= 0)
|
|
|
|
DrawValue(stat, str);
|
|
|
|
else
|
|
|
|
DrawValue(stat, "\p--");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-05-06 16:49:43 +00:00
|
|
|
void StatusDisplay::Update()
|
|
|
|
{
|
2019-01-24 17:15:47 +00:00
|
|
|
GrafPtr savePort;
|
|
|
|
GetPort(&savePort);
|
2018-05-06 16:49:43 +00:00
|
|
|
SetPortWindowPort(statusWindow);
|
|
|
|
BeginUpdate(statusWindow);
|
|
|
|
EraseRgn(background);
|
|
|
|
|
2018-05-07 20:39:24 +00:00
|
|
|
TextSize(12);
|
|
|
|
TextFace(normal);
|
|
|
|
|
2018-05-06 16:49:43 +00:00
|
|
|
MoveTo(statusRect.left,statusRect.bottom-10);
|
|
|
|
DrawString(statusString);
|
|
|
|
|
|
|
|
Rect r;
|
|
|
|
|
|
|
|
if(progressTotal)
|
|
|
|
{
|
|
|
|
FrameRect(&progressRect);
|
|
|
|
InsetRect(&r, 1,1);
|
|
|
|
SetRect(&r, progressRect.left+1, progressRect.top+1,
|
|
|
|
progressRect.left+1 + (progressRect.right-progressRect.left-2) * progressDone / progressTotal,
|
|
|
|
progressRect.bottom-1);
|
2018-05-14 21:58:11 +00:00
|
|
|
|
2018-05-16 22:38:55 +00:00
|
|
|
#if TARGET_CPU_68K && !TARGET_RT_MAC_CFM
|
|
|
|
if(!hasColorQD)
|
|
|
|
FillRect(&r, &qd.dkGray);
|
|
|
|
else
|
2018-05-14 21:58:11 +00:00
|
|
|
#endif
|
2018-05-16 22:38:55 +00:00
|
|
|
FillCRect(&r, progressFg);
|
2018-05-06 16:49:43 +00:00
|
|
|
r.left = r.right;
|
|
|
|
r.right = progressRect.right - 1;
|
2018-05-16 22:38:55 +00:00
|
|
|
#if TARGET_CPU_68K && !TARGET_RT_MAC_CFM
|
|
|
|
if(!hasColorQD)
|
|
|
|
FillRect(&r, &qd.ltGray);
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
FillCRect(&r, progressBg);
|
2018-05-06 16:49:43 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
EraseRect(&progressRect);
|
|
|
|
|
|
|
|
Str255 str;
|
2018-05-07 20:39:24 +00:00
|
|
|
|
|
|
|
TextSize(9);
|
|
|
|
TextFace(bold);
|
|
|
|
|
|
|
|
for(int i = 0; i < nValues; i++)
|
|
|
|
{
|
|
|
|
GetIndString(str, 129, (i*2)+1);
|
|
|
|
MoveTo(valueRects[i].left - StringWidth(str), valueRects[i].top + tableBaseline);
|
|
|
|
DrawString(str);
|
|
|
|
GetIndString(str, 129, (i*2)+2);
|
|
|
|
MoveTo(valueRects[i].right, valueRects[i].top + tableBaseline);
|
|
|
|
DrawString(str);
|
|
|
|
}
|
|
|
|
|
|
|
|
TextFace(normal);
|
2018-05-14 21:58:11 +00:00
|
|
|
#if !TARGET_API_MAC_CARBON
|
2018-05-07 20:39:24 +00:00
|
|
|
DrawValue(Stat::heapSize, (ApplicationZone()->bkLim - (Ptr)ApplicationZone()) / 1024);
|
2018-05-14 21:58:11 +00:00
|
|
|
#endif
|
2018-05-07 20:39:24 +00:00
|
|
|
DrawValue(Stat::freeMem, freeMem);
|
|
|
|
if(progressTotal)
|
|
|
|
{
|
|
|
|
DrawValue(Stat::fileSize, progressTotal / 1024);
|
|
|
|
DrawValue(Stat::transferred, progressDone / 1024);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DrawValue(Stat::fileSize, "\p--");
|
|
|
|
DrawValue(Stat::transferred, "\p--");
|
|
|
|
}
|
|
|
|
DrawValue(Stat::speed, speed);
|
|
|
|
DrawValue(Stat::timeRemaining, timeRemaining);
|
|
|
|
DrawValue(Stat::transmissionErrors, errorCount);
|
2018-05-06 16:49:43 +00:00
|
|
|
|
2019-01-08 23:31:32 +00:00
|
|
|
#ifdef DEBUG_CONSOLE
|
|
|
|
Rect updateRect;
|
|
|
|
#if TARGET_API_MAC_CARBON
|
|
|
|
RgnHandle rgn = NewRgn();
|
|
|
|
GetPortVisibleRegion(GetWindowPort(statusWindow), rgn);
|
|
|
|
GetRegionBounds(rgn, &updateRect);
|
|
|
|
DisposeRgn(rgn);
|
|
|
|
#else
|
|
|
|
updateRect = (*qd.thePort->visRgn)->rgnBBox; // Life was simple back then.
|
|
|
|
#endif
|
|
|
|
|
|
|
|
console.Draw(updateRect);
|
|
|
|
FrameRect(&consoleRect);
|
|
|
|
#endif
|
|
|
|
|
2018-05-06 16:49:43 +00:00
|
|
|
EndUpdate(statusWindow);
|
2019-01-24 17:15:47 +00:00
|
|
|
SetPort(savePort);
|
2018-05-06 16:49:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void StatusDisplay::Idle()
|
|
|
|
{
|
2018-05-07 20:39:24 +00:00
|
|
|
long newFreeMem = FreeMem() / 1024;
|
2018-05-06 16:49:43 +00:00
|
|
|
if(newFreeMem != freeMem)
|
|
|
|
{
|
|
|
|
freeMem = newFreeMem;
|
2018-05-14 21:58:11 +00:00
|
|
|
Inval(valueRects[(short)Stat::freeMem]);
|
2018-05-07 20:39:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
long newTimeRemaining = -1;
|
2018-05-08 00:37:25 +00:00
|
|
|
if(status == AppStatus::downloading || status == AppStatus::upgrading)
|
2018-05-07 20:39:24 +00:00
|
|
|
{
|
|
|
|
long now = TickCount();
|
|
|
|
if(now - startTime > 60 && progressDone > 4000)
|
|
|
|
{
|
|
|
|
long newSpeed = progressDone * 6015LL / (now-startTime) / 100;
|
|
|
|
newTimeRemaining = (uint64_t(now-startTime) * (progressTotal - progressDone) * 100
|
|
|
|
/ progressDone + 6014) / 6015;
|
|
|
|
if(newSpeed != speed)
|
|
|
|
{
|
|
|
|
speed = newSpeed;
|
2018-05-14 21:58:11 +00:00
|
|
|
Inval(valueRects[(short)Stat::speed]);
|
2018-05-07 20:39:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(newTimeRemaining != timeRemaining)
|
|
|
|
{
|
|
|
|
timeRemaining = newTimeRemaining;
|
2018-05-14 21:58:11 +00:00
|
|
|
Inval(valueRects[(short)Stat::timeRemaining]);
|
2018-05-06 16:49:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void StatusDisplay::SetStatus(AppStatus stat)
|
|
|
|
{
|
|
|
|
if(stat != status)
|
|
|
|
{
|
|
|
|
status = stat;
|
2018-05-08 00:37:25 +00:00
|
|
|
if(status == AppStatus::downloading || status == AppStatus::upgrading)
|
2018-05-07 20:39:24 +00:00
|
|
|
startTime = TickCount();
|
2018-05-06 16:49:43 +00:00
|
|
|
GetIndString(statusString,128,(short)stat);
|
2018-05-14 21:58:11 +00:00
|
|
|
Inval(statusRect);
|
2019-01-08 23:31:32 +00:00
|
|
|
|
|
|
|
#ifdef DEBUG_CONSOLE
|
|
|
|
statusString[statusString[0]+1] = 0;
|
|
|
|
printf("%s\n", (const char*)statusString+1);
|
|
|
|
#endif
|
2018-05-06 16:49:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void StatusDisplay::SetProgress(int done, int total)
|
|
|
|
{
|
|
|
|
if(done != progressDone || total != progressTotal)
|
|
|
|
{
|
2018-05-14 21:58:11 +00:00
|
|
|
Inval(progressRect);
|
2018-05-07 20:39:24 +00:00
|
|
|
if(total != progressTotal)
|
2018-05-14 21:58:11 +00:00
|
|
|
Inval(valueRects[(short)Stat::fileSize]);
|
|
|
|
Inval(valueRects[(short)Stat::transferred]);
|
2018-05-07 20:39:24 +00:00
|
|
|
progressTotal = total;
|
|
|
|
progressDone = done;
|
2018-05-06 16:49:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void StatusDisplay::SetStatus(AppStatus stat, int done, int total)
|
|
|
|
{
|
|
|
|
SetStatus(stat);
|
|
|
|
SetProgress(done, total);
|
|
|
|
}
|
2018-05-07 20:39:24 +00:00
|
|
|
|
|
|
|
void StatusDisplay::SetErrorCount(int newErrorCount)
|
|
|
|
{
|
|
|
|
if(newErrorCount != errorCount)
|
|
|
|
{
|
|
|
|
errorCount = newErrorCount;
|
2018-05-14 21:58:11 +00:00
|
|
|
Inval(valueRects[(short)Stat::transmissionErrors]);
|
2018-05-07 20:39:24 +00:00
|
|
|
}
|
|
|
|
}
|