#pragma region CPL License
/*
Nuclex Native Framework
Copyright (C) 2002-2013 Nuclex Development Labs
This library is free software; you can redistribute it and/or
modify it under the terms of the IBM Common Public License as
published by the IBM Corporation; either version 1.0 of the
License, or (at your option) any later version.
This library 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
IBM Common Public License for more details.
You should have received a copy of the IBM Common Public
License along with this library
*/
#pragma endregion // CPL License
#ifndef NUCLEX_INPUT_DEVICES_VIRTUALMOUSE_H
#define NUCLEX_INPUT_DEVICES_VIRTUALMOUSE_H
#include "Nuclex/Input/Devices/Mouse.h"
#include "Nuclex/Input/Devices/MouseButtons.h"
namespace Nuclex { namespace Input { namespace Devices {
/// Forwards mouse input from an exchangeable backing device
///
///
/// If this library directly dealt out instances of the input device implementations,
/// disconnecting a device and connecting another one, for example, would mean that
/// any pointers the user has to the disconnected device become either invalid.
///
///
/// So the design choice was to either let the library's user in on when devices are
/// replaced, forcing him to unsubscribe from events, resubscribe, replace pointers
/// he has stored to the old device and so on, or to use a forwarder device that
/// allows the underlying real input device to be replaced at will without anyone
/// outside of the library noticing.
///
///
/// Without a forwarding device assigned, this class can also be used as a dummy
/// device to fill slots for devices not available or not supported by the current
/// system (think keyboard on iPhone, etc.)
///
///
class VirtualMouse : public Mouse, public sigslot::has_slots<> {
/// Initializes a new virtual mouse
public: VirtualMouse() :
forwardingMouse(nullptr) {
this->neutralState.Reset();
}
/// Destroys the virtual mouse
public: virtual ~VirtualMouse() {
if(this->forwardingMouse != nullptr) {
unsubscribe(this->forwardingMouse);
}
}
/// Assigns the mouse for which this instance forwards input
/// Mouse for which input will be forwarded
public: void SetForwardingMouse(Mouse *forwardingMouse) {
if(this->forwardingMouse != nullptr) {
unsubscribe(this->forwardingMouse);
}
this->forwardingMouse = forwardingMouse;
if(this->forwardingMouse != nullptr) {
subscribe(this->forwardingMouse);
}
}
/// Whether the input device is currently attached
/// True if the input device is attached, otherwise false
public: virtual bool IsAttached() const {
if(this->forwardingMouse == nullptr) {
return false;
} else {
return this->forwardingMouse->IsAttached();
}
}
/// Retrieves the human-readable name of the input device
/// The human-readable name of the input device
public: virtual const std::string &GetName() const {
static std::string notConnected("No mouse connected");
if(this->forwardingMouse == nullptr) {
return notConnected;
} else {
return this->forwardingMouse->GetName();
}
}
/// Retrieves the current state of the input device
/// The input device's current state
public: virtual const MouseState &GetState() const {
if(this->forwardingMouse == nullptr) {
return this->neutralState;
} else {
return this->forwardingMouse->GetState();
}
}
/// Updates the state of the input device
protected: virtual void Update() {
if(this->forwardingMouse != nullptr) {
this->forwardingMouse->Update();
}
}
/// Takes a snapshot of the input device's current state
protected: virtual void TakeSnapshot() {
if(this->forwardingMouse != nullptr) {
this->forwardingMouse->TakeSnapshot();
}
}
/// Removes all snapshots the device has taken
protected: virtual void ClearSnapshots() {
if(this->forwardingMouse != nullptr) {
this->forwardingMouse->ClearSnapshots();
}
}
/// Subscribes to the events of the forwarding mouse
/// Mouse to whose events to subscribe
private: void subscribe(Mouse *mouse) {
mouse->CursorMoved.connect(this, &VirtualMouse::onCursorMoved);
mouse->Moved.connect(this, &VirtualMouse::onMoved);
mouse->ButtonPressed.connect(this, &VirtualMouse::onButtonPressed);
mouse->ButtonReleased.connect(this, &VirtualMouse::onButtonReleased);
mouse->WheelRotated.connect(this, &VirtualMouse::onWheelRotated);
}
/// Unsubscribes from the events of the forwarding mouse
/// Mouse from whose events to unsubscribe
private: void unsubscribe(Mouse *mouse) {
mouse->WheelRotated.disconnect(this);
mouse->ButtonReleased.disconnect(this);
mouse->ButtonPressed.disconnect(this);
mouse->Moved.disconnect(this);
mouse->CursorMoved.disconnect(this);
}
/// Forwards a cursor movement notification to the library user
/// New X coordinate of the mouse cursor
/// New Y coordinate of the mouse cursor
private: void onCursorMoved(int x, int y) {
CursorMoved(x, y);
}
/// Forwards a mouse move notification to the library user
/// Units by which the mouse was moved on the X axis
/// Units by which the mouse was moved on the Y axis
private: void onMoved(float deltaX, float deltaY) {
Moved(deltaX, deltaY);
}
/// Forwards a mouse press notification to the library user
/// Mouse button the user has pressed
private: void onButtonPressed(MouseButtons::Enum button) {
ButtonPressed(button);
}
/// Forwards a mouse release notification to the library user
/// Mouse button the user has released
private: void onButtonReleased(MouseButtons::Enum button) {
ButtonReleased(button);
}
/// Forwards a wheel rotation notification to the library user
/// Ticks by which the mouse wheel has been rotated
private: void onWheelRotated(float wheelDelta) {
WheelRotated(wheelDelta);
}
/// Disabled copy constructor for the virtual mouse
private: VirtualMouse(const VirtualMouse &);
/// Disabled assignment operator for the virtual mouse
private: void operator =(const VirtualMouse &);
/// Mouse that is forwarded by this instance
private: Mouse *forwardingMouse;
/// Neutral state that is returned when no mouse is connected
private: MouseState neutralState;
};
}}} // namespace Nuclex::Input::Devices
#endif // NUCLEX_INPUT_DEVICES_VIRTUALMOUSE_H