Port window-manager to React (#174)

This commit is contained in:
Jordan Eldredge 2016-07-31 17:18:12 -07:00 committed by GitHub
parent c5caa3cbf6
commit a87c5cfaf0
5 changed files with 121 additions and 109 deletions

77
js/DraggableWindow.jsx Normal file
View file

@ -0,0 +1,77 @@
import {cloneElement, Children, Component} from 'react';
// Many of the ideas of how to build this as a React componant were stolen
// from: https://github.com/mzabriskie/react-draggable Thanks! @mzabriskie
class DraggableWindow extends Component {
constructor(props) {
super(props);
this.handleMouseDown = this.handleMouseDown.bind(this);
this.state = {};
}
handleMouseDown(e) {
if (!e.target.classList.contains(this.props.handleClass)) {
// Prevent going into drag mode when clicking any of the title
// bar's icons by making sure the click was made directly on the
// handle
return true;
}
// If the element was 'absolutely' positioned we could simply use
// offsetLeft / offsetTop however the element is 'relatively'
// positioned so we're using style.left. parseInt is used to remove the
// 'px' postfix from the value
const winStart = {
left: parseInt(this.body.offsetLeft || 0, 10),
top: parseInt(this.body.offsetTop || 0, 10)
};
// Get starting mouse position
const mouseStart = {
left: e.clientX,
top: e.clientY
};
// Mouse move handler function while mouse is down
const handleMove = (moveEvent) => {
// Calculate difference offsets between current and starting positions
const diff = {
left: moveEvent.clientX - mouseStart.left,
top: moveEvent.clientY - mouseStart.top
};
// These margins were only useful for centering the div, now we
// don't need them
this.setState({
marginLeft: '0px',
marginTop: '0px',
left: `${winStart.left + diff.left}px`,
top: `${winStart.top + diff.top}px`,
position: 'absolute'
});
};
// Mouse button up
function handleUp() {
removeListeners();
}
function removeListeners() {
window.removeEventListener('mousemove', handleMove);
window.removeEventListener('mouseup', handleUp);
}
window.addEventListener('mousemove', handleMove);
window.addEventListener('mouseup', handleUp);
return false;
}
render() {
return cloneElement(Children.only(this.props.children), {
ref: (body) => this.body = body,
onMouseDown: this.handleMouseDown,
style: {...this.props.children.props, ...this.state}
});
}
}
module.exports = DraggableWindow;

View file

@ -8,6 +8,7 @@ import Close from './Close.jsx';
import ClutterBar from './ClutterBar.jsx';
import ContextMenu from './ContextMenu.jsx';
import DragTarget from './DragTarget.jsx';
import DraggableWindow from './DraggableWindow.jsx';
import Eject from './Eject.jsx';
import Kbps from './Kbps.jsx';
import Khz from './Khz.jsx';
@ -45,44 +46,51 @@ const MainWindow = (props) => {
props.winamp.loadFromFileReference(files[0]);
};
// NOTE: DragTarget but be outside Draggable Window, since currently
// DragTarget creates a wrapper DOM element which, since main-window is
// absolutely positioned, exists at a different location than the main
// window. Drag/Drop still work, because events propogate up to parent
// elements.
return <DragTarget handleFiles={handleDrop}>
<div id='main-window' className={className}>
<div id='loading'>Loading...</div>
<div id='title-bar' className='selected'>
<ContextMenu mediaPlayer={props.mediaPlayer} winamp={props.winamp} />
<ShadeTime />
<div id='minimize'></div>
<Shade />
<Close />
<DraggableWindow handleClass='title-bar'>
<div id='main-window' className={className}>
<div id='loading'>Loading...</div>
<div id='title-bar' className='selected title-bar'>
<ContextMenu mediaPlayer={props.mediaPlayer} winamp={props.winamp} />
<ShadeTime />
<div id='minimize'></div>
<Shade />
<Close />
</div>
<div className='status'>
<ClutterBar />
<div id='play-pause'></div>
<div id='work-indicator' className={props.display.working ? 'selected' : ''}></div>
<Time />
<Visualizer />
</div>
<div className='media-info'>
<Marquee />
<Kbps />
<Khz />
<MonoStereo />
</div>
<Volume />
<Balance />
<div className='windows'>
<div id='equalizer-button'></div>
<div id='playlist-button'></div>
</div>
<Position mediaPlayer={props.mediaPlayer} />
<Actions mediaPlayer={props.mediaPlayer} />
<Eject />
<div className='shuffle-repeat'>
<Shuffle />
<Repeat />
</div>
<a id='about' target='blank' href='https://github.com/captbaritone/winamp2-js'></a>
</div>
<div className='status'>
<ClutterBar />
<div id='play-pause'></div>
<div id='work-indicator' className={props.display.working ? 'selected' : ''}></div>
<Time />
<Visualizer />
</div>
<div className='media-info'>
<Marquee />
<Kbps />
<Khz />
<MonoStereo />
</div>
<Volume />
<Balance />
<div className='windows'>
<div id='equalizer-button'></div>
<div id='playlist-button'></div>
</div>
<Position mediaPlayer={props.mediaPlayer} />
<Actions mediaPlayer={props.mediaPlayer} />
<Eject />
<div className='shuffle-repeat'>
<Shuffle />
<Repeat />
</div>
<a id='about' target='blank' href='https://github.com/captbaritone/winamp2-js'></a>
</div>
</DraggableWindow>
</DragTarget>;
};

View file

@ -1,7 +0,0 @@
module.exports = {
init: function() {
this.handle = document.getElementById('title-bar');
this.body = document.getElementById('main-window');
return this;
}
};

View file

@ -1,6 +1,4 @@
// UI and App logic
import MainWindow from './main-window';
import WindowManager from './window-manager';
import Skin from './skin';
import Media from './media';
import MyFile from './my-file';
@ -14,12 +12,9 @@ module.exports = {
this.fileInput.type = 'file';
this.fileInput.style.display = 'none';
this.windowManager = WindowManager;
this.skin = Skin.init(document.getElementById('visualizer'), this.media._analyser);
this.state = '';
this.mainWindow = MainWindow.init(this);
this.events = {
timeUpdated: new Event('timeUpdated')
};
@ -36,8 +31,6 @@ module.exports = {
},
_registerListeners: function() {
this.windowManager.registerWindow(this.mainWindow);
this.media.addEventListener('timeupdate', () => {
this.dispatch({type: 'UPDATE_TIME_ELAPSED', elapsed: this.media.timeElapsed()});
// Legacy

View file

@ -1,59 +0,0 @@
module.exports = {
registerWindow: function(win) {
var body = win.body;
var handle = win.handle;
// Make window dragable
handle.addEventListener('mousedown', function(e){
if (e.target !== this) {
// Prevent going into drag mode when clicking any of the title
// bar's icons by making sure the click was made directly on the
// titlebar
return true;
}
// If the element was 'absolutely' positioned we could simply use
// offsetLeft / offsetTop however the element is 'relatively'
// positioned so we're using style.left. parseInt is used to remove the
// 'px' postfix from the value
var winStartLeft = parseInt(body.offsetLeft || 0, 10),
winStartTop = parseInt(body.offsetTop || 0, 10);
// Get starting mouse position
var mouseStartLeft = e.clientX,
mouseStartTop = e.clientY;
// Mouse move handler function while mouse is down
function handleMove(moveEvent) {
// Get current mouse position
var mouseLeft = moveEvent.clientX,
mouseTop = moveEvent.clientY;
// Calculate difference offsets
var diffLeft = mouseLeft - mouseStartLeft,
diffTop = mouseTop - mouseStartTop;
// These margins were only useful for centering the div, now we
// don't need them
body.style.marginLeft = '0px';
body.style.marginTop = '0px';
// Move window to new position
body.style.left = (winStartLeft + diffLeft) + 'px';
body.style.top = (winStartTop + diffTop) + 'px';
}
// Mouse button up
function handleUp() {
removeListeners();
}
function removeListeners() {
window.removeEventListener('mousemove', handleMove);
window.removeEventListener('mouseup', handleUp);
}
window.addEventListener('mousemove', handleMove);
window.addEventListener('mouseup', handleUp);
});
}
};