2 * Copyright 2017 Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
10 #include "TaskTimer.h"
12 #include <Application.h>
15 #include "constants.h"
17 #undef B_TRANSLATION_CONTEXT
18 #define B_TRANSLATION_CONTEXT "TaskTimer"
20 static int32 sAlertStackCount
= 0;
23 TaskTimer::TaskTimer(const BMessenger
& target
, Task
* owner
)
26 fTimeoutMicroSeconds(kTimerTimeoutSeconds
* 1000000),
27 fTimerIsRunning(false),
30 fTimeoutMessage(TASK_TIMEOUT
),
36 // Messenger for the Message Runner to use to send its message to the timer
37 fMessenger
.SetTo(this);
38 // Invoker for the Alerts to use to send their messages to the timer
39 fTimeoutAlertInvoker
.SetMessage(
40 new BMessage(TIMEOUT_ALERT_BUTTON_SELECTION
));
41 fTimeoutAlertInvoker
.SetTarget(this);
45 TaskTimer::~TaskTimer()
48 fTimeoutAlert
->Lock();
49 fTimeoutAlert
->Quit();
52 fMessageRunner
->SetCount(0);
57 TaskTimer::QuitRequested()
64 TaskTimer::MessageReceived(BMessage
* message
)
66 switch (message
->what
)
70 fMessageRunner
= NULL
;
71 if (fTimerIsRunning
) {
72 BString
text(B_TRANSLATE_COMMENT("The task for repository"
73 " %name% is taking a long time to complete.",
74 "Alert message. Do not translate %name%"));
75 BString
nameString("\"");
76 nameString
.Append(fRepositoryName
).Append("\"");
77 text
.ReplaceFirst("%name%", nameString
);
78 fTimeoutAlert
= new BAlert("timeout", text
,
79 B_TRANSLATE_COMMENT("Keep trying", "Button label"),
80 B_TRANSLATE_COMMENT("Cancel task", "Button label"),
81 NULL
, B_WIDTH_AS_USUAL
, B_WARNING_ALERT
);
82 fTimeoutAlert
->SetShortcut(0, B_ESCAPE
);
83 // Calculate the position to correctly stack this alert
84 BRect windowFrame
= be_app
->WindowAt(0)->Frame();
85 int32 stackPos
= _NextAlertStackCount();
86 float xPos
= windowFrame
.left
87 + windowFrame
.Width()/2 + stackPos
* kTimerAlertOffset
;
88 float yPos
= windowFrame
.top
89 + (stackPos
+ 1) * kTimerAlertOffset
;
90 fTimeoutAlert
->Go(&fTimeoutAlertInvoker
);
91 xPos
-= fTimeoutAlert
->Frame().Width()/2;
92 // The correct frame for the alert is not available until
94 fTimeoutAlert
->MoveTo(xPos
, yPos
);
99 case TIMEOUT_ALERT_BUTTON_SELECTION
:
101 fTimeoutAlert
= NULL
;
102 // Timeout alert was invoked by user and timer still has not
104 if (fTimerIsRunning
) {
105 // find which button was pressed
106 int32 selection
= -1;
107 message
->FindInt32("which", &selection
);
108 if (selection
== 1) {
109 BMessage
reply(TASK_KILL_REQUEST
);
110 reply
.AddPointer(key_taskptr
, fOwner
);
111 fReplyTarget
.SendMessage(&reply
);
112 } else if (selection
== 0) {
114 fMessageRunner
= new BMessageRunner(fMessenger
,
115 &fTimeoutMessage
, kTimerRetrySeconds
* 1000000, 1);
125 TaskTimer::Start(const char* name
)
127 fTimerIsRunning
= true;
128 fRepositoryName
.SetTo(name
);
130 // Create a message runner that will send a TASK_TIMEOUT message if the
131 // timer is not stopped
132 if (fMessageRunner
== NULL
) {
133 fMessageRunner
= new BMessageRunner(fMessenger
, &fTimeoutMessage
,
134 fTimeoutMicroSeconds
, 1);
137 fMessageRunner
->SetInterval(fTimeoutMicroSeconds
);
142 TaskTimer::Stop(const char* name
)
144 fTimerIsRunning
= false;
146 // Reset max timeout so we can reuse the runner at the next Start call
147 if (fMessageRunner
!= NULL
)
148 fMessageRunner
->SetInterval(LLONG_MAX
);
150 // If timeout alert is showing replace it
152 // Remove current alert
153 BRect frame
= fTimeoutAlert
->Frame();
154 fTimeoutAlert
->Quit();
155 fTimeoutAlert
= NULL
;
157 // Display new alert that won't send a message
158 BString
text(B_TRANSLATE_COMMENT("Good news! The task for repository "
159 "%name% completed.", "Alert message. Do not translate %name%"));
160 BString
nameString("\"");
161 nameString
.Append(name
).Append("\"");
162 text
.ReplaceFirst("%name%", nameString
);
163 BAlert
* newAlert
= new BAlert("timeout", text
, kOKLabel
, NULL
, NULL
,
164 B_WIDTH_AS_USUAL
, B_WARNING_ALERT
);
165 newAlert
->SetShortcut(0, B_ESCAPE
);
166 newAlert
->MoveTo(frame
.left
, frame
.top
);
173 TaskTimer::_NextAlertStackCount()
175 if (sAlertStackCount
> 9)
176 sAlertStackCount
= 0;
177 return sAlertStackCount
++;