⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 transportbutton.cpp

📁 video linux conference
💻 CPP
字号:
/***************************************************************************** * TransportButton.cpp ***************************************************************************** * Copyright (C) 2001 VideoLAN * $Id: TransportButton.cpp 10101 2005-03-02 16:47:31Z robux4 $ * * Authors: Tony Castley <tcastley@mail.powerup.com.au> *          Stephan Aßmus <stippi@yellowbites.com> * * 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., 59 Temple Place - Suite 330, Boston, MA  02111, USA. *****************************************************************************/#include <Bitmap.h>#include <Debug.h>#include <MessageFilter.h>#include <Screen.h>#include <Window.h>#include <map>#include "TransportButton.h"#include "DrawingTidbits.h"class BitmapStash {// Bitmap stash is a simple class to hold all the lazily-allocated// bitmaps that the TransportButton needs when rendering itself.// signature is a combination of the different enabled, pressed, playing, etc.// flavors of a bitmap. If the stash does not have a particular bitmap,// it turns around to ask the button to create one and stores it for next time.public:	BitmapStash(TransportButton *);	~BitmapStash();	BBitmap *GetBitmap(uint32 signature);	private:	TransportButton *owner;	map<uint32, BBitmap *> stash;};BitmapStash::BitmapStash(TransportButton *owner)	:	owner(owner){}BBitmap *BitmapStash::GetBitmap(uint32 signature){	if (stash.find(signature) == stash.end()) {		BBitmap *newBits = owner->MakeBitmap(signature);		ASSERT(newBits);		stash[signature] = newBits;	}		return stash[signature];}BitmapStash::~BitmapStash(){	// delete all the bitmaps	for (map<uint32, BBitmap *>::iterator i = stash.begin(); i != stash.end(); i++) 		delete (*i).second;}class PeriodicMessageSender {	// used to send a specified message repeatedly when holding down a buttonpublic:	static PeriodicMessageSender *Launch(BMessenger target,		const BMessage *message, bigtime_t period);	void Quit();private:	PeriodicMessageSender(BMessenger target, const BMessage *message,		bigtime_t period);	~PeriodicMessageSender() {}		// use quit	static status_t TrackBinder(void *);	void Run();		BMessenger target;	BMessage message;	bigtime_t period;		bool requestToQuit;};PeriodicMessageSender::PeriodicMessageSender(BMessenger target,	const BMessage *message, bigtime_t period)	:	target(target),		message(*message),		period(period),		requestToQuit(false){}PeriodicMessageSender *PeriodicMessageSender::Launch(BMessenger target, const BMessage *message,	bigtime_t period){	PeriodicMessageSender *result = new PeriodicMessageSender(target, message, period);	thread_id thread = spawn_thread(&PeriodicMessageSender::TrackBinder,		"ButtonRepeatingThread", B_NORMAL_PRIORITY, result);		if (thread <= 0 || resume_thread(thread) != B_OK) {		// didn't start, don't leak self		delete result;		result = 0;	}	return result;}void PeriodicMessageSender::Quit(){	requestToQuit = true;}status_t PeriodicMessageSender::TrackBinder(void *castToThis){	((PeriodicMessageSender *)castToThis)->Run();	return 0;}void PeriodicMessageSender::Run(){	for (;;) {		snooze(period);		if (requestToQuit)			break;		target.SendMessage(&message);	}	delete this;}class SkipButtonKeypressFilter : public BMessageFilter {public:	SkipButtonKeypressFilter(uint32 shortcutKey, uint32 shortcutModifier,		TransportButton *target);protected:	filter_result Filter(BMessage *message, BHandler **handler);private:	uint32 shortcutKey;	uint32 shortcutModifier;	TransportButton *target;};SkipButtonKeypressFilter::SkipButtonKeypressFilter(uint32 shortcutKey,	uint32 shortcutModifier, TransportButton *target)	:	BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE),		shortcutKey(shortcutKey),		shortcutModifier(shortcutModifier),		target(target){}filter_result SkipButtonKeypressFilter::Filter(BMessage *message, BHandler **handler){	if (target->IsEnabled()		&& (message->what == B_KEY_DOWN || message->what == B_KEY_UP)) {		uint32 modifiers;		uint32 rawKeyChar = 0;		uint8 byte = 0;		int32 key = 0;				if (message->FindInt32("modifiers", (int32 *)&modifiers) != B_OK			|| message->FindInt32("raw_char", (int32 *)&rawKeyChar) != B_OK			|| message->FindInt8("byte", (int8 *)&byte) != B_OK			|| message->FindInt32("key", &key) != B_OK)			return B_DISPATCH_MESSAGE;		modifiers &= B_SHIFT_KEY | B_COMMAND_KEY | B_CONTROL_KEY			| B_OPTION_KEY | B_MENU_KEY;			// strip caps lock, etc.		if (modifiers == shortcutModifier && rawKeyChar == shortcutKey) {			if (message->what == B_KEY_DOWN)				target->ShortcutKeyDown();			else				target->ShortcutKeyUp();						return B_SKIP_MESSAGE;		}	}	// let others deal with this	return B_DISPATCH_MESSAGE;}TransportButton::TransportButton(BRect frame, const char *name,	const unsigned char *normalBits,	const unsigned char *pressedBits,	const unsigned char *disabledBits,	BMessage *invokeMessage, BMessage *startPressingMessage,	BMessage *pressingMessage, BMessage *donePressingMessage, bigtime_t period,	uint32 key, uint32 modifiers, uint32 resizeFlags)	:	BControl(frame, name, "", invokeMessage, resizeFlags, B_WILL_DRAW | B_NAVIGABLE),		bitmaps(new BitmapStash(this)),		normalBits(normalBits),		pressedBits(pressedBits),		disabledBits(disabledBits),		startPressingMessage(startPressingMessage),		pressingMessage(pressingMessage),		donePressingMessage(donePressingMessage),		pressingPeriod(period),		mouseDown(false),		keyDown(false),		messageSender(0),		keyPressFilter(0){	if (key)		keyPressFilter = new SkipButtonKeypressFilter(key, modifiers, this);}void TransportButton::AttachedToWindow(){	_inherited::AttachedToWindow();	if (keyPressFilter)		Window()->AddCommonFilter(keyPressFilter);		// transparent to reduce flicker	SetViewColor(B_TRANSPARENT_COLOR);}void TransportButton::DetachedFromWindow(){	if (keyPressFilter)		Window()->RemoveCommonFilter(keyPressFilter);	_inherited::DetachedFromWindow();}TransportButton::~TransportButton(){	delete startPressingMessage;	delete pressingMessage;	delete donePressingMessage;	delete bitmaps;	delete keyPressFilter;}void TransportButton::WindowActivated(bool state){	if (!state)		ShortcutKeyUp();		_inherited::WindowActivated(state);}void TransportButton::SetEnabled(bool on){	if (on != IsEnabled()) {		_inherited::SetEnabled(on);		if (!on)			ShortcutKeyUp();	}	}const unsigned char *TransportButton::BitsForMask(uint32 mask) const{	switch (mask) {		case 0:			return normalBits;		case kDisabledMask:			return disabledBits;		case kPressedMask:			return pressedBits;		default:			break;	}		TRESPASS();	return 0;}BBitmap *TransportButton::MakeBitmap(uint32 mask){	BRect r(Bounds());	BBitmap *result = new BBitmap(r, B_CMAP8);	uint8* src = (uint8*)BitsForMask(mask);	if (src && result && result->IsValid()) {		// int32 width = r.IntegerWidth() + 1;		int32 height = r.IntegerHeight() + 1;		int32 bpr = result->BytesPerRow();		uint8* dst = (uint8*)result->Bits();		// copy source bits into bitmap line by line,		// taking possible alignment into account		// since the source data has been generated		// by QuickRes, it still contains aligment too		// (hence skipping bpr and not width bytes)		for (int32 y = 0; y < height; y++) {			memcpy(dst, src, bpr);			src += bpr;			dst += bpr;		}		ReplaceTransparentColor(result, Parent()->ViewColor());	} else {		delete result;		result = NULL;	}		return result;}uint32 TransportButton::ModeMask() const{	return (IsEnabled() ? 0 : kDisabledMask)		| (Value() ? kPressedMask : 0);}void TransportButton::Draw(BRect){	DrawBitmapAsync(bitmaps->GetBitmap(ModeMask()));}void TransportButton::StartPressing(){	SetValue(1);	if (startPressingMessage)		Invoke(startPressingMessage);		if (pressingMessage) {		ASSERT(pressingMessage);		messageSender = PeriodicMessageSender::Launch(Messenger(),			pressingMessage, pressingPeriod);	}}void TransportButton::MouseCancelPressing(){	if (!mouseDown || keyDown)		return;	mouseDown = false;	if (pressingMessage) {		ASSERT(messageSender);		PeriodicMessageSender *sender = messageSender;		messageSender = 0;		sender->Quit();	}	if (donePressingMessage)		Invoke(donePressingMessage);	SetValue(0);}void TransportButton::DonePressing(){		if (pressingMessage) {		ASSERT(messageSender);		PeriodicMessageSender *sender = messageSender;		messageSender = 0;		sender->Quit();	}	Invoke();	SetValue(0);}void TransportButton::MouseStartPressing(){	if (mouseDown)		return;		mouseDown = true;	if (!keyDown)		StartPressing();}void TransportButton::MouseDonePressing(){	if (!mouseDown)		return;		mouseDown = false;	if (!keyDown)		DonePressing();}void TransportButton::ShortcutKeyDown(){	if (!IsEnabled())		return;	if (keyDown)		return;		keyDown = true;	if (!mouseDown)		StartPressing();}void TransportButton::ShortcutKeyUp(){	if (!keyDown)		return;		keyDown = false;	if (!mouseDown)		DonePressing();}void TransportButton::MouseDown(BPoint){	if (!IsEnabled())		return;	ASSERT(Window()->Flags() & B_ASYNCHRONOUS_CONTROLS);	SetTracking(true);	SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);	MouseStartPressing();}void TransportButton::MouseMoved(BPoint point, uint32 code, const BMessage *){	if (IsTracking() && Bounds().Contains(point) != Value()) {		if (!Value())			MouseStartPressing();		else			MouseCancelPressing();	}}void TransportButton::MouseUp(BPoint point){	if (IsTracking()) {		if (Bounds().Contains(point))			MouseDonePressing();		else			MouseCancelPressing();		SetTracking(false);	}}void TransportButton::SetStartPressingMessage(BMessage *message){	delete startPressingMessage;	startPressingMessage = message;}void TransportButton::SetPressingMessage(BMessage *message){	delete pressingMessage;	pressingMessage = message;}void TransportButton::SetDonePressingMessage(BMessage *message){	delete donePressingMessage;	donePressingMessage = message;}void TransportButton::SetPressingPeriod(bigtime_t newTime){	pressingPeriod = newTime;}PlayPauseButton::PlayPauseButton(BRect frame, const char *name,	const unsigned char *normalBits, const unsigned char *pressedBits,	const unsigned char *disabledBits, const unsigned char *normalPlayingBits,	const unsigned char *pressedPlayingBits, const unsigned char *normalPausedBits,	const unsigned char *pressedPausedBits,	BMessage *invokeMessage, uint32 key, uint32 modifiers, uint32 resizeFlags)	:	TransportButton(frame, name, normalBits, pressedBits,			disabledBits, invokeMessage, 0,			0, 0, 0, key, modifiers, resizeFlags),		normalPlayingBits(normalPlayingBits),		pressedPlayingBits(pressedPlayingBits),		normalPausedBits(normalPausedBits),		pressedPausedBits(pressedPausedBits),		state(PlayPauseButton::kStopped),		lastPauseBlinkTime(0),		lastModeMask(0){}void PlayPauseButton::SetStopped(){	if (state == kStopped || state == kAboutToPlay)		return;		state = kStopped;	Invalidate();}void PlayPauseButton::SetPlaying(){	if (state == kPlaying || state == kAboutToPause)		return;		state = kPlaying;	Invalidate();}const bigtime_t kPauseBlinkPeriod = 600000;void PlayPauseButton::SetPaused(){	if (state == kAboutToPlay)		return;	// in paused state blink the LED on and off	bigtime_t now = system_time();	if (state == kPausedLedOn || state == kPausedLedOff) {		if (now - lastPauseBlinkTime < kPauseBlinkPeriod)			return;				if (state == kPausedLedOn)			state = kPausedLedOff;		else			state = kPausedLedOn;	} else		state = kPausedLedOn;		lastPauseBlinkTime = now;	Invalidate();}uint32 PlayPauseButton::ModeMask() const{	if (!IsEnabled())		return kDisabledMask;		uint32 result = 0;	if (Value())		result = kPressedMask;	if (state == kPlaying || state == kAboutToPlay)		result |= kPlayingMask;	else if (state == kAboutToPause || state == kPausedLedOn)				result |= kPausedMask;		return result;}const unsigned char *PlayPauseButton::BitsForMask(uint32 mask) const{	switch (mask) {		case kPlayingMask:			return normalPlayingBits;		case kPlayingMask | kPressedMask:			return pressedPlayingBits;		case kPausedMask:			return normalPausedBits;		case kPausedMask | kPressedMask:			return pressedPausedBits;		default:			return _inherited::BitsForMask(mask);	}		TRESPASS();	return 0;}void PlayPauseButton::StartPressing(){	if (state == kPlaying)		state = kAboutToPause;	else	 	state = kAboutToPlay;		_inherited::StartPressing();}void PlayPauseButton::MouseCancelPressing(){	if (state == kAboutToPause)	 	state = kPlaying;	else		state = kStopped;		_inherited::MouseCancelPressing();}void PlayPauseButton::DonePressing(){	if (state == kAboutToPause) {	 	state = kPausedLedOn;		lastPauseBlinkTime = system_time();	} else if (state == kAboutToPlay)		state = kPlaying;		_inherited::DonePressing();}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -