001/* [{
002Copyright 2007, 2008 Nicolas Carranza <nicarran at gmail.com>
003
004This file is part of jpen.
005
006jpen is free software: you can redistribute it and/or modify
007it under the terms of the GNU Lesser General Public License as published by
008the Free Software Foundation, either version 3 of the License,
009or (at your option) any later version.
010
011jpen is distributed in the hope that it will be useful,
012but WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014GNU Lesser General Public License for more details.
015
016You should have received a copy of the GNU Lesser General Public License
017along with jpen.  If not, see <http://www.gnu.org/licenses/>.
018}] */
019package jpen.provider.system;
020
021import java.awt.Component;
022import java.awt.event.MouseAdapter;
023import java.awt.event.MouseEvent;
024import java.awt.event.MouseListener;
025import java.awt.event.MouseMotionListener;
026import java.awt.event.MouseWheelEvent;
027import java.awt.event.MouseWheelListener;
028import java.awt.Point;
029import java.lang.ref.WeakReference;
030import java.util.Arrays;
031import java.util.Collection;
032import java.util.Collections;
033import java.util.List;
034import java.util.logging.Level;
035import java.util.logging.Logger;
036import jpen.PButton;
037import jpen.PButtonEvent;
038import jpen.PenDevice;
039import jpen.PenEvent;
040import jpen.PenManager;
041import jpen.PenProvider;
042import jpen.PLevel;
043import jpen.PLevelEvent;
044import jpen.provider.AbstractPenDevice;
045import jpen.PScroll;
046import jpen.PScrollEvent;
047
048@SuppressWarnings("deprecation")
049public final class MouseDevice
050        extends AbstractPenDevice {
051        private static final Logger L=Logger.getLogger(MouseDevice.class.getName());
052        //static {L.setLevel(Level.ALL);        }
053
054        private final MouseListener mouseL=new MouseAdapter() {
055                                @Override
056                                public void mousePressed(MouseEvent ev) {
057                                        scheduleMove(ev);
058                                        mouseButtonChanged(ev, true);
059                                }
060
061                                @Override
062                                public void mouseReleased(MouseEvent ev) {
063                                        scheduleMove(ev);
064                                        mouseButtonChanged(ev, false);
065                                }
066                        };
067        private final MouseMotionListener mouseMotionL=new MouseMotionListener(){
068                                //@Override
069                                public void mouseMoved(MouseEvent ev) {
070                                        scheduleMove(ev);
071                                }
072                                //@Override
073                                public void mouseDragged(MouseEvent ev) {
074                                        scheduleMove(ev);
075                                }
076                        };
077        private final MouseWheelListener mouseWheelL=new MouseWheelListener(){
078                                //@Override
079                                public void mouseWheelMoved(MouseWheelEvent ev) {
080                                        if(!getEnabled())
081                                                return;
082                                        int value=ev.getWheelRotation();
083                                        PScroll.Type type=PScroll.Type.DOWN;
084                                        if(value<0) {
085                                                type=PScroll.Type.UP;
086                                                value=-value;
087                                        }
088                                        if(ev.getScrollType()==ev.WHEEL_UNIT_SCROLL && ev.getScrollAmount()>0) // > 0 : is because windows bug workaround, sometimes it is 0.
089                                                value*=ev.getScrollAmount();
090                                        getPenManager().scheduleScrollEvent(MouseDevice.this, ev.getWhen(), new PScroll(type.ordinal(), value));
091                                }
092                        };
093        private final SystemProvider systemProvider;
094        private WeakReference<Component> activeComponentRef;
095
096        MouseDevice(SystemProvider systemProvider) {
097                super(systemProvider);
098                this.systemProvider=systemProvider;
099                setEnabled(true);
100        }
101
102        //@Override
103        public String getName() {
104                return "Mouse";
105        }
106
107        @Override
108        public boolean getUseFractionalMovements(){
109                return false;
110        }
111
112        void setPaused(boolean paused) {
113                Component activeComponent=activeComponentRef==null? null:activeComponentRef.get();
114                activeComponentRef=null;
115                if(activeComponent!=null){
116                        activeComponent.removeMouseListener(mouseL);
117                        activeComponent.removeMouseMotionListener(mouseMotionL);
118                        activeComponent.removeMouseWheelListener(mouseWheelL);
119                }
120                if(!paused){
121                        activeComponent=systemProvider.componentPenOwner.getActiveComponent();
122                        if(activeComponent!=null){
123                                activeComponent.addMouseListener(mouseL);
124                                activeComponent.addMouseMotionListener(mouseMotionL);
125                                activeComponent.addMouseWheelListener(mouseWheelL);
126                                activeComponentRef=new WeakReference<Component>(activeComponent);
127                        }
128                }
129        }
130
131        private void scheduleMove(MouseEvent ev){
132                if(!getEnabled())
133                        return;
134                scheduleMove(ev.getWhen(), ev.getX(), ev.getY());
135        }
136
137        private final PLevel[] changedLevelsA=new PLevel[2];
138        private final List<PLevel> changedLevels=Arrays.asList(changedLevelsA);
139
140        private void scheduleMove(long time, int x, int y) {
141                changedLevelsA[0]=new PLevel(PLevel.Type.X.ordinal(), x);
142                changedLevelsA[1]=new PLevel(PLevel.Type.Y.ordinal(), y);
143                getPenManager().scheduleLevelEvent(this, time, changedLevels, false);
144        }
145
146        private void mouseButtonChanged(MouseEvent ev, boolean state) {
147                if(!getEnabled())
148                        return;
149                PButton.Type buttonType=getButtonType(ev.getButton());
150                if(buttonType==null)
151                        return;
152                if(L.isLoggable(Level.FINE))
153                        L.fine("scheduling button event: "+buttonType+", "+state);
154                getPenManager().scheduleButtonEvent(this, ev.getWhen(), new PButton(buttonType.ordinal(), state));
155        }
156
157        private static PButton.Type getButtonType(int buttonNumber) {
158                switch(buttonNumber) {
159                case MouseEvent.BUTTON1:
160                        return PButton.Type.LEFT;
161                case MouseEvent.BUTTON2:
162                        return PButton.Type.CENTER;
163                case MouseEvent.BUTTON3:
164                        return PButton.Type.RIGHT;
165                }
166                return null;
167        }
168}