40
40
// flavors of a bitmap. If the stash does not have a particular bitmap,
41
41
// it turns around to ask the button to create one and stores it for next time.
43
BitmapStash(TransportButton *);
45
BBitmap *GetBitmap(uint32 signature);
43
BitmapStash(TransportButton *);
45
BBitmap *GetBitmap(uint32 signature);
48
TransportButton *owner;
49
map<uint32, BBitmap *> stash;
48
TransportButton *owner;
49
map<uint32, BBitmap *> stash;
52
52
BitmapStash::BitmapStash(TransportButton *owner)
58
58
BitmapStash::GetBitmap(uint32 signature)
60
if (stash.find(signature) == stash.end()) {
61
BBitmap *newBits = owner->MakeBitmap(signature);
63
stash[signature] = newBits;
66
return stash[signature];
60
if (stash.find(signature) == stash.end()) {
61
BBitmap *newBits = owner->MakeBitmap(signature);
63
stash[signature] = newBits;
66
return stash[signature];
69
69
BitmapStash::~BitmapStash()
71
// delete all the bitmaps
72
for (map<uint32, BBitmap *>::iterator i = stash.begin(); i != stash.end(); i++)
71
// delete all the bitmaps
72
for (map<uint32, BBitmap *>::iterator i = stash.begin(); i != stash.end(); i++)
77
77
class PeriodicMessageSender {
78
// used to send a specified message repeatedly when holding down a button
78
// used to send a specified message repeatedly when holding down a button
80
static PeriodicMessageSender *Launch(BMessenger target,
81
const BMessage *message, bigtime_t period);
80
static PeriodicMessageSender *Launch(BMessenger target,
81
const BMessage *message, bigtime_t period);
85
PeriodicMessageSender(BMessenger target, const BMessage *message,
87
~PeriodicMessageSender() {}
90
static status_t TrackBinder(void *);
85
PeriodicMessageSender(BMessenger target, const BMessage *message,
87
~PeriodicMessageSender() {}
90
static status_t TrackBinder(void *);
102
102
PeriodicMessageSender::PeriodicMessageSender(BMessenger target,
103
const BMessage *message, bigtime_t period)
103
const BMessage *message, bigtime_t period)
111
111
PeriodicMessageSender *
112
112
PeriodicMessageSender::Launch(BMessenger target, const BMessage *message,
115
PeriodicMessageSender *result = new PeriodicMessageSender(target, message, period);
116
thread_id thread = spawn_thread(&PeriodicMessageSender::TrackBinder,
117
"ButtonRepeatingThread", B_NORMAL_PRIORITY, result);
119
if (thread <= 0 || resume_thread(thread) != B_OK) {
120
// didn't start, don't leak self
115
PeriodicMessageSender *result = new PeriodicMessageSender(target, message, period);
116
thread_id thread = spawn_thread(&PeriodicMessageSender::TrackBinder,
117
"ButtonRepeatingThread", B_NORMAL_PRIORITY, result);
119
if (thread <= 0 || resume_thread(thread) != B_OK) {
120
// didn't start, don't leak self
129
129
PeriodicMessageSender::Quit()
131
requestToQuit = true;
131
requestToQuit = true;
135
135
PeriodicMessageSender::TrackBinder(void *castToThis)
137
((PeriodicMessageSender *)castToThis)->Run();
137
((PeriodicMessageSender *)castToThis)->Run();
142
142
PeriodicMessageSender::Run()
148
target.SendMessage(&message);
148
target.SendMessage(&message);
153
153
class SkipButtonKeypressFilter : public BMessageFilter {
155
SkipButtonKeypressFilter(uint32 shortcutKey, uint32 shortcutModifier,
156
TransportButton *target);
155
SkipButtonKeypressFilter(uint32 shortcutKey, uint32 shortcutModifier,
156
TransportButton *target);
159
filter_result Filter(BMessage *message, BHandler **handler);
159
filter_result Filter(BMessage *message, BHandler **handler);
163
uint32 shortcutModifier;
164
TransportButton *target;
163
uint32 shortcutModifier;
164
TransportButton *target;
167
167
SkipButtonKeypressFilter::SkipButtonKeypressFilter(uint32 shortcutKey,
168
uint32 shortcutModifier, TransportButton *target)
169
: BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE),
170
shortcutKey(shortcutKey),
171
shortcutModifier(shortcutModifier),
168
uint32 shortcutModifier, TransportButton *target)
169
: BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE),
170
shortcutKey(shortcutKey),
171
shortcutModifier(shortcutModifier),
177
177
SkipButtonKeypressFilter::Filter(BMessage *message, BHandler **handler)
179
if (target->IsEnabled()
180
&& (message->what == B_KEY_DOWN || message->what == B_KEY_UP)) {
182
uint32 rawKeyChar = 0;
186
if (message->FindInt32("modifiers", (int32 *)&modifiers) != B_OK
187
|| message->FindInt32("raw_char", (int32 *)&rawKeyChar) != B_OK
188
|| message->FindInt8("byte", (int8 *)&byte) != B_OK
189
|| message->FindInt32("key", &key) != B_OK)
190
return B_DISPATCH_MESSAGE;
192
modifiers &= B_SHIFT_KEY | B_COMMAND_KEY | B_CONTROL_KEY
193
| B_OPTION_KEY | B_MENU_KEY;
194
// strip caps lock, etc.
196
if (modifiers == shortcutModifier && rawKeyChar == shortcutKey) {
197
if (message->what == B_KEY_DOWN)
198
target->ShortcutKeyDown();
200
target->ShortcutKeyUp();
202
return B_SKIP_MESSAGE;
206
// let others deal with this
207
return B_DISPATCH_MESSAGE;
179
if (target->IsEnabled()
180
&& (message->what == B_KEY_DOWN || message->what == B_KEY_UP)) {
182
uint32 rawKeyChar = 0;
186
if (message->FindInt32("modifiers", (int32 *)&modifiers) != B_OK
187
|| message->FindInt32("raw_char", (int32 *)&rawKeyChar) != B_OK
188
|| message->FindInt8("byte", (int8 *)&byte) != B_OK
189
|| message->FindInt32("key", &key) != B_OK)
190
return B_DISPATCH_MESSAGE;
192
modifiers &= B_SHIFT_KEY | B_COMMAND_KEY | B_CONTROL_KEY
193
| B_OPTION_KEY | B_MENU_KEY;
194
// strip caps lock, etc.
196
if (modifiers == shortcutModifier && rawKeyChar == shortcutKey) {
197
if (message->what == B_KEY_DOWN)
198
target->ShortcutKeyDown();
200
target->ShortcutKeyUp();
202
return B_SKIP_MESSAGE;
206
// let others deal with this
207
return B_DISPATCH_MESSAGE;
210
210
TransportButton::TransportButton(BRect frame, const char *name,
211
const unsigned char *normalBits,
212
const unsigned char *pressedBits,
213
const unsigned char *disabledBits,
214
BMessage *invokeMessage, BMessage *startPressingMessage,
215
BMessage *pressingMessage, BMessage *donePressingMessage, bigtime_t period,
216
uint32 key, uint32 modifiers, uint32 resizeFlags)
217
: BControl(frame, name, "", invokeMessage, resizeFlags, B_WILL_DRAW | B_NAVIGABLE),
218
bitmaps(new BitmapStash(this)),
219
normalBits(normalBits),
220
pressedBits(pressedBits),
221
disabledBits(disabledBits),
222
startPressingMessage(startPressingMessage),
223
pressingMessage(pressingMessage),
224
donePressingMessage(donePressingMessage),
225
pressingPeriod(period),
211
const unsigned char *normalBits,
212
const unsigned char *pressedBits,
213
const unsigned char *disabledBits,
214
BMessage *invokeMessage, BMessage *startPressingMessage,
215
BMessage *pressingMessage, BMessage *donePressingMessage, bigtime_t period,
216
uint32 key, uint32 modifiers, uint32 resizeFlags)
217
: BControl(frame, name, "", invokeMessage, resizeFlags, B_WILL_DRAW | B_NAVIGABLE),
218
bitmaps(new BitmapStash(this)),
219
normalBits(normalBits),
220
pressedBits(pressedBits),
221
disabledBits(disabledBits),
222
startPressingMessage(startPressingMessage),
223
pressingMessage(pressingMessage),
224
donePressingMessage(donePressingMessage),
225
pressingPeriod(period),
232
keyPressFilter = new SkipButtonKeypressFilter(key, modifiers, this);
232
keyPressFilter = new SkipButtonKeypressFilter(key, modifiers, this);
237
237
TransportButton::AttachedToWindow()
239
_inherited::AttachedToWindow();
241
Window()->AddCommonFilter(keyPressFilter);
243
// transparent to reduce flicker
244
SetViewColor(B_TRANSPARENT_COLOR);
239
_inherited::AttachedToWindow();
241
Window()->AddCommonFilter(keyPressFilter);
243
// transparent to reduce flicker
244
SetViewColor(B_TRANSPARENT_COLOR);
248
248
TransportButton::DetachedFromWindow()
251
Window()->RemoveCommonFilter(keyPressFilter);
252
_inherited::DetachedFromWindow();
251
Window()->RemoveCommonFilter(keyPressFilter);
252
_inherited::DetachedFromWindow();
256
256
TransportButton::~TransportButton()
258
delete startPressingMessage;
259
delete pressingMessage;
260
delete donePressingMessage;
262
delete keyPressFilter;
258
delete startPressingMessage;
259
delete pressingMessage;
260
delete donePressingMessage;
262
delete keyPressFilter;
266
266
TransportButton::WindowActivated(bool state)
271
_inherited::WindowActivated(state);
271
_inherited::WindowActivated(state);
275
275
TransportButton::SetEnabled(bool on)
277
if (on != IsEnabled()) {
278
_inherited::SetEnabled(on);
277
if (on != IsEnabled()) {
278
_inherited::SetEnabled(on);
284
284
const unsigned char *
285
285
TransportButton::BitsForMask(uint32 mask) const
303
303
TransportButton::MakeBitmap(uint32 mask)
306
BBitmap *result = new BBitmap(r, B_CMAP8);
308
uint8* src = (uint8*)BitsForMask(mask);
310
if (src && result && result->IsValid()) {
311
// int32 width = r.IntegerWidth() + 1;
312
int32 height = r.IntegerHeight() + 1;
313
int32 bpr = result->BytesPerRow();
314
uint8* dst = (uint8*)result->Bits();
315
// copy source bits into bitmap line by line,
316
// taking possible alignment into account
317
// since the source data has been generated
318
// by QuickRes, it still contains aligment too
319
// (hence skipping bpr and not width bytes)
320
for (int32 y = 0; y < height; y++) {
321
memcpy(dst, src, bpr);
325
ReplaceTransparentColor(result, Parent()->ViewColor());
306
BBitmap *result = new BBitmap(r, B_CMAP8);
308
uint8* src = (uint8*)BitsForMask(mask);
310
if (src && result && result->IsValid()) {
311
// int32 width = r.IntegerWidth() + 1;
312
int32 height = r.IntegerHeight() + 1;
313
int32 bpr = result->BytesPerRow();
314
uint8* dst = (uint8*)result->Bits();
315
// copy source bits into bitmap line by line,
316
// taking possible alignment into account
317
// since the source data has been generated
318
// by QuickRes, it still contains aligment too
319
// (hence skipping bpr and not width bytes)
320
for (int32 y = 0; y < height; y++) {
321
memcpy(dst, src, bpr);
325
ReplaceTransparentColor(result, Parent()->ViewColor());
335
335
TransportButton::ModeMask() const
337
return (IsEnabled() ? 0 : kDisabledMask)
338
| (Value() ? kPressedMask : 0);
337
return (IsEnabled() ? 0 : kDisabledMask)
338
| (Value() ? kPressedMask : 0);
342
342
TransportButton::Draw(BRect)
344
DrawBitmapAsync(bitmaps->GetBitmap(ModeMask()));
344
DrawBitmapAsync(bitmaps->GetBitmap(ModeMask()));
349
349
TransportButton::StartPressing()
352
if (startPressingMessage)
353
Invoke(startPressingMessage);
355
if (pressingMessage) {
356
ASSERT(pressingMessage);
357
messageSender = PeriodicMessageSender::Launch(Messenger(),
358
pressingMessage, pressingPeriod);
352
if (startPressingMessage)
353
Invoke(startPressingMessage);
355
if (pressingMessage) {
356
ASSERT(pressingMessage);
357
messageSender = PeriodicMessageSender::Launch(Messenger(),
358
pressingMessage, pressingPeriod);
363
363
TransportButton::MouseCancelPressing()
365
if (!mouseDown || keyDown)
370
if (pressingMessage) {
371
ASSERT(messageSender);
372
PeriodicMessageSender *sender = messageSender;
377
if (donePressingMessage)
378
Invoke(donePressingMessage);
365
if (!mouseDown || keyDown)
370
if (pressingMessage) {
371
ASSERT(messageSender);
372
PeriodicMessageSender *sender = messageSender;
377
if (donePressingMessage)
378
Invoke(donePressingMessage);
383
383
TransportButton::DonePressing()
385
if (pressingMessage) {
386
ASSERT(messageSender);
387
PeriodicMessageSender *sender = messageSender;
385
if (pressingMessage) {
386
ASSERT(messageSender);
387
PeriodicMessageSender *sender = messageSender;
397
397
TransportButton::MouseStartPressing()
408
408
TransportButton::MouseDonePressing()
419
419
TransportButton::ShortcutKeyDown()
433
433
TransportButton::ShortcutKeyUp()
445
445
TransportButton::MouseDown(BPoint)
450
ASSERT(Window()->Flags() & B_ASYNCHRONOUS_CONTROLS);
452
SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
453
MouseStartPressing();
450
ASSERT(Window()->Flags() & B_ASYNCHRONOUS_CONTROLS);
452
SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
453
MouseStartPressing();
457
457
TransportButton::MouseMoved(BPoint point, uint32 code, const BMessage *)
459
if (IsTracking() && Bounds().Contains(point) != Value()) {
461
MouseStartPressing();
463
MouseCancelPressing();
459
if (IsTracking() && Bounds().Contains(point) != Value()) {
461
MouseStartPressing();
463
MouseCancelPressing();
468
468
TransportButton::MouseUp(BPoint point)
471
if (Bounds().Contains(point))
474
MouseCancelPressing();
471
if (Bounds().Contains(point))
474
MouseCancelPressing();
480
480
TransportButton::SetStartPressingMessage(BMessage *message)
482
delete startPressingMessage;
483
startPressingMessage = message;
482
delete startPressingMessage;
483
startPressingMessage = message;
487
487
TransportButton::SetPressingMessage(BMessage *message)
489
delete pressingMessage;
490
pressingMessage = message;
489
delete pressingMessage;
490
pressingMessage = message;
494
494
TransportButton::SetDonePressingMessage(BMessage *message)
496
delete donePressingMessage;
497
donePressingMessage = message;
496
delete donePressingMessage;
497
donePressingMessage = message;
501
501
TransportButton::SetPressingPeriod(bigtime_t newTime)
503
pressingPeriod = newTime;
503
pressingPeriod = newTime;
507
507
PlayPauseButton::PlayPauseButton(BRect frame, const char *name,
508
const unsigned char *normalBits, const unsigned char *pressedBits,
509
const unsigned char *disabledBits, const unsigned char *normalPlayingBits,
510
const unsigned char *pressedPlayingBits, const unsigned char *normalPausedBits,
511
const unsigned char *pressedPausedBits,
512
BMessage *invokeMessage, uint32 key, uint32 modifiers, uint32 resizeFlags)
513
: TransportButton(frame, name, normalBits, pressedBits,
514
disabledBits, invokeMessage, 0,
515
0, 0, 0, key, modifiers, resizeFlags),
516
normalPlayingBits(normalPlayingBits),
517
pressedPlayingBits(pressedPlayingBits),
518
normalPausedBits(normalPausedBits),
519
pressedPausedBits(pressedPausedBits),
520
state(PlayPauseButton::kStopped),
521
lastPauseBlinkTime(0),
508
const unsigned char *normalBits, const unsigned char *pressedBits,
509
const unsigned char *disabledBits, const unsigned char *normalPlayingBits,
510
const unsigned char *pressedPlayingBits, const unsigned char *normalPausedBits,
511
const unsigned char *pressedPausedBits,
512
BMessage *invokeMessage, uint32 key, uint32 modifiers, uint32 resizeFlags)
513
: TransportButton(frame, name, normalBits, pressedBits,
514
disabledBits, invokeMessage, 0,
515
0, 0, 0, key, modifiers, resizeFlags),
516
normalPlayingBits(normalPlayingBits),
517
pressedPlayingBits(pressedPlayingBits),
518
normalPausedBits(normalPausedBits),
519
pressedPausedBits(pressedPausedBits),
520
state(PlayPauseButton::kStopped),
521
lastPauseBlinkTime(0),
527
527
PlayPauseButton::SetStopped()
529
if (state == kStopped || state == kAboutToPlay)
529
if (state == kStopped || state == kAboutToPlay)
537
537
PlayPauseButton::SetPlaying()
539
if (state == kPlaying || state == kAboutToPause)
539
if (state == kPlaying || state == kAboutToPause)
546
546
const bigtime_t kPauseBlinkPeriod = 600000;
549
549
PlayPauseButton::SetPaused()
551
if (state == kAboutToPlay)
551
if (state == kAboutToPlay)
554
// in paused state blink the LED on and off
555
bigtime_t now = system_time();
556
if (state == kPausedLedOn || state == kPausedLedOff) {
557
if (now - lastPauseBlinkTime < kPauseBlinkPeriod)
560
if (state == kPausedLedOn)
561
state = kPausedLedOff;
563
state = kPausedLedOn;
565
state = kPausedLedOn;
567
lastPauseBlinkTime = now;
554
// in paused state blink the LED on and off
555
bigtime_t now = system_time();
556
if (state == kPausedLedOn || state == kPausedLedOff) {
557
if (now - lastPauseBlinkTime < kPauseBlinkPeriod)
560
if (state == kPausedLedOn)
561
state = kPausedLedOff;
563
state = kPausedLedOn;
565
state = kPausedLedOn;
567
lastPauseBlinkTime = now;
572
572
PlayPauseButton::ModeMask() const
575
return kDisabledMask;
580
result = kPressedMask;
582
if (state == kPlaying || state == kAboutToPlay)
583
result |= kPlayingMask;
584
else if (state == kAboutToPause || state == kPausedLedOn)
585
result |= kPausedMask;
575
return kDisabledMask;
580
result = kPressedMask;
582
if (state == kPlaying || state == kAboutToPlay)
583
result |= kPlayingMask;
584
else if (state == kAboutToPause || state == kPausedLedOn)
585
result |= kPausedMask;
590
590
const unsigned char *
591
591
PlayPauseButton::BitsForMask(uint32 mask) const
595
return normalPlayingBits;
596
case kPlayingMask | kPressedMask:
597
return pressedPlayingBits;
599
return normalPausedBits;
600
case kPausedMask | kPressedMask:
601
return pressedPausedBits;
603
return _inherited::BitsForMask(mask);
595
return normalPlayingBits;
596
case kPlayingMask | kPressedMask:
597
return pressedPlayingBits;
599
return normalPausedBits;
600
case kPausedMask | kPressedMask:
601
return pressedPausedBits;
603
return _inherited::BitsForMask(mask);
611
611
PlayPauseButton::StartPressing()
613
if (state == kPlaying)
614
state = kAboutToPause;
616
state = kAboutToPlay;
618
_inherited::StartPressing();
613
if (state == kPlaying)
614
state = kAboutToPause;
616
state = kAboutToPlay;
618
_inherited::StartPressing();
622
622
PlayPauseButton::MouseCancelPressing()
624
if (state == kAboutToPause)
629
_inherited::MouseCancelPressing();
624
if (state == kAboutToPause)
629
_inherited::MouseCancelPressing();
633
633
PlayPauseButton::DonePressing()
635
if (state == kAboutToPause) {
636
state = kPausedLedOn;
637
lastPauseBlinkTime = system_time();
638
} else if (state == kAboutToPlay)
641
_inherited::DonePressing();
635
if (state == kAboutToPause) {
636
state = kPausedLedOn;
637
lastPauseBlinkTime = system_time();
638
} else if (state == kAboutToPlay)
641
_inherited::DonePressing();